1
0
Fork 0
mirror of https://github.com/librespot-org/librespot.git synced 2025-10-03 09:49:31 +02:00

Mark unrelated parsing error as warning (#1491)

* mark known parsing error as warning

* add copilot suggestion

* adjust unknown enum handling for json
This commit is contained in:
Felix Prillwitz 2025-05-03 23:39:07 +02:00 committed by GitHub
parent d12e1b8549
commit e2c3ac3146
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 36 additions and 22 deletions

View file

@ -4,7 +4,7 @@ use crate::{
authentication::Credentials, authentication::Credentials,
dealer::{ dealer::{
manager::{BoxedStream, BoxedStreamResult, Reply, RequestReply}, manager::{BoxedStream, BoxedStreamResult, Reply, RequestReply},
protocol::{Command, Message, Request}, protocol::{Command, FallbackWrapper, Message, Request},
}, },
session::UserAttributes, session::UserAttributes,
Error, Session, SpotifyId, Error, Session, SpotifyId,
@ -81,7 +81,7 @@ struct SpircTask {
connect_state_volume_update: BoxedStreamResult<SetVolumeCommand>, connect_state_volume_update: BoxedStreamResult<SetVolumeCommand>,
connect_state_logout_request: BoxedStreamResult<LogoutCommand>, connect_state_logout_request: BoxedStreamResult<LogoutCommand>,
playlist_update: BoxedStreamResult<PlaylistModificationInfo>, playlist_update: BoxedStreamResult<PlaylistModificationInfo>,
session_update: BoxedStreamResult<SessionUpdate>, session_update: BoxedStreamResult<FallbackWrapper<SessionUpdate>>,
connect_state_command: BoxedStream<RequestReply>, connect_state_command: BoxedStream<RequestReply>,
user_attributes_update: BoxedStreamResult<UserAttributesUpdate>, user_attributes_update: BoxedStreamResult<UserAttributesUpdate>,
user_attributes_mutation: BoxedStreamResult<UserAttributesMutation>, user_attributes_mutation: BoxedStreamResult<UserAttributesMutation>,
@ -191,7 +191,7 @@ impl Spirc {
let session_update = session let session_update = session
.dealer() .dealer()
.listen_for("social-connect/v2/session_update", Message::from_json)?; .listen_for("social-connect/v2/session_update", Message::try_from_json)?;
let user_attributes_update = session let user_attributes_update = session
.dealer() .dealer()
@ -1552,7 +1552,24 @@ impl SpircTask {
Ok(()) Ok(())
} }
fn handle_session_update(&mut self, mut session_update: SessionUpdate) { fn handle_session_update(&mut self, session_update: FallbackWrapper<SessionUpdate>) {
// we know that this enum value isn't present in our current proto definitions, by that
// the json parsing fails because the enum isn't known as proto representation
const WBC: &str = "WIFI_BROADCAST_CHANGED";
let mut session_update = match session_update {
FallbackWrapper::Inner(update) => update,
FallbackWrapper::Fallback(value) => {
let fallback_inner = value.to_string();
if fallback_inner.contains(WBC) {
log::debug!("Received SessionUpdate::{WBC}");
} else {
log::warn!("SessionUpdate couldn't be parse correctly: {value:?}");
}
return;
}
};
let reason = session_update.reason.enum_value(); let reason = session_update.reason.enum_value();
let mut session = match session_update.session.take() { let mut session = match session_update.session.take() {

View file

@ -357,7 +357,7 @@ impl DealerShared {
} }
} }
warn!("No subscriber for msg.uri: {}", msg.uri); debug!("No subscriber for msg.uri: {}", msg.uri);
} }
fn dispatch_request( fn dispatch_request(

View file

@ -5,9 +5,8 @@ pub use request::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::{Error as IoError, Read}; use std::io::{Error as IoError, Read};
use crate::Error; use crate::{deserialize_with::json_proto, Error};
use base64::prelude::BASE64_STANDARD; use base64::{prelude::BASE64_STANDARD, DecodeError, Engine};
use base64::{DecodeError, Engine};
use flate2::read::GzDecoder; use flate2::read::GzDecoder;
use log::LevelFilter; use log::LevelFilter;
use serde::Deserialize; use serde::Deserialize;
@ -99,17 +98,19 @@ pub struct Message {
pub uri: String, pub uri: String,
} }
#[derive(Deserialize)]
#[serde(untagged)]
pub enum FallbackWrapper<T: protobuf::MessageFull> {
Inner(#[serde(deserialize_with = "json_proto")] T),
Fallback(JsonValue),
}
impl Message { impl Message {
pub fn from_json<M: protobuf::MessageFull>(value: Self) -> Result<M, Error> { pub fn try_from_json<M: protobuf::MessageFull>(
use protobuf_json_mapping::*; value: Self,
) -> Result<FallbackWrapper<M>, Error> {
match value.payload { match value.payload {
PayloadValue::Json(json) => match parse_from_str::<M>(&json) { PayloadValue::Json(json) => Ok(serde_json::from_str(&json)?),
Ok(message) => Ok(message),
Err(_) => match parse_from_str_with_options(&json, &IGNORE_UNKNOWN) {
Ok(message) => Ok(message),
Err(why) => Err(Error::failed_precondition(why)),
},
},
other => Err(ProtocolError::UnexpectedData(other).into()), other => Err(ProtocolError::UnexpectedData(other).into()),
} }
} }

View file

@ -35,11 +35,7 @@ where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let v: Value = Deserialize::deserialize(de)?; let v: Value = Deserialize::deserialize(de)?;
parse_value_to_msg(&v).map_err(|why| { parse_value_to_msg(&v).map_err(Error::custom)
warn!("deserialize_json_proto: {v}");
error!("deserialize_json_proto: {why}");
Error::custom(why)
})
} }
pub fn option_json_proto<'de, T, D>(de: D) -> Result<Option<T>, D::Error> pub fn option_json_proto<'de, T, D>(de: D) -> Result<Option<T>, D::Error>