pink_json/de/
mod.rs

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