serde_json_core_fmt/de/
mod.rs

1//! Deserialize JSON data to a Rust data structure
2
3use core::str::FromStr;
4use core::{fmt, str};
5
6use serde::de::{self, Visitor};
7
8use self::enum_::{UnitVariantAccess, VariantAccess};
9use self::map::MapAccess;
10use self::seq::SeqAccess;
11
12mod enum_;
13mod map;
14mod seq;
15
16/// Deserialization result
17pub type Result<T> = core::result::Result<T, Error>;
18
19/// This type represents all possible errors that can occur when deserializing JSON data
20#[derive(Debug, PartialEq)]
21#[non_exhaustive]
22pub enum Error {
23    /// EOF while parsing a list.
24    EofWhileParsingList,
25
26    /// EOF while parsing an object.
27    EofWhileParsingObject,
28
29    /// EOF while parsing a string.
30    EofWhileParsingString,
31
32    /// EOF while parsing a JSON number.
33    EofWhileParsingNumber,
34
35    /// EOF while parsing a JSON value.
36    EofWhileParsingValue,
37
38    /// Expected this character to be a `':'`.
39    ExpectedColon,
40
41    /// Expected this character to be either a `','` or a `']'`.
42    ExpectedListCommaOrEnd,
43
44    /// Expected this character to be either a `','` or a `'}'`.
45    ExpectedObjectCommaOrEnd,
46
47    /// Expected to parse either a `true`, `false`, or a `null`.
48    ExpectedSomeIdent,
49
50    /// Expected this character to start a JSON value.
51    ExpectedSomeValue,
52
53    /// Invalid number.
54    InvalidNumber,
55
56    /// Invalid type
57    InvalidType,
58
59    /// Invalid unicode code point.
60    InvalidUnicodeCodePoint,
61
62    /// Object key is not a string.
63    KeyMustBeAString,
64
65    /// JSON has non-whitespace trailing characters after the value.
66    TrailingCharacters,
67
68    /// JSON has a comma after the last value in an array or map.
69    TrailingComma,
70
71    /// Error with a custom message that we had to discard.
72    CustomError,
73
74    /// Error with a custom message that was preserved.
75    #[cfg(feature = "custom-error-messages")]
76    CustomErrorWithMessage(heapless::String<heapless::consts::U64>),
77}
78
79impl serde::de::StdError for Error {
80    #[cfg(feature = "std")]
81    fn description(&self) -> &str {
82        ""
83    }
84}
85
86pub(crate) struct Deserializer<'b> {
87    slice: &'b [u8],
88    index: usize,
89}
90
91impl<'a> Deserializer<'a> {
92    fn new(slice: &'a [u8]) -> Deserializer<'_> {
93        Deserializer { slice, index: 0 }
94    }
95
96    fn eat_char(&mut self) {
97        self.index += 1;
98    }
99
100    fn end(&mut self) -> Result<usize> {
101        match self.parse_whitespace() {
102            Some(_) => Err(Error::TrailingCharacters),
103            None => Ok(self.index),
104        }
105    }
106
107    fn end_seq(&mut self) -> Result<()> {
108        match self.parse_whitespace().ok_or(Error::EofWhileParsingList)? {
109            b']' => {
110                self.eat_char();
111                Ok(())
112            }
113            b',' => {
114                self.eat_char();
115                match self.parse_whitespace() {
116                    Some(b']') => Err(Error::TrailingComma),
117                    _ => Err(Error::TrailingCharacters),
118                }
119            }
120            _ => Err(Error::TrailingCharacters),
121        }
122    }
123
124    fn end_map(&mut self) -> Result<()> {
125        match self.parse_whitespace().ok_or(Error::EofWhileParsingObject)? {
126            b'}' => {
127                self.eat_char();
128                Ok(())
129            }
130            b',' => Err(Error::TrailingComma),
131            _ => Err(Error::TrailingCharacters),
132        }
133    }
134
135    fn next_char(&mut self) -> Option<u8> {
136        let ch = self.slice.get(self.index);
137
138        if ch.is_some() {
139            self.index += 1;
140        }
141
142        ch.cloned()
143    }
144
145    fn parse_ident(&mut self, ident: &[u8]) -> Result<()> {
146        for c in ident {
147            if Some(*c) != self.next_char() {
148                return Err(Error::ExpectedSomeIdent);
149            }
150        }
151
152        Ok(())
153    }
154
155    fn parse_object_colon(&mut self) -> Result<()> {
156        match self.parse_whitespace().ok_or(Error::EofWhileParsingObject)? {
157            b':' => {
158                self.eat_char();
159                Ok(())
160            }
161            _ => Err(Error::ExpectedColon),
162        }
163    }
164
165    fn parse_str(&mut self) -> Result<&'a str> {
166        let start = self.index;
167        loop {
168            match self.peek() {
169                Some(b'"') => {
170                    // Counts the number of backslashes in front of the current index.
171                    //
172                    // "some string with \\\" included."
173                    //                  ^^^^^
174                    //                  |||||
175                    //       loop run:  4321|
176                    //                      |
177                    //                   `index`
178                    //
179                    // Since we only get in this code branch if we found a " starting the string and `index` is greater
180                    // than the start position, we know the loop will end no later than this point.
181                    let leading_backslashes = |index: usize| -> usize {
182                        let mut count = 0;
183                        loop {
184                            if self.slice[index - count - 1] == b'\\' {
185                                count += 1;
186                            } else {
187                                return count;
188                            }
189                        }
190                    };
191
192                    let is_escaped = leading_backslashes(self.index) % 2 == 1;
193                    if is_escaped {
194                        self.eat_char(); // just continue
195                    } else {
196                        let end = self.index;
197                        self.eat_char();
198                        return str::from_utf8(&self.slice[start..end])
199                            .map_err(|_| Error::InvalidUnicodeCodePoint);
200                    }
201                }
202                Some(_) => self.eat_char(),
203                None => return Err(Error::EofWhileParsingString),
204            }
205        }
206    }
207
208    /// Consumes all the whitespace characters and returns a peek into the next character
209    fn parse_whitespace(&mut self) -> Option<u8> {
210        loop {
211            match self.peek() {
212                Some(b' ') | Some(b'\n') | Some(b'\t') | Some(b'\r') => {
213                    self.eat_char();
214                }
215                other => {
216                    return other;
217                }
218            }
219        }
220    }
221
222    fn peek(&mut self) -> Option<u8> {
223        self.slice.get(self.index).cloned()
224    }
225}
226
227// NOTE(deserialize_*signed) we avoid parsing into u64 and then casting to a smaller integer, which
228// is what upstream does, to avoid pulling in 64-bit compiler intrinsics, which waste a few KBs of
229// Flash, when targeting non 64-bit architectures
230macro_rules! deserialize_unsigned {
231    ($self:ident, $visitor:ident, $uxx:ident, $visit_uxx:ident) => {{
232        let peek = $self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
233
234        match peek {
235            b'-' => Err(Error::InvalidNumber),
236            b'0' => {
237                $self.eat_char();
238                $visitor.$visit_uxx(0)
239            }
240            b'1'..=b'9' => {
241                $self.eat_char();
242
243                let mut number = (peek - b'0') as $uxx;
244                loop {
245                    match $self.peek() {
246                        Some(c @ b'0'..=b'9') => {
247                            $self.eat_char();
248                            number = number
249                                .checked_mul(10)
250                                .ok_or(Error::InvalidNumber)?
251                                .checked_add((c - b'0') as $uxx)
252                                .ok_or(Error::InvalidNumber)?;
253                        }
254                        _ => return $visitor.$visit_uxx(number),
255                    }
256                }
257            }
258            _ => Err(Error::InvalidType),
259        }
260    }};
261}
262
263macro_rules! deserialize_signed {
264    ($self:ident, $visitor:ident, $ixx:ident, $visit_ixx:ident) => {{
265        let signed = match $self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
266            b'-' => {
267                $self.eat_char();
268                true
269            }
270            _ => false,
271        };
272
273        match $self.peek().ok_or(Error::EofWhileParsingValue)? {
274            b'0' => {
275                $self.eat_char();
276                $visitor.$visit_ixx(0)
277            }
278            c @ b'1'..=b'9' => {
279                $self.eat_char();
280
281                let mut number = (c - b'0') as $ixx * if signed { -1 } else { 1 };
282                loop {
283                    match $self.peek() {
284                        Some(c @ b'0'..=b'9') => {
285                            $self.eat_char();
286                            number = number
287                                .checked_mul(10)
288                                .ok_or(Error::InvalidNumber)?
289                                .checked_add((c - b'0') as $ixx * if signed { -1 } else { 1 })
290                                .ok_or(Error::InvalidNumber)?;
291                        }
292                        _ => return $visitor.$visit_ixx(number),
293                    }
294                }
295            }
296            _ => return Err(Error::InvalidType),
297        }
298    }};
299}
300
301macro_rules! deserialize_fromstr {
302    ($self:ident, $visitor:ident, $typ:ident, $visit_fn:ident, $pattern:expr) => {{
303        let start = $self.index;
304        while $self.peek().is_some() {
305            let c = $self.peek().unwrap();
306            if $pattern.iter().find(|&&d| d == c).is_some() {
307                $self.eat_char();
308            } else {
309                break;
310            }
311        }
312
313        // Note(unsafe): We already checked that it only contains ascii. This is only true if the
314        // caller has guaranteed that `pattern` contains only ascii characters.
315        let s = unsafe { str::from_utf8_unchecked(&$self.slice[start..$self.index]) };
316
317        let v = $typ::from_str(s).or(Err(Error::InvalidNumber))?;
318
319        $visitor.$visit_fn(v)
320    }};
321}
322
323impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
324    type Error = Error;
325
326    /// Unsupported. Can’t parse a value without knowing its expected type.
327    fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
328    where
329        V: Visitor<'de>,
330    {
331        unreachable!()
332    }
333
334    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
335    where
336        V: Visitor<'de>,
337    {
338        let peek = self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
339
340        match peek {
341            b't' => {
342                self.eat_char();
343                self.parse_ident(b"rue")?;
344                visitor.visit_bool(true)
345            }
346            b'f' => {
347                self.eat_char();
348                self.parse_ident(b"alse")?;
349                visitor.visit_bool(false)
350            }
351            _ => Err(Error::InvalidType),
352        }
353    }
354
355    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
356    where
357        V: Visitor<'de>,
358    {
359        deserialize_signed!(self, visitor, i8, visit_i8)
360    }
361
362    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
363    where
364        V: Visitor<'de>,
365    {
366        deserialize_signed!(self, visitor, i16, visit_i16)
367    }
368
369    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
370    where
371        V: Visitor<'de>,
372    {
373        deserialize_signed!(self, visitor, i32, visit_i32)
374    }
375
376    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
377    where
378        V: Visitor<'de>,
379    {
380        deserialize_signed!(self, visitor, i64, visit_i64)
381    }
382
383    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
384    where
385        V: Visitor<'de>,
386    {
387        deserialize_unsigned!(self, visitor, u8, visit_u8)
388    }
389
390    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
391    where
392        V: Visitor<'de>,
393    {
394        deserialize_unsigned!(self, visitor, u16, visit_u16)
395    }
396
397    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
398    where
399        V: Visitor<'de>,
400    {
401        deserialize_unsigned!(self, visitor, u32, visit_u32)
402    }
403
404    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
405    where
406        V: Visitor<'de>,
407    {
408        deserialize_unsigned!(self, visitor, u64, visit_u64)
409    }
410
411    fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
412    where
413        V: Visitor<'de>,
414    {
415        self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
416        deserialize_fromstr!(self, visitor, f32, visit_f32, b"0123456789+-.eE")
417    }
418
419    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
420    where
421        V: Visitor<'de>,
422    {
423        self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
424        deserialize_fromstr!(self, visitor, f64, visit_f64, b"0123456789+-.eE")
425    }
426
427    fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value>
428    where
429        V: Visitor<'de>,
430    {
431        unreachable!()
432    }
433
434    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
435    where
436        V: Visitor<'de>,
437    {
438        let peek = self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
439
440        match peek {
441            b'"' => {
442                self.eat_char();
443                visitor.visit_borrowed_str(self.parse_str()?)
444            }
445            _ => Err(Error::InvalidType),
446        }
447    }
448
449    /// Unsupported. String is not available in no-std.
450    fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value>
451    where
452        V: Visitor<'de>,
453    {
454        unreachable!()
455    }
456
457    /// Unsupported
458    fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
459    where
460        V: Visitor<'de>,
461    {
462        unreachable!()
463    }
464
465    /// Unsupported
466    fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value>
467    where
468        V: Visitor<'de>,
469    {
470        unreachable!()
471    }
472
473    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
474    where
475        V: Visitor<'de>,
476    {
477        match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
478            b'n' => {
479                self.eat_char();
480                self.parse_ident(b"ull")?;
481                visitor.visit_none()
482            }
483            _ => visitor.visit_some(self),
484        }
485    }
486
487    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
488    where
489        V: Visitor<'de>,
490    {
491        let peek = match self.parse_whitespace() {
492            Some(b) => b,
493            None => {
494                return Err(Error::EofWhileParsingValue);
495            }
496        };
497
498        match peek {
499            b'n' => {
500                self.eat_char();
501                self.parse_ident(b"ull")?;
502                visitor.visit_unit()
503            }
504            _ => Err(Error::InvalidType),
505        }
506    }
507
508    fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
509    where
510        V: Visitor<'de>,
511    {
512        self.deserialize_unit(visitor)
513    }
514
515    /// Unsupported. We can’t parse newtypes because we don’t know the underlying type.
516    fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
517    where
518        V: Visitor<'de>,
519    {
520        visitor.visit_newtype_struct(self)
521    }
522
523    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
524    where
525        V: Visitor<'de>,
526    {
527        match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
528            b'[' => {
529                self.eat_char();
530                let ret = visitor.visit_seq(SeqAccess::new(self))?;
531
532                self.end_seq()?;
533
534                Ok(ret)
535            }
536            _ => Err(Error::InvalidType),
537        }
538    }
539
540    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
541    where
542        V: Visitor<'de>,
543    {
544        self.deserialize_seq(visitor)
545    }
546
547    fn deserialize_tuple_struct<V>(
548        self,
549        _name: &'static str,
550        _len: usize,
551        visitor: V,
552    ) -> Result<V::Value>
553    where
554        V: Visitor<'de>,
555    {
556        self.deserialize_seq(visitor)
557    }
558
559    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
560    where
561        V: Visitor<'de>,
562    {
563        let peek = self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
564
565        if peek == b'{' {
566            self.eat_char();
567
568            let ret = visitor.visit_map(MapAccess::new(self))?;
569
570            self.end_map()?;
571
572            Ok(ret)
573        } else {
574            Err(Error::InvalidType)
575        }
576    }
577
578    fn deserialize_struct<V>(
579        self,
580        _name: &'static str,
581        _fields: &'static [&'static str],
582        visitor: V,
583    ) -> Result<V::Value>
584    where
585        V: Visitor<'de>,
586    {
587        self.deserialize_map(visitor)
588    }
589
590    fn deserialize_enum<V>(
591        self,
592        _name: &'static str,
593        _variants: &'static [&'static str],
594        visitor: V,
595    ) -> Result<V::Value>
596    where
597        V: Visitor<'de>,
598    {
599        match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
600            b'"' => visitor.visit_enum(UnitVariantAccess::new(self)),
601            b'{' => {
602                self.eat_char();
603                let value = visitor.visit_enum(VariantAccess::new(self))?;
604                match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
605                    b'}' => {
606                        self.eat_char();
607                        Ok(value)
608                    }
609                    _ => Err(Error::ExpectedSomeValue),
610                }
611            }
612            _ => Err(Error::ExpectedSomeValue),
613        }
614    }
615
616    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
617    where
618        V: Visitor<'de>,
619    {
620        self.deserialize_str(visitor)
621    }
622
623    /// Used to throw out fields from JSON objects that we don’t want to
624    /// keep in our structs.
625    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
626    where
627        V: Visitor<'de>,
628    {
629        match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
630            b'"' => self.deserialize_str(visitor),
631            b'[' => self.deserialize_seq(visitor),
632            b'{' => self.deserialize_struct("ignored", &[], visitor),
633            b',' | b'}' | b']' => Err(Error::ExpectedSomeValue),
634            // If it’s something else then we chomp until we get to an end delimiter.
635            // This does technically allow for illegal JSON since we’re just ignoring
636            // characters rather than parsing them.
637            _ => loop {
638                match self.peek() {
639                    // The visitor is expected to be UnknownAny’s visitor, which
640                    // implements visit_unit to return its unit Ok result.
641                    Some(b',') | Some(b'}') | Some(b']') => break visitor.visit_unit(),
642                    Some(_) => self.eat_char(),
643                    None => break Err(Error::EofWhileParsingString),
644                }
645            },
646        }
647    }
648}
649
650impl de::Error for Error {
651    #[cfg_attr(not(feature = "custom-error-messages"), allow(unused_variables))]
652    fn custom<T>(msg: T) -> Self
653    where
654        T: fmt::Display,
655    {
656        #[cfg(not(feature = "custom-error-messages"))]
657        {
658            Error::CustomError
659        }
660        #[cfg(feature = "custom-error-messages")]
661        {
662            use core::fmt::Write;
663
664            let mut string = heapless::String::new();
665            write!(string, "{:.64}", msg).unwrap();
666            Error::CustomErrorWithMessage(string)
667        }
668    }
669}
670
671impl fmt::Display for Error {
672    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
673        write!(
674            f,
675            "{}",
676            match self {
677                Error::EofWhileParsingList => "EOF while parsing a list.",
678                Error::EofWhileParsingObject => "EOF while parsing an object.",
679                Error::EofWhileParsingString => "EOF while parsing a string.",
680                Error::EofWhileParsingValue => "EOF while parsing a JSON value.",
681                Error::ExpectedColon => "Expected this character to be a `':'`.",
682                Error::ExpectedListCommaOrEnd => {
683                    "Expected this character to be either a `','` or\
684                     a \
685                     `']'`."
686                }
687                Error::ExpectedObjectCommaOrEnd => {
688                    "Expected this character to be either a `','` \
689                     or a \
690                     `'}'`."
691                }
692                Error::ExpectedSomeIdent => {
693                    "Expected to parse either a `true`, `false`, or a \
694                     `null`."
695                }
696                Error::ExpectedSomeValue => "Expected this character to start a JSON value.",
697                Error::InvalidNumber => "Invalid number.",
698                Error::InvalidType => "Invalid type",
699                Error::InvalidUnicodeCodePoint => "Invalid unicode code point.",
700                Error::KeyMustBeAString => "Object key is not a string.",
701                Error::TrailingCharacters => {
702                    "JSON has non-whitespace trailing characters after \
703                     the \
704                     value."
705                }
706                Error::TrailingComma => "JSON has a comma after the last value in an array or map.",
707                Error::CustomError => "JSON does not match deserializer’s expected format.",
708                #[cfg(feature = "custom-error-messages")]
709                Error::CustomErrorWithMessage(msg) => msg.as_str(),
710                _ => "Invalid JSON",
711            }
712        )
713    }
714}
715
716/// Deserializes an instance of type `T` from bytes of JSON text
717/// Returns the value and the number of bytes consumed in the process
718pub fn from_slice<'a, T>(v: &'a [u8]) -> Result<(T, usize)>
719where
720    T: de::Deserialize<'a>,
721{
722    let mut de = Deserializer::new(v);
723    let value = de::Deserialize::deserialize(&mut de)?;
724    let length = de.end()?;
725
726    Ok((value, length))
727}
728
729/// Deserializes an instance of type T from a string of JSON text
730pub fn from_str<'a, T>(s: &'a str) -> Result<(T, usize)>
731where
732    T: de::Deserialize<'a>,
733{
734    from_slice(s.as_bytes())
735}
736
737#[cfg(test)]
738mod tests {
739    use serde_derive::Deserialize;
740
741    #[derive(Debug, Deserialize, PartialEq)]
742    enum Type {
743        #[serde(rename = "boolean")]
744        Boolean,
745        #[serde(rename = "number")]
746        Number,
747        #[serde(rename = "thing")]
748        Thing,
749    }
750
751    #[test]
752    fn array() {
753        assert_eq!(crate::from_str::<[i32; 0]>("[]"), Ok(([], 2)));
754        assert_eq!(crate::from_str("[0, 1, 2]"), Ok(([0, 1, 2], 9)));
755
756        // errors
757        assert!(crate::from_str::<[i32; 2]>("[0, 1,]").is_err());
758    }
759
760    #[test]
761    fn bool() {
762        assert_eq!(crate::from_str("true"), Ok((true, 4)));
763        assert_eq!(crate::from_str(" true"), Ok((true, 5)));
764        assert_eq!(crate::from_str("true "), Ok((true, 5)));
765
766        assert_eq!(crate::from_str("false"), Ok((false, 5)));
767        assert_eq!(crate::from_str(" false"), Ok((false, 6)));
768        assert_eq!(crate::from_str("false "), Ok((false, 6)));
769
770        // errors
771        assert!(crate::from_str::<bool>("true false").is_err());
772        assert!(crate::from_str::<bool>("tru").is_err());
773    }
774
775    #[test]
776    fn floating_point() {
777        assert_eq!(crate::from_str("5.0"), Ok((5.0, 3)));
778        assert_eq!(crate::from_str("1"), Ok((1.0, 1)));
779        assert_eq!(crate::from_str("1e5"), Ok((1e5, 3)));
780        assert!(crate::from_str::<f32>("a").is_err());
781        assert!(crate::from_str::<f32>(",").is_err());
782    }
783
784    #[test]
785    fn integer() {
786        assert_eq!(crate::from_str("5"), Ok((5, 1)));
787        assert_eq!(crate::from_str("101"), Ok((101, 3)));
788        assert!(crate::from_str::<u16>("1e5").is_err());
789        assert!(crate::from_str::<u8>("256").is_err());
790        assert!(crate::from_str::<f32>(",").is_err());
791    }
792
793    #[test]
794    fn enum_clike() {
795        assert_eq!(crate::from_str(r#" "boolean" "#), Ok((Type::Boolean, 11)));
796        assert_eq!(crate::from_str(r#" "number" "#), Ok((Type::Number, 10)));
797        assert_eq!(crate::from_str(r#" "thing" "#), Ok((Type::Thing, 9)));
798    }
799
800    #[test]
801    fn str() {
802        assert_eq!(crate::from_str(r#" "hello" "#), Ok(("hello", 9)));
803        assert_eq!(crate::from_str(r#" "" "#), Ok(("", 4)));
804        assert_eq!(crate::from_str(r#" " " "#), Ok((" ", 5)));
805        assert_eq!(crate::from_str(r#" "👏" "#), Ok(("👏", 8)));
806
807        // no unescaping is done (as documented as a known issue in lib.rs)
808        assert_eq!(crate::from_str(r#" "hel\tlo" "#), Ok(("hel\\tlo", 11)));
809        assert_eq!(crate::from_str(r#" "hello \\" "#), Ok(("hello \\\\", 12)));
810
811        // escaped " in the string content
812        assert_eq!(crate::from_str(r#" "foo\"bar" "#), Ok((r#"foo\"bar"#, 12)));
813        assert_eq!(crate::from_str(r#" "foo\\\"bar" "#), Ok((r#"foo\\\"bar"#, 14)));
814        assert_eq!(crate::from_str(r#" "foo\"\"bar" "#), Ok((r#"foo\"\"bar"#, 14)));
815        assert_eq!(crate::from_str(r#" "\"bar" "#), Ok((r#"\"bar"#, 9)));
816        assert_eq!(crate::from_str(r#" "foo\"" "#), Ok((r#"foo\""#, 9)));
817        assert_eq!(crate::from_str(r#" "\"" "#), Ok((r#"\""#, 6)));
818
819        // non-excaped " preceded by backslashes
820        assert_eq!(crate::from_str(r#" "foo bar\\" "#), Ok((r#"foo bar\\"#, 13)));
821        assert_eq!(crate::from_str(r#" "foo bar\\\\" "#), Ok((r#"foo bar\\\\"#, 15)));
822        assert_eq!(crate::from_str(r#" "foo bar\\\\\\" "#), Ok((r#"foo bar\\\\\\"#, 17)));
823        assert_eq!(crate::from_str(r#" "foo bar\\\\\\\\" "#), Ok((r#"foo bar\\\\\\\\"#, 19)));
824        assert_eq!(crate::from_str(r#" "\\" "#), Ok((r#"\\"#, 6)));
825    }
826
827    #[test]
828    fn struct_bool() {
829        #[derive(Debug, Deserialize, PartialEq)]
830        struct Led {
831            led: bool,
832        }
833
834        assert_eq!(crate::from_str(r#"{ "led": true }"#), Ok((Led { led: true }, 15)));
835        assert_eq!(crate::from_str(r#"{ "led": false }"#), Ok((Led { led: false }, 16)));
836    }
837
838    #[test]
839    fn struct_i8() {
840        #[derive(Debug, Deserialize, PartialEq)]
841        struct Temperature {
842            temperature: i8,
843        }
844
845        assert_eq!(
846            crate::from_str(r#"{ "temperature": -17 }"#),
847            Ok((Temperature { temperature: -17 }, 22))
848        );
849
850        assert_eq!(
851            crate::from_str(r#"{ "temperature": -0 }"#),
852            Ok((Temperature { temperature: -0 }, 21))
853        );
854
855        assert_eq!(
856            crate::from_str(r#"{ "temperature": 0 }"#),
857            Ok((Temperature { temperature: 0 }, 20))
858        );
859
860        // out of range
861        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 128 }"#).is_err());
862        assert!(crate::from_str::<Temperature>(r#"{ "temperature": -129 }"#).is_err());
863    }
864
865    #[test]
866    fn struct_f32() {
867        #[derive(Debug, Deserialize, PartialEq)]
868        struct Temperature {
869            temperature: f32,
870        }
871
872        assert_eq!(
873            crate::from_str(r#"{ "temperature": -17.2 }"#),
874            Ok((Temperature { temperature: -17.2 }, 24))
875        );
876
877        assert_eq!(
878            crate::from_str(r#"{ "temperature": -0.0 }"#),
879            Ok((Temperature { temperature: -0. }, 23))
880        );
881
882        assert_eq!(
883            crate::from_str(r#"{ "temperature": -2.1e-3 }"#),
884            Ok((Temperature { temperature: -2.1e-3 }, 26))
885        );
886
887        assert_eq!(
888            crate::from_str(r#"{ "temperature": -3 }"#),
889            Ok((Temperature { temperature: -3. }, 21))
890        );
891
892        use core::f32;
893
894        assert_eq!(
895            crate::from_str(r#"{ "temperature": -1e500 }"#),
896            Ok((Temperature { temperature: f32::NEG_INFINITY }, 25))
897        );
898
899        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 1e1e1 }"#).is_err());
900        assert!(crate::from_str::<Temperature>(r#"{ "temperature": -2-2 }"#).is_err());
901        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 1 1 }"#).is_err());
902        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 0.0. }"#).is_err());
903        assert!(crate::from_str::<Temperature>(r#"{ "temperature": ä }"#).is_err());
904    }
905
906    #[test]
907    fn struct_option() {
908        #[derive(Debug, Deserialize, PartialEq)]
909        struct Property<'a> {
910            #[serde(borrow)]
911            description: Option<&'a str>,
912        }
913
914        assert_eq!(
915            crate::from_str(r#"{ "description": "An ambient temperature sensor" }"#),
916            Ok((Property { description: Some("An ambient temperature sensor") }, 50))
917        );
918
919        assert_eq!(
920            crate::from_str(r#"{ "description": null }"#),
921            Ok((Property { description: None }, 23))
922        );
923
924        assert_eq!(crate::from_str(r#"{}"#), Ok((Property { description: None }, 2)));
925    }
926
927    #[test]
928    fn struct_u8() {
929        #[derive(Debug, Deserialize, PartialEq)]
930        struct Temperature {
931            temperature: u8,
932        }
933
934        assert_eq!(
935            crate::from_str(r#"{ "temperature": 20 }"#),
936            Ok((Temperature { temperature: 20 }, 21))
937        );
938
939        assert_eq!(
940            crate::from_str(r#"{ "temperature": 0 }"#),
941            Ok((Temperature { temperature: 0 }, 20))
942        );
943
944        // out of range
945        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 256 }"#).is_err());
946        assert!(crate::from_str::<Temperature>(r#"{ "temperature": -1 }"#).is_err());
947    }
948
949    #[test]
950    fn test_unit() {
951        assert_eq!(crate::from_str::<()>(r#"null"#), Ok(((), 4)));
952    }
953
954    #[test]
955    fn newtype_struct() {
956        #[derive(Deserialize, Debug, PartialEq)]
957        struct A(pub u32);
958
959        assert_eq!(crate::from_str::<A>(r#"54"#), Ok((A(54), 2)));
960    }
961
962    #[test]
963    fn test_newtype_variant() {
964        #[derive(Deserialize, Debug, PartialEq)]
965        enum A {
966            A(u32),
967        }
968        let a = A::A(54);
969        let x = crate::from_str::<A>(r#"{"A":54}"#);
970        assert_eq!(x, Ok((a, 8)));
971    }
972
973    #[test]
974    fn test_struct_variant() {
975        #[derive(Deserialize, Debug, PartialEq)]
976        enum A {
977            A { x: u32, y: u16 },
978        }
979        let a = A::A { x: 54, y: 720 };
980        let x = crate::from_str::<A>(r#"{"A": {"x":54,"y":720 } }"#);
981        assert_eq!(x, Ok((a, 25)));
982    }
983
984    #[test]
985    #[cfg(not(feature = "custom-error-messages"))]
986    fn struct_tuple() {
987        #[derive(Debug, Deserialize, PartialEq)]
988        struct Xy(i8, i8);
989
990        assert_eq!(crate::from_str(r#"[10, 20]"#), Ok((Xy(10, 20), 8)));
991        assert_eq!(crate::from_str(r#"[10, -20]"#), Ok((Xy(10, -20), 9)));
992
993        // wrong number of args
994        assert_eq!(crate::from_str::<Xy>(r#"[10]"#), Err(crate::de::Error::CustomError));
995        assert_eq!(
996            crate::from_str::<Xy>(r#"[10, 20, 30]"#),
997            Err(crate::de::Error::TrailingCharacters)
998        );
999    }
1000
1001    #[test]
1002    #[cfg(feature = "custom-error-messages")]
1003    fn struct_tuple() {
1004        #[derive(Debug, Deserialize, PartialEq)]
1005        struct Xy(i8, i8);
1006
1007        assert_eq!(crate::from_str(r#"[10, 20]"#), Ok((Xy(10, 20), 8)));
1008        assert_eq!(crate::from_str(r#"[10, -20]"#), Ok((Xy(10, -20), 9)));
1009
1010        // wrong number of args
1011        assert_eq!(
1012            crate::from_str::<Xy>(r#"[10]"#),
1013            Err(crate::de::Error::CustomErrorWithMessage(
1014                "invalid length 1, expected tuple struct Xy with 2 elements".into()
1015            ))
1016        );
1017        assert_eq!(
1018            crate::from_str::<Xy>(r#"[10, 20, 30]"#),
1019            Err(crate::de::Error::TrailingCharacters)
1020        );
1021    }
1022
1023    #[test]
1024    fn ignoring_extra_fields() {
1025        #[derive(Debug, Deserialize, PartialEq)]
1026        struct Temperature {
1027            temperature: u8,
1028        }
1029
1030        assert_eq!(
1031            crate::from_str(r#"{ "temperature": 20, "high": 80, "low": -10, "updated": true }"#),
1032            Ok((Temperature { temperature: 20 }, 62))
1033        );
1034
1035        assert_eq!(
1036            crate::from_str(
1037                r#"{ "temperature": 20, "conditions": "windy", "forecast": "cloudy" }"#
1038            ),
1039            Ok((Temperature { temperature: 20 }, 66))
1040        );
1041
1042        assert_eq!(
1043            crate::from_str(r#"{ "temperature": 20, "hourly_conditions": ["windy", "rainy"] }"#),
1044            Ok((Temperature { temperature: 20 }, 62))
1045        );
1046
1047        assert_eq!(
1048            crate::from_str(
1049                r#"{ "temperature": 20, "source": { "station": "dock", "sensors": ["front", "back"] } }"#
1050            ),
1051            Ok((Temperature { temperature: 20 }, 84))
1052        );
1053
1054        assert_eq!(
1055            crate::from_str(r#"{ "temperature": 20, "invalid": this-is-ignored }"#),
1056            Ok((Temperature { temperature: 20 }, 49))
1057        );
1058
1059        assert_eq!(
1060            crate::from_str::<Temperature>(r#"{ "temperature": 20, "broken": }"#),
1061            Err(crate::de::Error::ExpectedSomeValue)
1062        );
1063
1064        assert_eq!(
1065            crate::from_str::<Temperature>(r#"{ "temperature": 20, "broken": [ }"#),
1066            Err(crate::de::Error::ExpectedSomeValue)
1067        );
1068
1069        assert_eq!(
1070            crate::from_str::<Temperature>(r#"{ "temperature": 20, "broken": ] }"#),
1071            Err(crate::de::Error::ExpectedSomeValue)
1072        );
1073    }
1074
1075    #[test]
1076    #[cfg(feature = "custom-error-messages")]
1077    fn preserve_short_error_message() {
1078        use serde::de::Error;
1079        assert_eq!(
1080            crate::de::Error::custom("something bad happened"),
1081            crate::de::Error::CustomErrorWithMessage("something bad happened".into())
1082        );
1083    }
1084
1085    #[test]
1086    #[cfg(feature = "custom-error-messages")]
1087    fn truncate_error_message() {
1088        use serde::de::Error;
1089        assert_eq!(
1090            crate::de::Error::custom("0123456789012345678901234567890123456789012345678901234567890123 <- after here the message should be truncated"),
1091            crate::de::Error::CustomErrorWithMessage(
1092                "0123456789012345678901234567890123456789012345678901234567890123".into()
1093            )
1094        );
1095    }
1096
1097    // See https://iot.mozilla.org/wot/#thing-resource
1098    #[test]
1099    fn wot() {
1100        #[derive(Debug, Deserialize, PartialEq)]
1101        struct Thing<'a> {
1102            #[serde(borrow)]
1103            properties: Properties<'a>,
1104            #[serde(rename = "type")]
1105            ty: Type,
1106        }
1107
1108        #[derive(Debug, Deserialize, PartialEq)]
1109        struct Properties<'a> {
1110            #[serde(borrow)]
1111            temperature: Property<'a>,
1112            #[serde(borrow)]
1113            humidity: Property<'a>,
1114            #[serde(borrow)]
1115            led: Property<'a>,
1116        }
1117
1118        #[derive(Debug, Deserialize, PartialEq)]
1119        struct Property<'a> {
1120            #[serde(rename = "type")]
1121            ty: Type,
1122            unit: Option<&'a str>,
1123            #[serde(borrow)]
1124            description: Option<&'a str>,
1125            href: &'a str,
1126        }
1127
1128        assert_eq!(
1129            crate::from_str::<Thing<'_>>(
1130                r#"
1131                    {
1132                    "type": "thing",
1133                    "properties": {
1134                        "temperature": {
1135                        "type": "number",
1136                        "unit": "celsius",
1137                        "description": "An ambient temperature sensor",
1138                        "href": "/properties/temperature"
1139                        },
1140                        "humidity": {
1141                        "type": "number",
1142                        "unit": "percent",
1143                        "href": "/properties/humidity"
1144                        },
1145                        "led": {
1146                        "type": "boolean",
1147                        "description": "A red LED",
1148                        "href": "/properties/led"
1149                        }
1150                    }
1151                    }
1152                    "#
1153            ),
1154            Ok((
1155                Thing {
1156                    properties: Properties {
1157                        temperature: Property {
1158                            ty: Type::Number,
1159                            unit: Some("celsius"),
1160                            description: Some("An ambient temperature sensor"),
1161                            href: "/properties/temperature",
1162                        },
1163                        humidity: Property {
1164                            ty: Type::Number,
1165                            unit: Some("percent"),
1166                            description: None,
1167                            href: "/properties/humidity",
1168                        },
1169                        led: Property {
1170                            ty: Type::Boolean,
1171                            unit: None,
1172                            description: Some("A red LED"),
1173                            href: "/properties/led",
1174                        },
1175                    },
1176                    ty: Type::Thing,
1177                },
1178                852
1179            ))
1180        )
1181    }
1182}