pbjson_types/
value.rs

1pub use crate::pb::google::protobuf::value::Kind;
2
3use alloc::string::String;
4use alloc::vec::Vec;
5
6use serde::{
7    de::{self, MapAccess, SeqAccess},
8    ser, Deserialize, Deserializer, Serialize, Serializer,
9};
10
11macro_rules! from {
12    ($($typ: ty [$id:ident] => {$($from_type:ty => $exp:expr),+ $(,)?})+) => {
13        $($(
14            impl From<$from_type> for $typ {
15                #[allow(unused_variables)]
16                fn from($id: $from_type) -> Self {
17                    $exp
18                }
19            }
20        )+)+
21    }
22}
23
24from! {
25    crate::Value[value] => {
26        &'static str => Kind::from(value).into(),
27        () => Kind::NullValue(0).into(),
28        Kind => Self { kind: Some(value) },
29        Option<Kind> => Self { kind: value },
30        String => Kind::from(value).into(),
31        Vec<Self> => Kind::from(value).into(),
32        bool => Kind::from(value).into(),
33        crate::ListValue => Kind::from(value).into(),
34        crate::Struct => Kind::from(value).into(),
35        f64 => Kind::from(value).into(),
36    }
37
38    Kind[value] => {
39        &'static str => Self::StringValue(value.into()),
40        () => Self::NullValue(0),
41        String => Self::StringValue(value),
42        Vec<crate::Value> => Self::ListValue(value.into()),
43        bool => Self::BoolValue(value),
44        crate::ListValue => Self::ListValue(value),
45        crate::Struct => Self::StructValue(value),
46        f64 => Self::NumberValue(value),
47    }
48}
49
50#[cfg(feature = "std")]
51from! {
52    crate::Value[value] => {
53        std::collections::HashMap<String, Self> => Kind::from(value).into(),
54    }
55
56    Kind[value] => {
57        std::collections::HashMap<String, crate::Value> => Self::StructValue(value.into()),
58    }
59}
60
61#[cfg(not(feature = "std"))]
62from! {
63    crate::Value[value] => {
64        alloc::collections::BTreeMap<String, Self> => Kind::from(value).into(),
65    }
66
67    Kind[value] => {
68        alloc::collections::BTreeMap<String, crate::Value> => Self::StructValue(value.into()),
69    }
70}
71
72impl<const N: usize> From<[Self; N]> for crate::Value {
73    fn from(value: [Self; N]) -> Self {
74        crate::ListValue::from(value).into()
75    }
76}
77
78impl Serialize for crate::Value {
79    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
80    where
81        S: Serializer,
82    {
83        self.kind.serialize(ser)
84    }
85}
86
87impl<'de> Deserialize<'de> for crate::Value {
88    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
89    where
90        D: Deserializer<'de>,
91    {
92        Ok(Self {
93            kind: <_>::deserialize(deserializer)?,
94        })
95    }
96}
97
98impl Serialize for Kind {
99    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
100    where
101        S: Serializer,
102    {
103        match self {
104            Self::NullValue(_) => ().serialize(ser),
105            Self::StringValue(value) => value.serialize(ser),
106            Self::BoolValue(value) => value.serialize(ser),
107            Self::StructValue(value) => value.serialize(ser),
108            Self::ListValue(list) => list.serialize(ser),
109            Self::NumberValue(value) => {
110                // Kind does not allow NaN's or Infinity as they are
111                // indistinguishable from strings.
112                if value.is_nan() {
113                    Err(ser::Error::custom(
114                        "Cannot serialize NaN as google.protobuf.Value.number_value",
115                    ))
116                } else if value.is_infinite() {
117                    Err(ser::Error::custom(
118                        "Cannot serialize infinity as google.protobuf.Value.number_value",
119                    ))
120                } else {
121                    value.serialize(ser)
122                }
123            }
124        }
125    }
126}
127
128impl<'de> Deserialize<'de> for Kind {
129    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
130    where
131        D: Deserializer<'de>,
132    {
133        deserializer.deserialize_any(KindVisitor)
134    }
135}
136
137struct KindVisitor;
138
139impl<'de> serde::de::Visitor<'de> for KindVisitor {
140    type Value = Kind;
141
142    fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
143        formatter.write_str("google.protobuf.Value")
144    }
145
146    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
147    where
148        E: de::Error,
149    {
150        Ok(Kind::BoolValue(v))
151    }
152
153    fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
154    where
155        E: de::Error,
156    {
157        Ok(Kind::NumberValue(v.into()))
158    }
159
160    fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
161    where
162        E: de::Error,
163    {
164        Ok(Kind::NumberValue(v.into()))
165    }
166
167    fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
168    where
169        E: de::Error,
170    {
171        Ok(Kind::NumberValue(v.into()))
172    }
173
174    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
175    where
176        E: de::Error,
177    {
178        if v > -(1 << f64::MANTISSA_DIGITS) && v < 1 << f64::MANTISSA_DIGITS {
179            return Ok(Kind::NumberValue(v as f64));
180        }
181
182        Err(de::Error::custom(
183            "out of range integral type conversion attempted",
184        ))
185    }
186
187    fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
188    where
189        E: de::Error,
190    {
191        self.visit_i64(v.try_into().map_err(de::Error::custom)?)
192    }
193
194    fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
195    where
196        E: de::Error,
197    {
198        Ok(Kind::NumberValue(v.into()))
199    }
200
201    fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
202    where
203        E: de::Error,
204    {
205        Ok(Kind::NumberValue(v.into()))
206    }
207
208    fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
209    where
210        E: de::Error,
211    {
212        Ok(Kind::NumberValue(v.into()))
213    }
214
215    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
216    where
217        E: de::Error,
218    {
219        if v < 1 << f64::MANTISSA_DIGITS {
220            return Ok(Kind::NumberValue(v as f64));
221        }
222
223        Err(de::Error::custom(
224            "out of range integral type conversion attempted",
225        ))
226    }
227
228    fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
229    where
230        E: de::Error,
231    {
232        self.visit_u64(v.try_into().map_err(de::Error::custom)?)
233    }
234
235    fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
236    where
237        E: de::Error,
238    {
239        Ok(Kind::NumberValue(v.into()))
240    }
241
242    fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
243    where
244        E: de::Error,
245    {
246        Ok(Kind::NumberValue(v))
247    }
248
249    fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
250    where
251        E: de::Error,
252    {
253        Ok(Kind::StringValue(v.into()))
254    }
255
256    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
257    where
258        E: de::Error,
259    {
260        Ok(Kind::StringValue(v.into()))
261    }
262
263    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
264    where
265        E: de::Error,
266    {
267        Ok(Kind::StringValue(v.into()))
268    }
269
270    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
271    where
272        E: de::Error,
273    {
274        Ok(Kind::StringValue(v))
275    }
276
277    fn visit_none<E>(self) -> Result<Self::Value, E>
278    where
279        E: de::Error,
280    {
281        Ok(Kind::NullValue(0))
282    }
283
284    fn visit_some<D>(self, de: D) -> Result<Self::Value, D::Error>
285    where
286        D: Deserializer<'de>,
287    {
288        Deserialize::deserialize(de)
289    }
290
291    fn visit_unit<E>(self) -> Result<Self::Value, E>
292    where
293        E: de::Error,
294    {
295        Ok(Kind::NullValue(0))
296    }
297
298    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
299    where
300        A: SeqAccess<'de>,
301    {
302        let mut list = Vec::new();
303
304        while let Some(value) = seq.next_element()? {
305            list.push(value);
306        }
307
308        Ok(Kind::ListValue(list.into()))
309    }
310
311    fn visit_map<A>(self, mut map_access: A) -> Result<Self::Value, A::Error>
312    where
313        A: MapAccess<'de>,
314    {
315        #[cfg(feature = "std")]
316        let mut map = std::collections::HashMap::new();
317
318        #[cfg(not(feature = "std"))]
319        let mut map = alloc::collections::BTreeMap::new();
320
321        while let Some((key, value)) = map_access.next_entry()? {
322            map.insert(key, value);
323        }
324
325        Ok(Kind::StructValue(map.into()))
326    }
327}
328
329#[cfg(test)]
330mod tests {
331    use crate::Value;
332
333    #[test]
334    fn boolean() {
335        assert_eq!(
336            serde_json::to_value(Value::from(false)).unwrap(),
337            serde_json::json!(false)
338        );
339        assert_eq!(
340            serde_json::to_value(Value::from(true)).unwrap(),
341            serde_json::json!(true)
342        );
343    }
344
345    #[test]
346    fn number() {
347        assert_eq!(
348            serde_json::to_value(Value::from(5.0)).unwrap(),
349            serde_json::json!(5.0)
350        );
351    }
352
353    #[test]
354    fn string() {
355        assert_eq!(
356            serde_json::to_value(Value::from("string")).unwrap(),
357            serde_json::json!("string")
358        );
359    }
360
361    #[test]
362    fn float_special_cases() {
363        assert!(serde_json::to_value(Value::from(f64::NAN)).is_err());
364        assert!(serde_json::to_value(Value::from(f64::INFINITY)).is_err());
365        assert!(serde_json::to_value(Value::from(f64::NEG_INFINITY)).is_err());
366    }
367
368    #[test]
369    fn parse_max_safe_integer() {
370        let max_safe_integer: i64 = 9007199254740991;
371        let json = serde_json::json!(max_safe_integer);
372        let vec = serde_json::to_vec(&json).unwrap();
373        let pb = serde_json::from_slice::<Value>(&vec).unwrap();
374        assert_eq!(
375            serde_json::to_value(pb).unwrap(),
376            serde_json::json!(max_safe_integer as f64)
377        );
378    }
379
380    #[test]
381    fn parse_min_safe_integer() {
382        let min_safe_integer: i64 = -9007199254740991;
383        let json = serde_json::json!(min_safe_integer);
384        let vec = serde_json::to_vec(&json).unwrap();
385        let pb = serde_json::from_slice::<Value>(&vec).unwrap();
386        assert_eq!(
387            serde_json::to_value(pb).unwrap(),
388            serde_json::json!(min_safe_integer as f64)
389        );
390    }
391}