librespot_core/
deserialize_with.rs

1use 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}