lib_contra/deserialize/
json.rs

1use std::{
2    io::Cursor,
3    str::{from_utf8, FromStr},
4};
5
6use crate::error::AnyError;
7
8use super::{Deserialize, Deserializer, MapAccess, Peek, SeqAccess, Visitor};
9
10pub trait FromJson: Sized {
11    fn from_json(str: &str) -> Result<Self, AnyError>;
12}
13
14impl<D: Deserialize> FromJson for D {
15    fn from_json(str: &str) -> Result<Self, AnyError> {
16        let mut de = JsonDeserializer {
17            read: Cursor::new(str),
18        };
19        Self::deserialize(&mut de)
20    }
21}
22
23macro_rules! impl_deserializer_primitive {
24    ($ttype: ident, $deserialize_fn: ident, $parse_fn: ident, $visit_fn: ident) => {
25        fn $deserialize_fn<V: Visitor>(self, v: V) -> Result<V::Value, AnyError> {
26            self.parse_whitespaces()?;
27            match self.read.peek()? {
28                Some(b'-') | Some(b'0') | Some(b'1') | Some(b'2') | Some(b'3') | Some(b'4')
29                | Some(b'5') | Some(b'6') | Some(b'7') | Some(b'8') | Some(b'9') | Some(b'.') => {
30                    let str = self
31                        .read
32                        .read_until(&[b' ', b',', b'\t', b'\n', b']', b'}', b':'])?;
33                    let str = from_utf8(str.as_slice())?;
34                    let val = self.$parse_fn(str)?;
35                    v.$visit_fn(val)
36                }
37                Some(b'"') => {
38                    self.read.consume()?;
39                    let str = self.read.read_until(&[b'"'])?;
40                    self.read.consume()?;
41                    let str = from_utf8(str.as_slice())?;
42                    let val = self.$parse_fn(str)?;
43                    v.$visit_fn(val)
44                }
45                Some(_) | None => {
46                    Err(concat!("expected a ", stringify!($ttype), " to start").into())
47                }
48            }
49        }
50    };
51    ($ttype: ident as $cast: ident, $deserialize_fn: ident, $parse_fn: ident, $visit_fn: ident) => {
52        fn $deserialize_fn<V: Visitor>(self, v: V) -> Result<V::Value, AnyError> {
53            self.parse_whitespaces()?;
54            match self.read.peek()? {
55                Some(b'-') | Some(b'0') | Some(b'1') | Some(b'2') | Some(b'3') | Some(b'4')
56                | Some(b'5') | Some(b'6') | Some(b'7') | Some(b'8') | Some(b'9') | Some(b'.') => {
57                    let str = self
58                        .read
59                        .read_until(&[b' ', b',', b'\t', b'\n', b']', b'}', b':'])?;
60                    let str = from_utf8(str.as_slice())?;
61                    let val = self.$parse_fn(str)?;
62                    v.$visit_fn(val as $cast)
63                }
64                Some(b'"') => {
65                    self.read.consume()?;
66                    let str = self.read.read_until(&[b'"'])?;
67                    self.read.consume()?;
68                    let str = from_utf8(str.as_slice())?;
69                    let val = self.$parse_fn(str)?;
70                    v.$visit_fn(val)
71                }
72                Some(_) | None => {
73                    Err(concat!("expected a ", stringify!($ttype), " to start").into())
74                }
75            }
76        }
77    };
78}
79
80pub struct JsonDeserializer<P: Peek> {
81    read: P,
82}
83
84struct JsonMap<'de, P: Peek> {
85    de: &'de mut JsonDeserializer<P>,
86}
87
88struct JsonArray<'de, P: Peek> {
89    de: &'de mut JsonDeserializer<P>,
90}
91
92impl<P: Peek> JsonDeserializer<P> {
93    pub fn new(peek: P) -> Self {
94        Self { read: peek }
95    }
96
97    fn parse_whitespaces(&mut self) -> Result<(), AnyError> {
98        self.read.consume_matching(&[b' ', b'\n', b'\t'])
99    }
100
101    fn parse_signed_number<I: FromStr>(&mut self, str: &str) -> Result<I, AnyError>
102    where
103        <I as FromStr>::Err: std::error::Error + 'static,
104    {
105        str.parse().map_err(|err| Box::from(err))
106    }
107
108    fn parse_unsigned_number<U: FromStr>(&mut self, str: &str) -> Result<U, AnyError>
109    where
110        <U as FromStr>::Err: std::error::Error + 'static,
111    {
112        str.parse().map_err(|err| Box::from(err))
113    }
114
115    fn parse_floating_number<F: FromStr>(&mut self, str: &str) -> Result<F, AnyError>
116    where
117        <F as FromStr>::Err: std::error::Error + 'static,
118    {
119        str.parse().map_err(|err| Box::from(err))
120    }
121}
122
123impl<P: Peek> Deserializer for &mut JsonDeserializer<P> {
124    fn deserialize_map<V: Visitor>(self, v: V) -> Result<V::Value, AnyError> {
125        self.parse_whitespaces()?;
126        match self.read.peek()? {
127            Some(b'{') => {
128                self.read.consume()?;
129                let val = v.visit_map(JsonMap { de: self });
130                self.read.consume()?;
131                val
132            }
133            Some(char) => {
134                Err(format!("expected a map to start but got \"{}\" instead", char).into())
135            }
136            None => Err("expected a map to start".into()),
137        }
138    }
139
140    fn deserialize_seq<V: Visitor>(self, v: V) -> Result<V::Value, AnyError> {
141        self.parse_whitespaces()?;
142        match self.read.peek()? {
143            Some(b'[') => {
144                self.read.consume()?;
145                v.visit_seq(JsonArray { de: self })
146            }
147            Some(_) | None => Err("expected a vec to start".into()),
148        }
149    }
150
151    fn deserialize_struct<V: Visitor>(self, v: V) -> Result<V::Value, AnyError> {
152        self.deserialize_map(v)
153    }
154
155    fn deserialize_str<V: Visitor>(self, v: V) -> Result<V::Value, AnyError> {
156        self.parse_whitespaces()?;
157        match self.read.peek()? {
158            Some(b'"') => {
159                self.read.consume()?;
160                let str = self.read.read_until(&[b'"'])?;
161                self.read.consume()?;
162                let str = from_utf8(str.as_slice())?;
163                v.visit_str(str)
164            }
165            Some(_) | None => Err("expected a str to start".into()),
166        }
167    }
168
169    impl_deserializer_primitive!(i8, deserialize_i8, parse_signed_number, visit_i8);
170    impl_deserializer_primitive!(i16, deserialize_i16, parse_signed_number, visit_i16);
171    impl_deserializer_primitive!(i32, deserialize_i32, parse_signed_number, visit_i32);
172    impl_deserializer_primitive!(i64, deserialize_i64, parse_signed_number, visit_i64);
173    impl_deserializer_primitive!(i128, deserialize_i128, parse_signed_number, visit_i128);
174    impl_deserializer_primitive!(u8, deserialize_u8, parse_unsigned_number, visit_u8);
175    impl_deserializer_primitive!(u16, deserialize_u16, parse_unsigned_number, visit_u16);
176    impl_deserializer_primitive!(u32, deserialize_u32, parse_unsigned_number, visit_u32);
177    impl_deserializer_primitive!(u64, deserialize_u64, parse_unsigned_number, visit_u64);
178    impl_deserializer_primitive!(u128, deserialize_u128, parse_unsigned_number, visit_u128);
179    impl_deserializer_primitive!(f32, deserialize_f32, parse_floating_number, visit_f32);
180    impl_deserializer_primitive!(f64, deserialize_f64, parse_floating_number, visit_f64);
181    impl_deserializer_primitive!(isize, deserialize_isize, parse_signed_number, visit_isize);
182    impl_deserializer_primitive!(usize, deserialize_usize, parse_unsigned_number, visit_usize);
183}
184
185impl<'de, P: Peek> MapAccess for JsonMap<'de, P> {
186    fn next_value<V: Deserialize>(&mut self) -> Result<V, AnyError> {
187        self.de.parse_whitespaces()?;
188        match self.de.read.peek()? {
189            Some(b':') => {
190                self.de.read.consume()?;
191                self.de.parse_whitespaces()?;
192                match self.de.read.peek()? {
193                    Some(b'0') | Some(b'1') | Some(b'2') | Some(b'3') | Some(b'4') | Some(b'5')
194                    | Some(b'6') | Some(b'7') | Some(b'8') | Some(b'9') | Some(b'-')
195                    | Some(b'"') | Some(b'{') | Some(b'[') => Ok(V::deserialize(&mut *self.de)?),
196                    Some(_) | None => Err("expected a map value".into()),
197                }
198            }
199            Some(_) | None => Err("expected a map assignment".into()),
200        }
201    }
202
203    fn next_key<K: Deserialize>(&mut self) -> Result<Option<K>, AnyError> {
204        self.de.parse_whitespaces()?;
205        match self.de.read.peek()? {
206            Some(b'"') => Ok(Some(K::deserialize(&mut *self.de)?)),
207            Some(b',') => {
208                self.de.read.consume()?;
209                self.next_key()
210            }
211            Some(b'}') => Ok(None),
212            Some(_) | None => Err("expected a map key".into()),
213        }
214    }
215}
216
217impl<'de, P: Peek> SeqAccess for JsonArray<'de, P> {
218    fn next_value<V: Deserialize>(&mut self) -> Result<Option<V>, AnyError> {
219        self.de.parse_whitespaces()?;
220        match self.de.read.peek()? {
221            Some(b',') => {
222                self.de.read.consume()?;
223                self.next_value()
224            }
225            Some(b']') => {
226                self.de.read.consume()?;
227                Ok(None)
228            }
229            Some(b'"') | Some(_) => Ok(Some(V::deserialize(&mut *self.de)?)),
230            None => Err("expected a seq element".into()),
231        }
232    }
233}
234
235#[cfg(test)]
236mod test {
237    use std::{collections::HashMap, io::Cursor};
238
239    use super::*;
240
241    #[test]
242    fn parse_vec_test() {
243        let expected = vec![32i32, 64i32];
244
245        let input = "[32, 64]";
246        let input = Cursor::new(input);
247        let mut de = JsonDeserializer { read: input };
248        let result = Vec::<i32>::deserialize(&mut de);
249
250        dbg!(&result);
251        assert!(result.is_ok());
252        assert_eq!(result.unwrap(), expected);
253    }
254
255    #[test]
256    fn parse_map_test() {
257        let mut expected = HashMap::new();
258        expected.insert(2i32, 32i32);
259
260        let input = "{ \"2\": 32 }";
261        let input = Cursor::new(input);
262        let mut de = JsonDeserializer { read: input };
263        let map = HashMap::<i32, i32>::deserialize(&mut de);
264
265        dbg!(&map);
266        assert!(map.is_ok());
267        assert_eq!(map.unwrap(), expected);
268    }
269
270    #[test]
271    fn parse_struct_test() {
272        #[derive(Debug)]
273        struct A {
274            a: i32,
275            s: String,
276        }
277
278        impl Deserialize for A {
279            fn deserialize<D: Deserializer>(des: D) -> Result<Self, AnyError> {
280                enum Field {
281                    A,
282                    S,
283                }
284
285                impl Deserialize for Field {
286                    fn deserialize<D: Deserializer>(des: D) -> Result<Self, AnyError> {
287                        struct FieldVisitor {}
288                        impl Visitor for FieldVisitor {
289                            type Value = Field;
290
291                            fn visit_str(self, v: &str) -> Result<Self::Value, AnyError> {
292                                match v {
293                                    "a" => Ok(Field::A),
294                                    "s" => Ok(Field::S),
295                                    val => Err(format!("unknown \"{}\" field for A", val).into()),
296                                }
297                            }
298
299                            fn expected_a(self) -> String {
300                                "A field".into()
301                            }
302                        }
303
304                        des.deserialize_str(FieldVisitor {})
305                    }
306                }
307
308                struct AVisitor {}
309                impl Visitor for AVisitor {
310                    type Value = A;
311
312                    fn expected_a(self) -> String {
313                        "A".into()
314                    }
315
316                    fn visit_map<M: MapAccess>(self, mut map: M) -> Result<Self::Value, AnyError> {
317                        let mut a = None;
318                        let mut s = None;
319
320                        while let Some(key) = map.next_key()? {
321                            match key {
322                                Field::A => {
323                                    if a.is_some() {
324                                        return Err("duplicate field a".into());
325                                    };
326                                    a = Some(map.next_value()?)
327                                }
328                                Field::S => {
329                                    if s.is_some() {
330                                        return Err("duplicate field s".into());
331                                    };
332                                    s = Some(map.next_value()?)
333                                }
334                            }
335                        }
336
337                        let a = a.ok_or_else(|| "missing field a")?;
338                        let s = s.ok_or_else(|| "missing field s")?;
339
340                        Ok(A { a: a, s: s })
341                    }
342                }
343
344                des.deserialize_struct(AVisitor {})
345            }
346        }
347
348        let input = "{ \"a\": \"32\", \"s\": \"well well well\" }";
349        let input = Cursor::new(input);
350
351        let mut de = JsonDeserializer { read: input };
352
353        let a = A::deserialize(&mut de);
354
355        dbg!(&a);
356        assert!(a.is_ok());
357        assert_eq!(a.as_ref().unwrap().a, 32);
358        assert_eq!(a.as_ref().unwrap().s, "well well well".to_string());
359    }
360}