librespot_core/
deserialize_with.rs1use base64::Engine;
2use base64::prelude::BASE64_STANDARD;
3use protobuf::MessageFull;
4use serde::de::{Error, Unexpected};
5use serde::{Deserialize, Deserializer};
6use serde_json::Value;
7
8const IGNORE_UNKNOWN: protobuf_json_mapping::ParseOptions = protobuf_json_mapping::ParseOptions {
9 ignore_unknown_fields: true,
10 _future_options: (),
11};
12
13fn parse_value_to_msg<T: MessageFull>(
14 value: &Value,
15) -> Result<T, protobuf_json_mapping::ParseError> {
16 protobuf_json_mapping::parse_from_str_with_options::<T>(&value.to_string(), &IGNORE_UNKNOWN)
17}
18
19pub fn base64_proto<'de, T, D>(de: D) -> Result<Option<T>, D::Error>
20where
21 T: MessageFull,
22 D: Deserializer<'de>,
23{
24 let v: String = Deserialize::deserialize(de)?;
25 let bytes = BASE64_STANDARD
26 .decode(v)
27 .map_err(|e| Error::custom(e.to_string()))?;
28
29 T::parse_from_bytes(&bytes).map(Some).map_err(Error::custom)
30}
31
32pub fn json_proto<'de, T, D>(de: D) -> Result<T, D::Error>
33where
34 T: MessageFull,
35 D: Deserializer<'de>,
36{
37 let v: Value = Deserialize::deserialize(de)?;
38 parse_value_to_msg(&v).map_err(Error::custom)
39}
40
41pub fn option_json_proto<'de, T, D>(de: D) -> Result<Option<T>, D::Error>
42where
43 T: MessageFull,
44 D: Deserializer<'de>,
45{
46 let v: Value = Deserialize::deserialize(de)?;
47 parse_value_to_msg(&v).map(Some).map_err(Error::custom)
48}
49
50pub fn vec_json_proto<'de, T, D>(de: D) -> Result<Vec<T>, D::Error>
51where
52 T: MessageFull,
53 D: Deserializer<'de>,
54{
55 let v: Value = Deserialize::deserialize(de)?;
56 let array = match v {
57 Value::Array(array) => array,
58 _ => return Err(Error::custom("the value wasn't an array")),
59 };
60
61 let res = array
62 .iter()
63 .flat_map(parse_value_to_msg)
64 .collect::<Vec<T>>();
65
66 Ok(res)
67}
68
69pub fn boxed<'de, T, D>(de: D) -> Result<Box<T>, D::Error>
70where
71 T: Deserialize<'de>,
72 D: Deserializer<'de>,
73{
74 let v: T = Deserialize::deserialize(de)?;
75 Ok(Box::new(v))
76}
77
78pub fn bool_from_string<'de, D>(de: D) -> Result<bool, D::Error>
79where
80 D: Deserializer<'de>,
81{
82 match String::deserialize(de)?.as_ref() {
83 "true" => Ok(true),
84 "false" => Ok(false),
85 other => Err(Error::invalid_value(
86 Unexpected::Str(other),
87 &"true or false",
88 )),
89 }
90}