core_serde_json/de/
mod.rs

1//! Deserialize JSON data to a Rust data structure
2
3use core::{fmt, str};
4
5use serde::de::{self, Visitor};
6
7use self::enum_::UnitVariantAccess;
8use self::map::MapAccess;
9use self::seq::SeqAccess;
10
11mod enum_;
12mod map;
13mod seq;
14
15/// Deserialization result
16pub type Result<T> = core::result::Result<T, Error>;
17
18/// This type represents all possible errors that can occur when deserializing JSON data
19#[derive(Debug, PartialEq)]
20pub enum Error {
21    /// EOF while parsing a list.
22    EofWhileParsingList,
23
24    /// EOF while parsing an object.
25    EofWhileParsingObject,
26
27    /// EOF while parsing a string.
28    EofWhileParsingString,
29
30    /// EOF while parsing a JSON value.
31    EofWhileParsingValue,
32
33    /// Expected this character to be a `':'`.
34    ExpectedColon,
35
36    /// Expected this character to be either a `','` or a `']'`.
37    ExpectedListCommaOrEnd,
38
39    /// Expected this character to be either a `','` or a `'}'`.
40    ExpectedObjectCommaOrEnd,
41
42    /// Expected to parse either a `true`, `false`, or a `null`.
43    ExpectedSomeIdent,
44
45    /// Expected this character to start a JSON value.
46    ExpectedSomeValue,
47
48    /// Invalid number.
49    InvalidNumber,
50
51    /// Invalid type
52    InvalidType,
53
54    /// Invalid unicode code point.
55    InvalidUnicodeCodePoint,
56
57    /// Object key is not a string.
58    KeyMustBeAString,
59
60    /// JSON has non-whitespace trailing characters after the value.
61    TrailingCharacters,
62
63    /// JSON has a comma after the last value in an array or map.
64    TrailingComma,
65
66    #[doc(hidden)]
67    __Extensible,
68}
69
70#[cfg(feature = "std")]
71impl ::std::error::Error for Error {
72    fn description(&self) -> &str {
73        ""
74    }
75}
76
77pub(crate) struct Deserializer<'b> {
78    slice: &'b [u8],
79    index: usize,
80}
81
82impl<'a> Deserializer<'a> {
83    fn new(slice: &'a [u8]) -> Deserializer<'_> {
84        Deserializer { slice, index: 0 }
85    }
86
87    fn eat_char(&mut self) {
88        self.index += 1;
89    }
90
91    fn end(&mut self) -> Result<()> {
92        match self.parse_whitespace() {
93            Some(_) => Err(Error::TrailingCharacters),
94            None => Ok(()),
95        }
96    }
97
98    fn end_seq(&mut self) -> Result<()> {
99        match self.parse_whitespace().ok_or(Error::EofWhileParsingList)? {
100            b']' => {
101                self.eat_char();
102                Ok(())
103            }
104            b',' => {
105                self.eat_char();
106                match self.parse_whitespace() {
107                    Some(b']') => Err(Error::TrailingComma),
108                    _ => Err(Error::TrailingCharacters),
109                }
110            }
111            _ => Err(Error::TrailingCharacters),
112        }
113    }
114
115    fn end_map(&mut self) -> Result<()> {
116        match self
117            .parse_whitespace()
118            .ok_or(Error::EofWhileParsingObject)?
119        {
120            b'}' => {
121                self.eat_char();
122                Ok(())
123            }
124            b',' => Err(Error::TrailingComma),
125            _ => Err(Error::TrailingCharacters),
126        }
127    }
128
129    fn next_char(&mut self) -> Option<u8> {
130        let ch = self.slice.get(self.index);
131
132        if ch.is_some() {
133            self.index += 1;
134        }
135
136        ch.cloned()
137    }
138
139    fn parse_ident(&mut self, ident: &[u8]) -> Result<()> {
140        for c in ident {
141            if Some(*c) != self.next_char() {
142                return Err(Error::ExpectedSomeIdent);
143            }
144        }
145
146        Ok(())
147    }
148
149    fn parse_object_colon(&mut self) -> Result<()> {
150        match self
151            .parse_whitespace()
152            .ok_or(Error::EofWhileParsingObject)?
153        {
154            b':' => {
155                self.eat_char();
156                Ok(())
157            }
158            _ => Err(Error::ExpectedColon),
159        }
160    }
161
162    fn parse_str(&mut self) -> Result<&'a str> {
163        let start = self.index;
164        loop {
165            match self.peek() {
166                Some(b'"') => {
167                    let end = self.index;
168                    self.eat_char();
169                    return str::from_utf8(&self.slice[start..end])
170                        .map_err(|_| Error::InvalidUnicodeCodePoint);
171                }
172                Some(_) => self.eat_char(),
173                None => return Err(Error::EofWhileParsingString),
174            }
175        }
176    }
177
178    /// Consumes all the whitespace characters and returns a peek into the next character
179    fn parse_whitespace(&mut self) -> Option<u8> {
180        loop {
181            match self.peek() {
182                Some(b' ') | Some(b'\n') | Some(b'\t') | Some(b'\r') => {
183                    self.eat_char();
184                }
185                other => {
186                    return other;
187                }
188            }
189        }
190    }
191
192    fn peek(&mut self) -> Option<u8> {
193        self.slice.get(self.index).cloned()
194    }
195}
196
197// NOTE(deserialize_*signed) we avoid parsing into u64 and then casting to a smaller integer, which
198// is what upstream does, to avoid pulling in 64-bit compiler intrinsics, which waste a few KBs of
199// Flash, when targeting non 64-bit architectures
200macro_rules! deserialize_unsigned {
201    ($self:ident, $visitor:ident, $uxx:ident, $visit_uxx:ident) => {{
202        let peek = $self
203            .parse_whitespace()
204            .ok_or(Error::EofWhileParsingValue)?;
205
206        match peek {
207            b'-' => Err(Error::InvalidNumber),
208            b'0' => {
209                $self.eat_char();
210                $visitor.$visit_uxx(0)
211            }
212            b'1'..=b'9' => {
213                $self.eat_char();
214
215                let mut number = (peek - b'0') as $uxx;
216                loop {
217                    match $self.peek() {
218                        Some(c @ b'0'..=b'9') => {
219                            $self.eat_char();
220                            number = number
221                                .checked_mul(10)
222                                .ok_or(Error::InvalidNumber)?
223                                .checked_add((c - b'0') as $uxx)
224                                .ok_or(Error::InvalidNumber)?;
225                        }
226                        _ => return $visitor.$visit_uxx(number),
227                    }
228                }
229            }
230            _ => Err(Error::InvalidType),
231        }
232    }};
233}
234
235macro_rules! deserialize_signed {
236    ($self:ident, $visitor:ident, $ixx:ident, $visit_ixx:ident) => {{
237        let signed = match $self
238            .parse_whitespace()
239            .ok_or(Error::EofWhileParsingValue)?
240        {
241            b'-' => {
242                $self.eat_char();
243                true
244            }
245            _ => false,
246        };
247
248        match $self.peek().ok_or(Error::EofWhileParsingValue)? {
249            b'0' => {
250                $self.eat_char();
251                $visitor.$visit_ixx(0)
252            }
253            c @ b'1'..=b'9' => {
254                $self.eat_char();
255
256                let mut number = (c - b'0') as $ixx * if signed { -1 } else { 1 };
257                loop {
258                    match $self.peek() {
259                        Some(c @ b'0'..=b'9') => {
260                            $self.eat_char();
261                            number = number
262                                .checked_mul(10)
263                                .ok_or(Error::InvalidNumber)?
264                                .checked_add((c - b'0') as $ixx * if signed { -1 } else { 1 })
265                                .ok_or(Error::InvalidNumber)?;
266                        }
267                        _ => return $visitor.$visit_ixx(number),
268                    }
269                }
270            }
271            _ => return Err(Error::InvalidType),
272        }
273    }};
274}
275
276impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
277    type Error = Error;
278
279    fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
280    where
281        V: Visitor<'de>,
282    {
283        unreachable!()
284    }
285
286    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
287    where
288        V: Visitor<'de>,
289    {
290        let peek = self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
291
292        match peek {
293            b't' => {
294                self.eat_char();
295                self.parse_ident(b"rue")?;
296                visitor.visit_bool(true)
297            }
298            b'f' => {
299                self.eat_char();
300                self.parse_ident(b"alse")?;
301                visitor.visit_bool(false)
302            }
303            _ => Err(Error::InvalidType),
304        }
305    }
306
307    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
308    where
309        V: Visitor<'de>,
310    {
311        deserialize_signed!(self, visitor, i8, visit_i8)
312    }
313
314    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
315    where
316        V: Visitor<'de>,
317    {
318        deserialize_signed!(self, visitor, i16, visit_i16)
319    }
320
321    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
322    where
323        V: Visitor<'de>,
324    {
325        deserialize_signed!(self, visitor, i32, visit_i32)
326    }
327
328    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
329    where
330        V: Visitor<'de>,
331    {
332        deserialize_signed!(self, visitor, i64, visit_i64)
333    }
334
335    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
336    where
337        V: Visitor<'de>,
338    {
339        deserialize_unsigned!(self, visitor, u8, visit_u8)
340    }
341
342    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
343    where
344        V: Visitor<'de>,
345    {
346        deserialize_unsigned!(self, visitor, u16, visit_u16)
347    }
348
349    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
350    where
351        V: Visitor<'de>,
352    {
353        deserialize_unsigned!(self, visitor, u32, visit_u32)
354    }
355
356    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
357    where
358        V: Visitor<'de>,
359    {
360        deserialize_unsigned!(self, visitor, u64, visit_u64)
361    }
362
363    fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value>
364    where
365        V: Visitor<'de>,
366    {
367        unreachable!()
368    }
369
370    fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value>
371    where
372        V: Visitor<'de>,
373    {
374        unreachable!()
375    }
376
377    fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value>
378    where
379        V: Visitor<'de>,
380    {
381        unreachable!()
382    }
383
384    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
385    where
386        V: Visitor<'de>,
387    {
388        let peek = self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
389
390        match peek {
391            b'"' => {
392                self.eat_char();
393                visitor.visit_borrowed_str(self.parse_str()?)
394            }
395            _ => Err(Error::InvalidType),
396        }
397    }
398
399    fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value>
400    where
401        V: Visitor<'de>,
402    {
403        unreachable!()
404    }
405
406    fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
407    where
408        V: Visitor<'de>,
409    {
410        unreachable!()
411    }
412
413    fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value>
414    where
415        V: Visitor<'de>,
416    {
417        unreachable!()
418    }
419
420    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
421    where
422        V: Visitor<'de>,
423    {
424        match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
425            b'n' => {
426                self.eat_char();
427                self.parse_ident(b"ull")?;
428                visitor.visit_none()
429            }
430            _ => visitor.visit_some(self),
431        }
432    }
433
434    fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value>
435    where
436        V: Visitor<'de>,
437    {
438        unreachable!()
439    }
440
441    fn deserialize_unit_struct<V>(self, _name: &'static str, _visitor: V) -> Result<V::Value>
442    where
443        V: Visitor<'de>,
444    {
445        unreachable!()
446    }
447
448    fn deserialize_newtype_struct<V>(self, _name: &'static str, _visitor: V) -> Result<V::Value>
449    where
450        V: Visitor<'de>,
451    {
452        unreachable!()
453    }
454
455    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
456    where
457        V: Visitor<'de>,
458    {
459        match self.peek().ok_or(Error::EofWhileParsingValue)? {
460            b'[' => {
461                self.eat_char();
462                let ret = visitor.visit_seq(SeqAccess::new(self))?;
463
464                self.end_seq()?;
465
466                Ok(ret)
467            }
468            _ => Err(Error::InvalidType),
469        }
470    }
471
472    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
473    where
474        V: Visitor<'de>,
475    {
476        self.deserialize_seq(visitor)
477    }
478
479    fn deserialize_tuple_struct<V>(
480        self,
481        _name: &'static str,
482        _len: usize,
483        _visitor: V,
484    ) -> Result<V::Value>
485    where
486        V: Visitor<'de>,
487    {
488        unreachable!()
489    }
490
491    fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value>
492    where
493        V: Visitor<'de>,
494    {
495        unreachable!()
496    }
497
498    fn deserialize_struct<V>(
499        self,
500        _name: &'static str,
501        _fields: &'static [&'static str],
502        visitor: V,
503    ) -> Result<V::Value>
504    where
505        V: Visitor<'de>,
506    {
507        let peek = self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
508
509        if peek == b'{' {
510            self.eat_char();
511
512            let ret = visitor.visit_map(MapAccess::new(self))?;
513
514            self.end_map()?;
515
516            Ok(ret)
517        } else {
518            Err(Error::InvalidType)
519        }
520    }
521
522    fn deserialize_enum<V>(
523        self,
524        _name: &'static str,
525        _variants: &'static [&'static str],
526        visitor: V,
527    ) -> Result<V::Value>
528    where
529        V: Visitor<'de>,
530    {
531        match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
532            b'"' => visitor.visit_enum(UnitVariantAccess::new(self)),
533            _ => Err(Error::ExpectedSomeValue),
534        }
535    }
536
537    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
538    where
539        V: Visitor<'de>,
540    {
541        self.deserialize_str(visitor)
542    }
543
544    fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value>
545    where
546        V: Visitor<'de>,
547    {
548        unreachable!()
549    }
550}
551
552impl de::Error for Error {
553    fn custom<T>(_msg: T) -> Self
554    where
555        T: fmt::Display,
556    {
557        unreachable!()
558    }
559}
560
561impl fmt::Display for Error {
562    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563        write!(
564            f,
565            "{}",
566            match self {
567                Error::EofWhileParsingList => "EOF while parsing a list.",
568                Error::EofWhileParsingObject => "EOF while parsing an object.",
569                Error::EofWhileParsingString => "EOF while parsing a string.",
570                Error::EofWhileParsingValue => "EOF while parsing a JSON value.",
571                Error::ExpectedColon => "Expected this character to be a `':'`.",
572                Error::ExpectedListCommaOrEnd => {
573                    "Expected this character to be either a `','` or\
574                     a \
575                     `']'`."
576                }
577                Error::ExpectedObjectCommaOrEnd => {
578                    "Expected this character to be either a `','` \
579                     or a \
580                     `'}'`."
581                }
582                Error::ExpectedSomeIdent => {
583                    "Expected to parse either a `true`, `false`, or a \
584                     `null`."
585                }
586                Error::ExpectedSomeValue => "Expected this character to start a JSON value.",
587                Error::InvalidNumber => "Invalid number.",
588                Error::InvalidType => "Invalid type",
589                Error::InvalidUnicodeCodePoint => "Invalid unicode code point.",
590                Error::KeyMustBeAString => "Object key is not a string.",
591                Error::TrailingCharacters => {
592                    "JSON has non-whitespace trailing characters after \
593                     the \
594                     value."
595                }
596                Error::TrailingComma => "JSON has a comma after the last value in an array or map.",
597                _ => "Invalid JSON",
598            }
599        )
600    }
601}
602
603/// Deserializes an instance of type `T` from bytes of JSON text
604pub fn from_slice<'a, T>(v: &'a [u8]) -> Result<T>
605where
606    T: de::Deserialize<'a>,
607{
608    let mut de = Deserializer::new(v);
609    let value = de::Deserialize::deserialize(&mut de)?;
610    de.end()?;
611
612    Ok(value)
613}
614
615/// Deserializes an instance of type T from a string of JSON text
616pub fn from_str<'a, T>(s: &'a str) -> Result<T>
617where
618    T: de::Deserialize<'a>,
619{
620    from_slice(s.as_bytes())
621}
622
623#[cfg(test)]
624mod tests {
625    use serde_derive::Deserialize;
626
627    #[derive(Debug, Deserialize, PartialEq)]
628    enum Type {
629        #[serde(rename = "boolean")]
630        Boolean,
631        #[serde(rename = "number")]
632        Number,
633        #[serde(rename = "thing")]
634        Thing,
635    }
636
637    #[test]
638    fn array() {
639        assert_eq!(crate::from_str::<[i32; 0]>("[]"), Ok([]));
640        assert_eq!(crate::from_str("[0, 1, 2]"), Ok([0, 1, 2]));
641
642        // errors
643        assert!(crate::from_str::<[i32; 2]>("[0, 1,]").is_err());
644    }
645
646    #[test]
647    fn bool() {
648        assert_eq!(crate::from_str("true"), Ok(true));
649        assert_eq!(crate::from_str(" true"), Ok(true));
650        assert_eq!(crate::from_str("true "), Ok(true));
651
652        assert_eq!(crate::from_str("false"), Ok(false));
653        assert_eq!(crate::from_str(" false"), Ok(false));
654        assert_eq!(crate::from_str("false "), Ok(false));
655
656        // errors
657        assert!(crate::from_str::<bool>("true false").is_err());
658        assert!(crate::from_str::<bool>("tru").is_err());
659    }
660
661    #[test]
662    fn enum_clike() {
663        assert_eq!(crate::from_str(r#" "boolean" "#), Ok(Type::Boolean));
664        assert_eq!(crate::from_str(r#" "number" "#), Ok(Type::Number));
665        assert_eq!(crate::from_str(r#" "thing" "#), Ok(Type::Thing));
666    }
667
668    #[test]
669    fn str() {
670        assert_eq!(crate::from_str(r#" "hello" "#), Ok("hello"));
671    }
672
673    #[test]
674    fn struct_bool() {
675        #[derive(Debug, Deserialize, PartialEq)]
676        struct Led {
677            led: bool,
678        }
679
680        assert_eq!(crate::from_str(r#"{ "led": true }"#), Ok(Led { led: true }));
681        assert_eq!(
682            crate::from_str(r#"{ "led": false }"#),
683            Ok(Led { led: false })
684        );
685    }
686
687    #[test]
688    fn struct_i8() {
689        #[derive(Debug, Deserialize, PartialEq)]
690        struct Temperature {
691            temperature: i8,
692        }
693
694        assert_eq!(
695            crate::from_str(r#"{ "temperature": -17 }"#),
696            Ok(Temperature { temperature: -17 })
697        );
698
699        assert_eq!(
700            crate::from_str(r#"{ "temperature": -0 }"#),
701            Ok(Temperature { temperature: -0 })
702        );
703
704        assert_eq!(
705            crate::from_str(r#"{ "temperature": 0 }"#),
706            Ok(Temperature { temperature: 0 })
707        );
708
709        // out of range
710        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 128 }"#).is_err());
711        assert!(crate::from_str::<Temperature>(r#"{ "temperature": -129 }"#).is_err());
712    }
713
714    #[test]
715    fn struct_option() {
716        #[derive(Debug, Deserialize, PartialEq)]
717        struct Property<'a> {
718            #[serde(borrow)]
719            description: Option<&'a str>,
720        }
721
722        assert_eq!(
723            crate::from_str(r#"{ "description": "An ambient temperature sensor" }"#),
724            Ok(Property {
725                description: Some("An ambient temperature sensor"),
726            })
727        );
728
729        assert_eq!(
730            crate::from_str(r#"{ "description": null }"#),
731            Ok(Property { description: None })
732        );
733
734        assert_eq!(crate::from_str(r#"{}"#), Ok(Property { description: None }));
735    }
736
737    #[test]
738    fn struct_u8() {
739        #[derive(Debug, Deserialize, PartialEq)]
740        struct Temperature {
741            temperature: u8,
742        }
743
744        assert_eq!(
745            crate::from_str(r#"{ "temperature": 20 }"#),
746            Ok(Temperature { temperature: 20 })
747        );
748
749        assert_eq!(
750            crate::from_str(r#"{ "temperature": 0 }"#),
751            Ok(Temperature { temperature: 0 })
752        );
753
754        // out of range
755        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 256 }"#).is_err());
756        assert!(crate::from_str::<Temperature>(r#"{ "temperature": -1 }"#).is_err());
757    }
758
759    // See https://iot.mozilla.org/wot/#thing-resource
760    #[test]
761    #[ignore]
762    fn wot() {
763        #[derive(Debug, Deserialize, PartialEq)]
764        struct Thing<'a> {
765            #[serde(borrow)]
766            properties: Properties<'a>,
767            #[serde(rename = "type")]
768            ty: Type,
769        }
770
771        #[derive(Debug, Deserialize, PartialEq)]
772        struct Properties<'a> {
773            #[serde(borrow)]
774            temperature: Property<'a>,
775            #[serde(borrow)]
776            humidity: Property<'a>,
777            #[serde(borrow)]
778            led: Property<'a>,
779        }
780
781        #[derive(Debug, Deserialize, PartialEq)]
782        struct Property<'a> {
783            #[serde(rename = "type")]
784            ty: Type,
785            unit: Option<&'a str>,
786            #[serde(borrow)]
787            description: Option<&'a str>,
788            href: &'a str,
789        }
790
791        assert_eq!(
792            crate::from_str::<Thing<'_>>(
793                r#"
794{
795  "type": "thing",
796  "properties": {
797    "temperature": {
798      "type": "number",
799      "unit": "celsius",
800      "description": "An ambient temperature sensor",
801      "href": "/properties/temperature"
802    },
803    "humidity": {
804      "type": "number",
805      "unit": "percent",
806      "href": "/properties/humidity"
807    },
808    "led": {
809      "type": "boolean",
810      "description": "A red LED",
811      "href": "/properties/led"
812    }
813  }
814}
815"#
816            ),
817            Ok(Thing {
818                properties: Properties {
819                    temperature: Property {
820                        ty: Type::Number,
821                        unit: Some("celcius"),
822                        description: Some("An ambient temperature sensor"),
823                        href: "/properties/temperature",
824                    },
825                    humidity: Property {
826                        ty: Type::Number,
827                        unit: Some("percent"),
828                        description: None,
829                        href: "/properties/humidity",
830                    },
831                    led: Property {
832                        ty: Type::Boolean,
833                        unit: None,
834                        description: Some("A red LED"),
835                        href: "/properties/led",
836                    },
837                },
838                ty: Type::Thing,
839            })
840        )
841    }
842}