jmap_tools/json/
de.rs

1/*
2 * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
3 *
4 * SPDX-License-Identifier: Apache-2.0 OR MIT
5 */
6
7use super::value::Value;
8use crate::json::key::{self, Key};
9use crate::json::object_vec::ObjectAsVec;
10use crate::{Element, Property};
11use serde::de::{Deserialize, DeserializeSeed, MapAccess, SeqAccess, Visitor};
12use std::borrow::Cow;
13
14#[derive(Clone, Default)]
15pub(crate) struct DeserializationContext<'x, P: Property, E: Element> {
16    parent_key: Option<&'x Key<'x, P>>,
17    phantom: std::marker::PhantomData<E>,
18}
19
20impl<'de, P: Property, E: Element<Property = P>> Deserialize<'de> for Value<'de, P, E> {
21    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
22    where
23        D: serde::Deserializer<'de>,
24    {
25        DeserializationContext {
26            parent_key: None,
27            phantom: std::marker::PhantomData,
28        }
29        .deserialize(deserializer)
30    }
31}
32
33impl<'de, 'x, P: Property, E: Element<Property = P>> DeserializeSeed<'de>
34    for DeserializationContext<'x, P, E>
35{
36    type Value = Value<'de, P, E>;
37
38    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
39    where
40        D: serde::Deserializer<'de>,
41    {
42        deserializer.deserialize_any(ContextualVisitor { context: &self })
43    }
44}
45
46struct ContextualVisitor<'x, P: Property, E: Element> {
47    context: &'x DeserializationContext<'x, P, E>,
48}
49
50impl<'de, 'x, P: Property, E: Element<Property = P>> Visitor<'de> for ContextualVisitor<'x, P, E> {
51    type Value = Value<'de, P, E>;
52
53    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54        formatter.write_str("any valid JSON value")
55    }
56
57    #[inline]
58    fn visit_bool<ERR>(self, value: bool) -> Result<Value<'de, P, E>, ERR>
59    where
60        ERR: serde::de::Error,
61    {
62        Ok(Value::Bool(value))
63    }
64
65    #[inline]
66    fn visit_i64<ERR>(self, value: i64) -> Result<Value<'de, P, E>, ERR>
67    where
68        ERR: serde::de::Error,
69    {
70        Ok(Value::Number(value.into()))
71    }
72
73    #[inline]
74    fn visit_u64<ERR>(self, value: u64) -> Result<Value<'de, P, E>, ERR>
75    where
76        ERR: serde::de::Error,
77    {
78        Ok(Value::Number(value.into()))
79    }
80
81    #[inline]
82    fn visit_f64<ERR>(self, value: f64) -> Result<Value<'de, P, E>, ERR>
83    where
84        ERR: serde::de::Error,
85    {
86        Ok(Value::Number(value.into()))
87    }
88
89    #[inline]
90    fn visit_string<ERR>(self, v: String) -> Result<Self::Value, ERR>
91    where
92        ERR: serde::de::Error,
93    {
94        if let Some(element) = self
95            .context
96            .parent_key
97            .and_then(|key| E::try_parse::<P>(key, &v))
98        {
99            Ok(Value::Element(element))
100        } else {
101            Ok(Value::Str(Cow::Owned(v)))
102        }
103    }
104
105    #[inline]
106    fn visit_str<ERR>(self, v: &str) -> Result<Self::Value, ERR>
107    where
108        ERR: serde::de::Error,
109    {
110        if let Some(element) = self
111            .context
112            .parent_key
113            .and_then(|key| E::try_parse::<P>(key, v))
114        {
115            Ok(Value::Element(element))
116        } else {
117            Ok(Value::Str(Cow::Owned(v.to_owned())))
118        }
119    }
120
121    #[inline]
122    fn visit_borrowed_str<ERR>(self, v: &'de str) -> Result<Self::Value, ERR>
123    where
124        ERR: serde::de::Error,
125    {
126        if let Some(element) = self
127            .context
128            .parent_key
129            .and_then(|key| E::try_parse::<P>(key, v))
130        {
131            Ok(Value::Element(element))
132        } else {
133            Ok(Value::Str(Cow::Borrowed(v)))
134        }
135    }
136
137    #[inline]
138    fn visit_none<ERR>(self) -> Result<Value<'de, P, E>, ERR>
139    where
140        ERR: serde::de::Error,
141    {
142        Ok(Value::Null)
143    }
144
145    #[inline]
146    fn visit_i8<ERR>(self, v: i8) -> Result<Self::Value, ERR>
147    where
148        ERR: serde::de::Error,
149    {
150        Ok(Value::Number((v as i64).into()))
151    }
152
153    #[inline]
154    fn visit_i16<ERR>(self, v: i16) -> Result<Self::Value, ERR>
155    where
156        ERR: serde::de::Error,
157    {
158        Ok(Value::Number((v as i64).into()))
159    }
160
161    #[inline]
162    fn visit_i32<ERR>(self, v: i32) -> Result<Self::Value, ERR>
163    where
164        ERR: serde::de::Error,
165    {
166        Ok(Value::Number((v as i64).into()))
167    }
168
169    #[inline]
170    fn visit_u8<ERR>(self, v: u8) -> Result<Self::Value, ERR>
171    where
172        ERR: serde::de::Error,
173    {
174        Ok(Value::Number((v as u64).into()))
175    }
176
177    #[inline]
178    fn visit_u16<ERR>(self, v: u16) -> Result<Self::Value, ERR>
179    where
180        ERR: serde::de::Error,
181    {
182        Ok(Value::Number((v as u64).into()))
183    }
184
185    #[inline]
186    fn visit_u32<ERR>(self, v: u32) -> Result<Self::Value, ERR>
187    where
188        ERR: serde::de::Error,
189    {
190        Ok(Value::Number((v as u64).into()))
191    }
192
193    #[inline]
194    fn visit_f32<ERR>(self, v: f32) -> Result<Self::Value, ERR>
195    where
196        ERR: serde::de::Error,
197    {
198        Ok(Value::Number((v as f64).into()))
199    }
200
201    #[inline]
202    fn visit_some<D>(self, deserializer: D) -> Result<Value<'de, P, E>, D::Error>
203    where
204        D: serde::Deserializer<'de>,
205    {
206        DeserializationContext {
207            parent_key: self.context.parent_key,
208            phantom: std::marker::PhantomData,
209        }
210        .deserialize(deserializer)
211    }
212
213    #[inline]
214    fn visit_unit<ERR>(self) -> Result<Value<'de, P, E>, ERR>
215    where
216        ERR: serde::de::Error,
217    {
218        Ok(Value::Null)
219    }
220
221    #[inline]
222    fn visit_seq<V>(self, mut visitor: V) -> Result<Value<'de, P, E>, V::Error>
223    where
224        V: SeqAccess<'de>,
225    {
226        let mut vec = Vec::with_capacity(visitor.size_hint().unwrap_or(0));
227
228        while let Some(elem) = visitor.next_element_seed(DeserializationContext {
229            parent_key: self.context.parent_key,
230            phantom: std::marker::PhantomData,
231        })? {
232            vec.push(elem);
233        }
234
235        Ok(Value::Array(vec))
236    }
237
238    #[inline]
239    fn visit_map<V>(self, mut visitor: V) -> Result<Value<'de, P, E>, V::Error>
240    where
241        V: MapAccess<'de>,
242    {
243        let mut values = Vec::with_capacity(visitor.size_hint().unwrap_or(0));
244
245        while let Some(key) = visitor.next_key_seed(key::DeserializationContext {
246            parent_key: self.context.parent_key,
247        })? {
248            let value = visitor.next_value_seed(DeserializationContext {
249                parent_key: Some(&key),
250                phantom: std::marker::PhantomData,
251            })?;
252
253            values.push((key, value));
254        }
255
256        Ok(Value::Object(ObjectAsVec(values)))
257    }
258}
259
260#[cfg(test)]
261mod tests {
262
263    use std::borrow::Cow;
264
265    use crate::{Null, Value};
266
267    #[test]
268    fn deserialize_json_test() {
269        let json_obj = r#"
270            {
271                "bool": true,
272                "string_key": "string_val",
273                "float": 1.23,
274                "i64": -123,
275                "u64": 123
276            }
277       "#;
278
279        let val: Value<'_, Null, Null> = serde_json::from_str(json_obj).unwrap();
280        assert_eq!(val.get("bool"), &Value::Bool(true));
281        assert_eq!(
282            val.get("string_key"),
283            &Value::Str(Cow::Borrowed("string_val"))
284        );
285        assert_eq!(val.get("float"), &Value::Number(1.23.into()));
286        assert_eq!(val.get("i64"), &Value::Number((-123i64).into()));
287        assert_eq!(val.get("u64"), &Value::Number(123u64.into()));
288    }
289
290    #[test]
291    fn deserialize_json_allow_escaped_strings_in_values() {
292        let json_obj = r#"
293            {
294                "bool": true,
295                "string_key": "string\"_val",
296                "u64": 123
297            }
298       "#;
299
300        let val: Value<'_, Null, Null> = serde_json::from_str(json_obj).unwrap();
301        assert_eq!(val.get("bool"), &Value::Bool(true));
302        assert_eq!(
303            val.get("string_key"),
304            &Value::Str(Cow::Borrowed("string\"_val"))
305        );
306    }
307}