Skip to main content

serde_json_core/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};
7use serde::Serialize;
8
9use self::enum_::{UnitVariantAccess, VariantAccess};
10use self::map::MapAccess;
11use self::seq::SeqAccess;
12
13mod enum_;
14mod map;
15mod seq;
16
17/// Deserialization result
18pub type Result<T> = core::result::Result<T, Error>;
19
20/// This type represents all possible errors that can occur when deserializing JSON data
21#[derive(Debug, PartialEq, Eq, Clone, Serialize)]
22#[cfg_attr(not(feature = "custom-error-messages"), derive(Copy))]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24#[non_exhaustive]
25pub enum Error {
26    /// Can’t parse a value without knowing its expected type.
27    AnyIsUnsupported,
28
29    /// Cannot parse a sequence of bytes.
30    BytesIsUnsupported,
31
32    /// EOF while parsing a list.
33    EofWhileParsingList,
34
35    /// EOF while parsing an object.
36    EofWhileParsingObject,
37
38    /// EOF while parsing a string.
39    EofWhileParsingString,
40
41    /// EOF while parsing a JSON number.
42    EofWhileParsingNumber,
43
44    /// EOF while parsing a JSON value.
45    EofWhileParsingValue,
46
47    /// Expected this character to be a `':'`.
48    ExpectedColon,
49
50    /// Expected this character to be either a `','` or a `']'`.
51    ExpectedListCommaOrEnd,
52
53    /// Expected this character to be either a `','` or a `'}'`.
54    ExpectedObjectCommaOrEnd,
55
56    /// Expected to parse either a `true`, `false`, or a `null`.
57    ExpectedSomeIdent,
58
59    /// Expected this character to start a JSON value.
60    ExpectedSomeValue,
61
62    /// Invalid number.
63    InvalidNumber,
64
65    /// Invalid type
66    InvalidType,
67
68    /// Invalid unicode code point.
69    InvalidUnicodeCodePoint,
70
71    /// Invalid String Escape Sequence
72    InvalidEscapeSequence,
73
74    /// Escaped String length exceeds buffer size
75    EscapedStringIsTooLong,
76
77    /// Object key is not a string.
78    KeyMustBeAString,
79
80    /// JSON has non-whitespace trailing characters after the value.
81    TrailingCharacters,
82
83    /// JSON has a comma after the last value in an array or map.
84    TrailingComma,
85
86    /// Error with a custom message that we had to discard.
87    CustomError,
88
89    /// Error with a custom message that was preserved.
90    #[cfg(feature = "custom-error-messages")]
91    CustomErrorWithMessage(
92        #[cfg_attr(feature = "defmt", defmt(Debug2Format))] heapless::String<64>,
93    ),
94}
95
96impl serde::de::StdError for Error {}
97
98impl From<crate::str::StringUnescapeError> for Error {
99    fn from(error: crate::str::StringUnescapeError) -> Self {
100        match error {
101            crate::str::StringUnescapeError::InvalidEscapeSequence => Self::InvalidEscapeSequence,
102        }
103    }
104}
105
106/// A structure that deserializes Rust values from JSON in a buffer.
107pub struct Deserializer<'b, 's> {
108    slice: &'b [u8],
109    index: usize,
110    string_unescape_buffer: Option<&'s mut [u8]>,
111}
112
113impl<'a, 's> Deserializer<'a, 's> {
114    /// Create a new `Deserializer`, optionally with a buffer to use to unescape strings.
115    /// If not present, strings are not unescaped.
116    pub fn new(
117        slice: &'a [u8],
118        string_unescape_buffer: Option<&'s mut [u8]>,
119    ) -> Deserializer<'a, 's> {
120        Deserializer {
121            slice,
122            index: 0,
123            string_unescape_buffer,
124        }
125    }
126
127    fn eat_char(&mut self) {
128        self.index += 1;
129    }
130
131    /// Check whether there is any unexpected data left in the buffer
132    /// and return the amount of data consumed
133    pub fn end(&mut self) -> Result<usize> {
134        match self.parse_whitespace() {
135            Some(_) => Err(Error::TrailingCharacters),
136            None => Ok(self.index),
137        }
138    }
139
140    fn end_seq(&mut self) -> Result<()> {
141        match self.parse_whitespace().ok_or(Error::EofWhileParsingList)? {
142            b']' => {
143                self.eat_char();
144                Ok(())
145            }
146            b',' => {
147                self.eat_char();
148                match self.parse_whitespace() {
149                    Some(b']') => Err(Error::TrailingComma),
150                    _ => Err(Error::TrailingCharacters),
151                }
152            }
153            _ => Err(Error::TrailingCharacters),
154        }
155    }
156
157    fn end_map(&mut self) -> Result<()> {
158        match self
159            .parse_whitespace()
160            .ok_or(Error::EofWhileParsingObject)?
161        {
162            b'}' => {
163                self.eat_char();
164                Ok(())
165            }
166            b',' => Err(Error::TrailingComma),
167            _ => Err(Error::TrailingCharacters),
168        }
169    }
170
171    fn next_char(&mut self) -> Option<u8> {
172        let ch = self.slice.get(self.index);
173
174        if ch.is_some() {
175            self.index += 1;
176        }
177
178        ch.cloned()
179    }
180
181    fn parse_ident(&mut self, ident: &[u8]) -> Result<()> {
182        for c in ident {
183            if Some(*c) != self.next_char() {
184                return Err(Error::ExpectedSomeIdent);
185            }
186        }
187
188        Ok(())
189    }
190
191    fn parse_object_colon(&mut self) -> Result<()> {
192        match self
193            .parse_whitespace()
194            .ok_or(Error::EofWhileParsingObject)?
195        {
196            b':' => {
197                self.eat_char();
198                Ok(())
199            }
200            _ => Err(Error::ExpectedColon),
201        }
202    }
203
204    /// Parse a string, returning the escaped string.
205    fn parse_str(&mut self) -> Result<&'a str> {
206        if self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? == b'"' {
207            self.eat_char();
208        } else {
209            return Err(Error::InvalidType);
210        }
211
212        let start = self.index;
213        loop {
214            match self.peek() {
215                Some(b'"') => {
216                    // Counts the number of backslashes in front of the current index.
217                    //
218                    // "some string with \\\" included."
219                    //                  ^^^^^
220                    //                  |||||
221                    //       loop run:  4321|
222                    //                      |
223                    //                   `index`
224                    //
225                    // Since we only get in this code branch if we found a " starting the string and `index` is greater
226                    // than the start position, we know the loop will end no later than this point.
227                    let leading_backslashes = |index: usize| -> usize {
228                        let mut count = 0;
229                        loop {
230                            if self.slice[index - count - 1] == b'\\' {
231                                count += 1;
232                            } else {
233                                return count;
234                            }
235                        }
236                    };
237
238                    let is_escaped = leading_backslashes(self.index) % 2 == 1;
239                    if is_escaped {
240                        self.eat_char(); // just continue
241                    } else {
242                        let end = self.index;
243                        self.eat_char();
244
245                        return str::from_utf8(&self.slice[start..end])
246                            .map_err(|_| Error::InvalidUnicodeCodePoint);
247                    }
248                }
249                Some(_) => self.eat_char(),
250                None => return Err(Error::EofWhileParsingString),
251            }
252        }
253    }
254
255    /// Consumes all the whitespace characters and returns a peek into the next character
256    fn parse_whitespace(&mut self) -> Option<u8> {
257        loop {
258            match self.peek() {
259                Some(b' ') | Some(b'\n') | Some(b'\t') | Some(b'\r') => {
260                    self.eat_char();
261                }
262                other => {
263                    return other;
264                }
265            }
266        }
267    }
268
269    fn peek(&mut self) -> Option<u8> {
270        self.slice.get(self.index).cloned()
271    }
272}
273
274// NOTE(deserialize_*signed) we avoid parsing into u64 and then casting to a smaller integer, which
275// is what upstream does, to avoid pulling in 64-bit compiler intrinsics, which waste a few KBs of
276// Flash, when targeting non 64-bit architectures
277macro_rules! deserialize_unsigned {
278    ($self:ident, $visitor:ident, $uxx:ident, $visit_uxx:ident) => {{
279        let peek = $self
280            .parse_whitespace()
281            .ok_or(Error::EofWhileParsingValue)?;
282
283        match peek {
284            b'-' => Err(Error::InvalidNumber),
285            b'0' => {
286                $self.eat_char();
287                $visitor.$visit_uxx(0)
288            }
289            b'1'..=b'9' => {
290                $self.eat_char();
291
292                let mut number = (peek - b'0') as $uxx;
293                loop {
294                    match $self.peek() {
295                        Some(c @ b'0'..=b'9') => {
296                            $self.eat_char();
297                            number = number
298                                .checked_mul(10)
299                                .ok_or(Error::InvalidNumber)?
300                                .checked_add((c - b'0') as $uxx)
301                                .ok_or(Error::InvalidNumber)?;
302                        }
303                        _ => return $visitor.$visit_uxx(number),
304                    }
305                }
306            }
307            _ => Err(Error::InvalidType),
308        }
309    }};
310}
311
312macro_rules! deserialize_signed {
313    ($self:ident, $visitor:ident, $ixx:ident, $visit_ixx:ident) => {{
314        let signed = match $self
315            .parse_whitespace()
316            .ok_or(Error::EofWhileParsingValue)?
317        {
318            b'-' => {
319                $self.eat_char();
320                true
321            }
322            _ => false,
323        };
324
325        match $self.peek().ok_or(Error::EofWhileParsingValue)? {
326            b'0' => {
327                $self.eat_char();
328                $visitor.$visit_ixx(0)
329            }
330            c @ b'1'..=b'9' => {
331                $self.eat_char();
332
333                let mut number = (c - b'0') as $ixx * if signed { -1 } else { 1 };
334                loop {
335                    match $self.peek() {
336                        Some(c @ b'0'..=b'9') => {
337                            $self.eat_char();
338                            number = number
339                                .checked_mul(10)
340                                .ok_or(Error::InvalidNumber)?
341                                .checked_add((c - b'0') as $ixx * if signed { -1 } else { 1 })
342                                .ok_or(Error::InvalidNumber)?;
343                        }
344                        _ => return $visitor.$visit_ixx(number),
345                    }
346                }
347            }
348            _ => return Err(Error::InvalidType),
349        }
350    }};
351}
352
353macro_rules! deserialize_fromstr {
354    ($self:ident, $visitor:ident, $typ:ident, $visit_fn:ident, $pattern:expr) => {{
355        match $self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
356            b'n' => {
357                $self.eat_char();
358                $self.parse_ident(b"ull")?;
359                $visitor.$visit_fn($typ::NAN)
360            }
361            _ => {
362                let start = $self.index;
363                while $self.peek().is_some() {
364                    let c = $self.peek().unwrap();
365                    if $pattern.iter().find(|&&d| d == c).is_some() {
366                        $self.eat_char();
367                    } else {
368                        break;
369                    }
370                }
371
372                // Note(unsafe): We already checked that it only contains ascii. This is only true if the
373                // caller has guaranteed that `pattern` contains only ascii characters.
374                let s = unsafe { str::from_utf8_unchecked(&$self.slice[start..$self.index]) };
375
376                let v = $typ::from_str(s).or(Err(Error::InvalidNumber))?;
377
378                $visitor.$visit_fn(v)
379            }
380        }
381    }};
382}
383
384impl<'de> de::Deserializer<'de> for &mut Deserializer<'de, '_> {
385    type Error = Error;
386
387    /// Unsupported. Can’t parse a value without knowing its expected type.
388    fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
389    where
390        V: Visitor<'de>,
391    {
392        Err(Error::AnyIsUnsupported)
393    }
394
395    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
396    where
397        V: Visitor<'de>,
398    {
399        let peek = self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
400
401        match peek {
402            b't' => {
403                self.eat_char();
404                self.parse_ident(b"rue")?;
405                visitor.visit_bool(true)
406            }
407            b'f' => {
408                self.eat_char();
409                self.parse_ident(b"alse")?;
410                visitor.visit_bool(false)
411            }
412            _ => Err(Error::InvalidType),
413        }
414    }
415
416    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
417    where
418        V: Visitor<'de>,
419    {
420        deserialize_signed!(self, visitor, i8, visit_i8)
421    }
422
423    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
424    where
425        V: Visitor<'de>,
426    {
427        deserialize_signed!(self, visitor, i16, visit_i16)
428    }
429
430    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
431    where
432        V: Visitor<'de>,
433    {
434        deserialize_signed!(self, visitor, i32, visit_i32)
435    }
436
437    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
438    where
439        V: Visitor<'de>,
440    {
441        deserialize_signed!(self, visitor, i64, visit_i64)
442    }
443
444    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
445    where
446        V: Visitor<'de>,
447    {
448        deserialize_unsigned!(self, visitor, u8, visit_u8)
449    }
450
451    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
452    where
453        V: Visitor<'de>,
454    {
455        deserialize_unsigned!(self, visitor, u16, visit_u16)
456    }
457
458    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
459    where
460        V: Visitor<'de>,
461    {
462        deserialize_unsigned!(self, visitor, u32, visit_u32)
463    }
464
465    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
466    where
467        V: Visitor<'de>,
468    {
469        deserialize_unsigned!(self, visitor, u64, visit_u64)
470    }
471
472    fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
473    where
474        V: Visitor<'de>,
475    {
476        deserialize_fromstr!(self, visitor, f32, visit_f32, b"0123456789+-.eE")
477    }
478
479    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
480    where
481        V: Visitor<'de>,
482    {
483        deserialize_fromstr!(self, visitor, f64, visit_f64, b"0123456789+-.eE")
484    }
485
486    fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
487    where
488        V: Visitor<'de>,
489    {
490        self.deserialize_str(visitor)
491    }
492
493    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
494    where
495        V: Visitor<'de>,
496    {
497        let escaped_string = self.parse_str()?;
498
499        // If the unescape buffer is not provided, skip unescaping strings
500        let Some(string_unescape_buffer) = self.string_unescape_buffer.as_deref_mut() else {
501            return visitor.visit_borrowed_str(escaped_string);
502        };
503
504        // If the escaped string doesn't contain '\\', it' can't have any escaped characters
505        if !escaped_string.as_bytes().contains(&b'\\') {
506            return visitor.visit_borrowed_str(escaped_string);
507        }
508
509        let mut string_unescape_buffer_write_position = 0;
510
511        for fragment in crate::str::EscapedStr(escaped_string).fragments() {
512            let char_encode_buffer = &mut [0; 4];
513
514            let unescaped_bytes = match fragment? {
515                crate::str::EscapedStringFragment::NotEscaped(fragment) => fragment.as_bytes(),
516                crate::str::EscapedStringFragment::Escaped(c) => {
517                    c.encode_utf8(char_encode_buffer).as_bytes()
518                }
519            };
520
521            string_unescape_buffer[string_unescape_buffer_write_position..]
522                .get_mut(..unescaped_bytes.len())
523                .ok_or(Error::EscapedStringIsTooLong)?
524                .copy_from_slice(unescaped_bytes);
525
526            string_unescape_buffer_write_position += unescaped_bytes.len();
527        }
528
529        visitor.visit_str(
530            str::from_utf8(&string_unescape_buffer[..string_unescape_buffer_write_position])
531                .map_err(|_| Error::InvalidUnicodeCodePoint)?,
532        )
533    }
534
535    /// Unsupported. String is not available in no-std.
536    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
537    where
538        V: Visitor<'de>,
539    {
540        self.deserialize_str(visitor)
541    }
542
543    /// Unsupported
544    fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
545    where
546        V: Visitor<'de>,
547    {
548        Err(Error::BytesIsUnsupported)
549    }
550
551    /// Unsupported
552    fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value>
553    where
554        V: Visitor<'de>,
555    {
556        Err(Error::BytesIsUnsupported)
557    }
558
559    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
560    where
561        V: Visitor<'de>,
562    {
563        match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
564            b'n' => {
565                self.eat_char();
566                self.parse_ident(b"ull")?;
567                visitor.visit_none()
568            }
569            _ => visitor.visit_some(self),
570        }
571    }
572
573    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
574    where
575        V: Visitor<'de>,
576    {
577        let peek = match self.parse_whitespace() {
578            Some(b) => b,
579            None => {
580                return Err(Error::EofWhileParsingValue);
581            }
582        };
583
584        match peek {
585            b'n' => {
586                self.eat_char();
587                self.parse_ident(b"ull")?;
588                visitor.visit_unit()
589            }
590            _ => Err(Error::InvalidType),
591        }
592    }
593
594    fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
595    where
596        V: Visitor<'de>,
597    {
598        self.deserialize_unit(visitor)
599    }
600
601    fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value>
602    where
603        V: Visitor<'de>,
604    {
605        // If the newtype struct is an `EscapedStr`...
606        if name == crate::str::EscapedStr::NAME {
607            // ...deserialize as an escaped string instead.
608
609            struct EscapedStringDeserializer<'a, 'de, 's>(&'a mut Deserializer<'de, 's>);
610
611            impl<'de> serde::Deserializer<'de> for EscapedStringDeserializer<'_, 'de, '_> {
612                type Error = Error;
613
614                fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
615                where
616                    V: Visitor<'de>,
617                {
618                    // The only structure which is deserialized at this point is an `EscapedStr`,
619                    // so pass the escaped string to its implementation of visit_borrowed_str.
620                    // This line defacto becomes `Ok(EscapedStr(self.0.parse_str()?))`.
621                    visitor.visit_borrowed_str(self.0.parse_str()?)
622                }
623
624                // `EscapedStr` only deserializes strings, so we might as well forward all methods to `deserialize_any`.
625                serde::forward_to_deserialize_any! {
626                    bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
627                    bytes byte_buf option unit unit_struct newtype_struct seq tuple
628                    tuple_struct map struct enum identifier ignored_any
629                }
630            }
631
632            visitor.visit_newtype_struct(EscapedStringDeserializer(self))
633        } else {
634            visitor.visit_newtype_struct(self)
635        }
636    }
637
638    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
639    where
640        V: Visitor<'de>,
641    {
642        match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
643            b'[' => {
644                self.eat_char();
645                let ret = visitor.visit_seq(SeqAccess::new(self))?;
646
647                self.end_seq()?;
648
649                Ok(ret)
650            }
651            _ => Err(Error::InvalidType),
652        }
653    }
654
655    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
656    where
657        V: Visitor<'de>,
658    {
659        self.deserialize_seq(visitor)
660    }
661
662    fn deserialize_tuple_struct<V>(
663        self,
664        _name: &'static str,
665        _len: usize,
666        visitor: V,
667    ) -> Result<V::Value>
668    where
669        V: Visitor<'de>,
670    {
671        self.deserialize_seq(visitor)
672    }
673
674    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
675    where
676        V: Visitor<'de>,
677    {
678        let peek = self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
679
680        if peek == b'{' {
681            self.eat_char();
682
683            let ret = visitor.visit_map(MapAccess::new(self))?;
684
685            self.end_map()?;
686
687            Ok(ret)
688        } else {
689            Err(Error::InvalidType)
690        }
691    }
692
693    fn deserialize_struct<V>(
694        self,
695        _name: &'static str,
696        _fields: &'static [&'static str],
697        visitor: V,
698    ) -> Result<V::Value>
699    where
700        V: Visitor<'de>,
701    {
702        self.deserialize_map(visitor)
703    }
704
705    fn deserialize_enum<V>(
706        self,
707        _name: &'static str,
708        _variants: &'static [&'static str],
709        visitor: V,
710    ) -> Result<V::Value>
711    where
712        V: Visitor<'de>,
713    {
714        match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
715            b'"' => visitor.visit_enum(UnitVariantAccess::new(self)),
716            b'{' => {
717                self.eat_char();
718                let value = visitor.visit_enum(VariantAccess::new(self))?;
719                match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
720                    b'}' => {
721                        self.eat_char();
722                        Ok(value)
723                    }
724                    _ => Err(Error::ExpectedSomeValue),
725                }
726            }
727            _ => Err(Error::ExpectedSomeValue),
728        }
729    }
730
731    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
732    where
733        V: Visitor<'de>,
734    {
735        self.deserialize_str(visitor)
736    }
737
738    /// Used to throw out fields from JSON objects that we don’t want to
739    /// keep in our structs.
740    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
741    where
742        V: Visitor<'de>,
743    {
744        match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
745            b'"' => self.deserialize_str(visitor),
746            b'[' => self.deserialize_seq(visitor),
747            b'{' => self.deserialize_struct("ignored", &[], visitor),
748            b',' | b'}' | b']' => Err(Error::ExpectedSomeValue),
749            // If it’s something else then we chomp until we get to an end delimiter.
750            // This does technically allow for illegal JSON since we’re just ignoring
751            // characters rather than parsing them.
752            _ => loop {
753                match self.peek() {
754                    // The visitor is expected to be UnknownAny’s visitor, which
755                    // implements visit_unit to return its unit Ok result.
756                    Some(b',') | Some(b'}') | Some(b']') => break visitor.visit_unit(),
757                    Some(_) => self.eat_char(),
758                    None => break Err(Error::EofWhileParsingString),
759                }
760            },
761        }
762    }
763}
764
765impl de::Error for Error {
766    #[cfg_attr(not(feature = "custom-error-messages"), allow(unused_variables))]
767    fn custom<T>(msg: T) -> Self
768    where
769        T: fmt::Display,
770    {
771        #[cfg(not(feature = "custom-error-messages"))]
772        {
773            Error::CustomError
774        }
775        #[cfg(feature = "custom-error-messages")]
776        {
777            use core::fmt::Write;
778
779            let mut string = heapless::String::new();
780            write!(string, "{:.64}", msg).unwrap();
781            Error::CustomErrorWithMessage(string)
782        }
783    }
784}
785
786impl fmt::Display for Error {
787    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
788        write!(
789            f,
790            "{}",
791            match self {
792                Error::EofWhileParsingList => "EOF while parsing a list.",
793                Error::EofWhileParsingObject => "EOF while parsing an object.",
794                Error::EofWhileParsingString => "EOF while parsing a string.",
795                Error::EofWhileParsingValue => "EOF while parsing a JSON value.",
796                Error::ExpectedColon => "Expected this character to be a `':'`.",
797                Error::ExpectedListCommaOrEnd => {
798                    "Expected this character to be either a `','` or\
799                     a \
800                     `']'`."
801                }
802                Error::ExpectedObjectCommaOrEnd => {
803                    "Expected this character to be either a `','` \
804                     or a \
805                     `'}'`."
806                }
807                Error::ExpectedSomeIdent => {
808                    "Expected to parse either a `true`, `false`, or a \
809                     `null`."
810                }
811                Error::ExpectedSomeValue => "Expected this character to start a JSON value.",
812                Error::InvalidNumber => "Invalid number.",
813                Error::InvalidType => "Invalid type",
814                Error::InvalidUnicodeCodePoint => "Invalid unicode code point.",
815                Error::KeyMustBeAString => "Object key is not a string.",
816                Error::TrailingCharacters => {
817                    "JSON has non-whitespace trailing characters after \
818                     the \
819                     value."
820                }
821                Error::TrailingComma => "JSON has a comma after the last value in an array or map.",
822                Error::CustomError => "JSON does not match deserializer’s expected format.",
823                #[cfg(feature = "custom-error-messages")]
824                Error::CustomErrorWithMessage(msg) => msg.as_str(),
825                _ => "Invalid JSON",
826            }
827        )
828    }
829}
830
831fn from_slice_maybe_escaped<'a, T>(
832    v: &'a [u8],
833    string_unescape_buffer: Option<&mut [u8]>,
834) -> Result<(T, usize)>
835where
836    T: de::Deserialize<'a>,
837{
838    let mut de = Deserializer::new(v, string_unescape_buffer);
839    let value = de::Deserialize::deserialize(&mut de)?;
840    let length = de.end()?;
841
842    Ok((value, length))
843}
844
845/// Deserializes an instance of type `T` from bytes of JSON text, using the provided buffer to unescape strings
846/// Returns the value and the number of bytes consumed in the process
847pub fn from_slice_escaped<'a, T>(
848    v: &'a [u8],
849    string_unescape_buffer: &mut [u8],
850) -> Result<(T, usize)>
851where
852    T: de::Deserialize<'a>,
853{
854    from_slice_maybe_escaped(v, Some(string_unescape_buffer))
855}
856
857/// Deserializes an instance of type `T` from bytes of JSON text
858/// Returns the value and the number of bytes consumed in the process
859pub fn from_slice<'a, T>(v: &'a [u8]) -> Result<(T, usize)>
860where
861    T: de::Deserialize<'a>,
862{
863    from_slice_maybe_escaped(v, None)
864}
865
866/// Deserializes an instance of type T from a string of JSON text, using the provided buffer to unescape strings
867pub fn from_str_escaped<'a, T>(s: &'a str, string_unescape_buffer: &mut [u8]) -> Result<(T, usize)>
868where
869    T: de::Deserialize<'a>,
870{
871    from_slice_escaped(s.as_bytes(), string_unescape_buffer)
872}
873
874/// Deserializes an instance of type T from a string of JSON text
875pub fn from_str<'a, T>(s: &'a str) -> Result<(T, usize)>
876where
877    T: de::Deserialize<'a>,
878{
879    from_slice(s.as_bytes())
880}
881
882#[cfg(test)]
883mod tests {
884    use serde_derive::Deserialize;
885
886    #[derive(Debug, Deserialize, PartialEq)]
887    enum Type {
888        #[serde(rename = "boolean")]
889        Boolean,
890        #[serde(rename = "number")]
891        Number,
892        #[serde(rename = "thing")]
893        Thing,
894    }
895
896    #[test]
897    fn array() {
898        assert_eq!(crate::from_str::<[i32; 0]>("[]"), Ok(([], 2)));
899        assert_eq!(crate::from_str("[0, 1, 2]"), Ok(([0, 1, 2], 9)));
900
901        // errors
902        assert!(crate::from_str::<[i32; 2]>("[0, 1,]").is_err());
903    }
904
905    #[test]
906    fn bool() {
907        assert_eq!(crate::from_str("true"), Ok((true, 4)));
908        assert_eq!(crate::from_str(" true"), Ok((true, 5)));
909        assert_eq!(crate::from_str("true "), Ok((true, 5)));
910
911        assert_eq!(crate::from_str("false"), Ok((false, 5)));
912        assert_eq!(crate::from_str(" false"), Ok((false, 6)));
913        assert_eq!(crate::from_str("false "), Ok((false, 6)));
914
915        // errors
916        assert!(crate::from_str::<bool>("true false").is_err());
917        assert!(crate::from_str::<bool>("tru").is_err());
918    }
919
920    #[test]
921    fn floating_point() {
922        assert_eq!(crate::from_str("5.0"), Ok((5.0, 3)));
923        assert_eq!(crate::from_str("1"), Ok((1.0, 1)));
924        assert_eq!(crate::from_str("1e5"), Ok((1e5, 3)));
925        assert!(crate::from_str::<f32>("a").is_err());
926        assert!(crate::from_str::<f32>(",").is_err());
927    }
928
929    #[test]
930    fn integer() {
931        assert_eq!(crate::from_str("5"), Ok((5, 1)));
932        assert_eq!(crate::from_str("101"), Ok((101, 3)));
933        assert!(crate::from_str::<u16>("1e5").is_err());
934        assert!(crate::from_str::<u8>("256").is_err());
935        assert!(crate::from_str::<f32>(",").is_err());
936    }
937
938    #[test]
939    fn enum_clike() {
940        assert_eq!(crate::from_str(r#" "boolean" "#), Ok((Type::Boolean, 11)));
941        assert_eq!(crate::from_str(r#" "number" "#), Ok((Type::Number, 10)));
942        assert_eq!(crate::from_str(r#" "thing" "#), Ok((Type::Thing, 9)));
943    }
944
945    #[test]
946    fn char() {
947        fn from_str_test<'de, T: serde::Deserialize<'de>>(
948            s: &'de str,
949        ) -> super::Result<(T, usize)> {
950            crate::from_str_escaped(s, &mut [0; 8])
951        }
952
953        assert_eq!(from_str_test(r#""n""#), Ok(('n', 3)));
954        assert_eq!(from_str_test(r#""\"""#), Ok(('"', 4)));
955        assert_eq!(from_str_test(r#""\\""#), Ok(('\\', 4)));
956        assert_eq!(from_str_test(r#""/""#), Ok(('/', 3)));
957        assert_eq!(from_str_test(r#""\b""#), Ok(('\x08', 4)));
958        assert_eq!(from_str_test(r#""\f""#), Ok(('\x0C', 4)));
959        assert_eq!(from_str_test(r#""\n""#), Ok(('\n', 4)));
960        assert_eq!(from_str_test(r#""\r""#), Ok(('\r', 4)));
961        assert_eq!(from_str_test(r#""\t""#), Ok(('\t', 4)));
962        assert_eq!(from_str_test(r#""\u000b""#), Ok(('\x0B', 8)));
963        assert_eq!(from_str_test(r#""\u000B""#), Ok(('\x0B', 8)));
964        assert_eq!(from_str_test(r#""Σ""#), Ok(('Σ', 4)));
965    }
966
967    #[test]
968    fn str() {
969        // No escaping, so can borrow from the input
970        assert_eq!(crate::from_str(r#" "hello" "#), Ok(("hello", 9)));
971        assert_eq!(crate::from_str(r#" "" "#), Ok(("", 4)));
972        assert_eq!(crate::from_str(r#" " " "#), Ok((" ", 5)));
973        assert_eq!(crate::from_str(r#" "👏" "#), Ok(("👏", 8)));
974
975        fn s(s: &'static str) -> heapless::String<1024> {
976            s.parse().expect("Failed to create test string")
977        }
978
979        fn from_str_test<'de, T: serde::Deserialize<'de>>(
980            s: &'de str,
981        ) -> super::Result<(T, usize)> {
982            crate::from_str_escaped(s, &mut [0; 16])
983        }
984
985        // escaped " in the string content
986        assert_eq!(from_str_test(r#" "foo\"bar" "#), Ok((s(r#"foo"bar"#), 12)));
987        assert_eq!(
988            from_str_test(r#" "foo\\\"bar" "#),
989            Ok((s(r#"foo\"bar"#), 14))
990        );
991        assert_eq!(
992            from_str_test(r#" "foo\"\"bar" "#),
993            Ok((s(r#"foo""bar"#), 14))
994        );
995        assert_eq!(from_str_test(r#" "\"bar" "#), Ok((s(r#""bar"#), 9)));
996        assert_eq!(from_str_test(r#" "foo\"" "#), Ok((s(r#"foo""#), 9)));
997        assert_eq!(from_str_test(r#" "\"" "#), Ok((s(r#"""#), 6)));
998
999        // non-excaped " preceded by backslashes
1000        assert_eq!(
1001            from_str_test(r#" "foo bar\\" "#),
1002            Ok((s(r#"foo bar\"#), 13))
1003        );
1004        assert_eq!(
1005            from_str_test(r#" "foo bar\\\\" "#),
1006            Ok((s(r#"foo bar\\"#), 15))
1007        );
1008        assert_eq!(
1009            from_str_test(r#" "foo bar\\\\\\" "#),
1010            Ok((s(r#"foo bar\\\"#), 17))
1011        );
1012        assert_eq!(
1013            from_str_test(r#" "foo bar\\\\\\\\" "#),
1014            Ok((s(r#"foo bar\\\\"#), 19))
1015        );
1016        assert_eq!(from_str_test(r#" "\\" "#), Ok((s(r#"\"#), 6)));
1017    }
1018
1019    #[test]
1020    fn tuple_of_str() {
1021        fn s(s: &'static str) -> heapless::String<1024> {
1022            s.parse().expect("Failed to create test string")
1023        }
1024
1025        fn from_str_test<'de, T: serde::Deserialize<'de>>(
1026            s: &'de str,
1027        ) -> super::Result<(T, usize)> {
1028            crate::from_str_escaped(s, &mut [0; 16])
1029        }
1030
1031        // The combined length of the first and third strings are longer than the buffer, but that's OK,
1032        // as escaped strings are deserialized into owned str types, e.g. `heapless::String`.
1033        // The second string is longer than the buffer, but that's OK, as strings which aren't escaped
1034        // are deserialized as str's borrowed from the input
1035
1036        assert_eq!(
1037            from_str_test(
1038                r#" [ "AAAAAAAAAAAA\n", "BBBBBBBBBBBBBBBBBBBBBBBB", "CCCCCCCCCCCC\n" ] "#
1039            ),
1040            Ok((
1041                (
1042                    s("AAAAAAAAAAAA\n"),
1043                    "BBBBBBBBBBBBBBBBBBBBBBBB",
1044                    s("CCCCCCCCCCCC\n")
1045                ),
1046                68
1047            ))
1048        );
1049    }
1050
1051    #[test]
1052    fn escaped_str() {
1053        assert_eq!(
1054            crate::from_str(r#""Hello\nWorld""#),
1055            Ok((crate::str::EscapedStr(r#"Hello\nWorld"#), 14))
1056        );
1057    }
1058
1059    #[test]
1060    fn struct_bool() {
1061        #[derive(Debug, Deserialize, PartialEq)]
1062        struct Led {
1063            led: bool,
1064        }
1065
1066        assert_eq!(
1067            crate::from_str(r#"{ "led": true }"#),
1068            Ok((Led { led: true }, 15))
1069        );
1070        assert_eq!(
1071            crate::from_str(r#"{ "led": false }"#),
1072            Ok((Led { led: false }, 16))
1073        );
1074    }
1075
1076    #[test]
1077    fn struct_i8() {
1078        #[derive(Debug, Deserialize, PartialEq)]
1079        struct Temperature {
1080            temperature: i8,
1081        }
1082
1083        assert_eq!(
1084            crate::from_str(r#"{ "temperature": -17 }"#),
1085            Ok((Temperature { temperature: -17 }, 22))
1086        );
1087
1088        assert_eq!(
1089            crate::from_str(r#"{ "temperature": -0 }"#),
1090            Ok((Temperature { temperature: -0 }, 21))
1091        );
1092
1093        assert_eq!(
1094            crate::from_str(r#"{ "temperature": 0 }"#),
1095            Ok((Temperature { temperature: 0 }, 20))
1096        );
1097
1098        // out of range
1099        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 128 }"#).is_err());
1100        assert!(crate::from_str::<Temperature>(r#"{ "temperature": -129 }"#).is_err());
1101    }
1102
1103    #[test]
1104    fn struct_f32() {
1105        #[derive(Debug, Deserialize, PartialEq)]
1106        struct Temperature {
1107            temperature: f32,
1108        }
1109
1110        assert_eq!(
1111            crate::from_str(r#"{ "temperature": -17.2 }"#),
1112            Ok((Temperature { temperature: -17.2 }, 24))
1113        );
1114
1115        assert_eq!(
1116            crate::from_str(r#"{ "temperature": -0.0 }"#),
1117            Ok((Temperature { temperature: -0. }, 23))
1118        );
1119
1120        assert_eq!(
1121            crate::from_str(r#"{ "temperature": -2.1e-3 }"#),
1122            Ok((
1123                Temperature {
1124                    temperature: -2.1e-3
1125                },
1126                26
1127            ))
1128        );
1129
1130        assert_eq!(
1131            crate::from_str(r#"{ "temperature": -3 }"#),
1132            Ok((Temperature { temperature: -3. }, 21))
1133        );
1134
1135        assert_eq!(
1136            crate::from_str(r#"{ "temperature": -1e500 }"#),
1137            Ok((
1138                Temperature {
1139                    temperature: f32::NEG_INFINITY
1140                },
1141                25
1142            ))
1143        );
1144
1145        // NaNs will always compare unequal.
1146        let (r, n): (Temperature, usize) = crate::from_str(r#"{ "temperature": null }"#).unwrap();
1147        assert!(r.temperature.is_nan());
1148        assert_eq!(n, 23);
1149
1150        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 1e1e1 }"#).is_err());
1151        assert!(crate::from_str::<Temperature>(r#"{ "temperature": -2-2 }"#).is_err());
1152        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 1 1 }"#).is_err());
1153        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 0.0. }"#).is_err());
1154        assert!(crate::from_str::<Temperature>(r#"{ "temperature": ä }"#).is_err());
1155        assert!(crate::from_str::<Temperature>(r#"{ "temperature": None }"#).is_err());
1156    }
1157
1158    #[test]
1159    fn struct_option() {
1160        #[derive(Debug, Deserialize, PartialEq)]
1161        struct Property<'a> {
1162            #[serde(borrow)]
1163            description: Option<&'a str>,
1164        }
1165
1166        assert_eq!(
1167            crate::from_str(r#"{ "description": "An ambient temperature sensor" }"#),
1168            Ok((
1169                Property {
1170                    description: Some("An ambient temperature sensor"),
1171                },
1172                50
1173            ))
1174        );
1175
1176        assert_eq!(
1177            crate::from_str(r#"{ "description": null }"#),
1178            Ok((Property { description: None }, 23))
1179        );
1180
1181        assert_eq!(
1182            crate::from_str(r#"{}"#),
1183            Ok((Property { description: None }, 2))
1184        );
1185    }
1186
1187    #[test]
1188    fn struct_u8() {
1189        #[derive(Debug, Deserialize, PartialEq)]
1190        struct Temperature {
1191            temperature: u8,
1192        }
1193
1194        assert_eq!(
1195            crate::from_str(r#"{ "temperature": 20 }"#),
1196            Ok((Temperature { temperature: 20 }, 21))
1197        );
1198
1199        assert_eq!(
1200            crate::from_str(r#"{ "temperature": 0 }"#),
1201            Ok((Temperature { temperature: 0 }, 20))
1202        );
1203
1204        // out of range
1205        assert!(crate::from_str::<Temperature>(r#"{ "temperature": 256 }"#).is_err());
1206        assert!(crate::from_str::<Temperature>(r#"{ "temperature": -1 }"#).is_err());
1207    }
1208
1209    #[test]
1210    fn test_unit() {
1211        assert_eq!(crate::from_str::<()>(r#"null"#), Ok(((), 4)));
1212    }
1213
1214    #[test]
1215    fn newtype_struct() {
1216        #[derive(Deserialize, Debug, PartialEq)]
1217        struct A(pub u32);
1218
1219        assert_eq!(crate::from_str::<A>(r#"54"#), Ok((A(54), 2)));
1220    }
1221
1222    #[test]
1223    fn test_newtype_variant() {
1224        #[derive(Deserialize, Debug, PartialEq)]
1225        enum A {
1226            A(u32),
1227        }
1228        let a = A::A(54);
1229        let x = crate::from_str::<A>(r#"{"A":54}"#);
1230        assert_eq!(x, Ok((a, 8)));
1231    }
1232
1233    #[test]
1234    fn test_struct_variant() {
1235        #[derive(Deserialize, Debug, PartialEq)]
1236        enum A {
1237            A { x: u32, y: u16 },
1238        }
1239        let a = A::A { x: 54, y: 720 };
1240        let x = crate::from_str::<A>(r#"{"A": {"x":54,"y":720 } }"#);
1241        assert_eq!(x, Ok((a, 25)));
1242    }
1243
1244    #[test]
1245    #[cfg(not(feature = "custom-error-messages"))]
1246    fn struct_tuple() {
1247        #[derive(Debug, Deserialize, PartialEq)]
1248        struct Xy(i8, i8);
1249
1250        assert_eq!(crate::from_str(r#"[10, 20]"#), Ok((Xy(10, 20), 8)));
1251        assert_eq!(crate::from_str(r#"[10, -20]"#), Ok((Xy(10, -20), 9)));
1252
1253        // wrong number of args
1254        assert_eq!(
1255            crate::from_str::<Xy>(r#"[10]"#),
1256            Err(crate::de::Error::CustomError)
1257        );
1258        assert_eq!(
1259            crate::from_str::<Xy>(r#"[10, 20, 30]"#),
1260            Err(crate::de::Error::TrailingCharacters)
1261        );
1262    }
1263
1264    #[test]
1265    #[cfg(feature = "custom-error-messages")]
1266    fn struct_tuple() {
1267        #[derive(Debug, Deserialize, PartialEq)]
1268        struct Xy(i8, i8);
1269
1270        assert_eq!(crate::from_str(r#"[10, 20]"#), Ok((Xy(10, 20), 8)));
1271        assert_eq!(crate::from_str(r#"[10, -20]"#), Ok((Xy(10, -20), 9)));
1272
1273        // wrong number of args
1274        assert_eq!(
1275            crate::from_str::<Xy>(r#"[10]"#),
1276            Err(crate::de::Error::CustomErrorWithMessage(
1277                "invalid length 1, expected tuple struct Xy with 2 elements"
1278                    .parse()
1279                    .unwrap()
1280            ))
1281        );
1282        assert_eq!(
1283            crate::from_str::<Xy>(r#"[10, 20, 30]"#),
1284            Err(crate::de::Error::TrailingCharacters)
1285        );
1286    }
1287
1288    #[test]
1289    fn struct_with_array_field() {
1290        #[derive(Debug, Deserialize, PartialEq)]
1291        struct Test {
1292            status: bool,
1293            point: [u32; 3],
1294        }
1295
1296        assert_eq!(
1297            crate::from_str(r#"{ "status": true, "point": [1, 2, 3] }"#),
1298            Ok((
1299                Test {
1300                    status: true,
1301                    point: [1, 2, 3]
1302                },
1303                38
1304            ))
1305        );
1306    }
1307
1308    #[test]
1309    fn struct_with_tuple_field() {
1310        #[derive(Debug, Deserialize, PartialEq)]
1311        struct Test {
1312            status: bool,
1313            point: (u32, u32, u32),
1314        }
1315
1316        assert_eq!(
1317            crate::from_str(r#"{ "status": true, "point": [1, 2, 3] }"#),
1318            Ok((
1319                Test {
1320                    status: true,
1321                    point: (1, 2, 3)
1322                },
1323                38
1324            ))
1325        );
1326    }
1327
1328    #[test]
1329    fn ignoring_extra_fields() {
1330        #[derive(Debug, Deserialize, PartialEq)]
1331        struct Temperature {
1332            temperature: u8,
1333        }
1334
1335        assert_eq!(
1336            crate::from_str(r#"{ "temperature": 20, "high": 80, "low": -10, "updated": true }"#),
1337            Ok((Temperature { temperature: 20 }, 62))
1338        );
1339
1340        assert_eq!(
1341            crate::from_str(
1342                r#"{ "temperature": 20, "conditions": "windy", "forecast": "cloudy" }"#
1343            ),
1344            Ok((Temperature { temperature: 20 }, 66))
1345        );
1346
1347        assert_eq!(
1348            crate::from_str(r#"{ "temperature": 20, "hourly_conditions": ["windy", "rainy"] }"#),
1349            Ok((Temperature { temperature: 20 }, 62))
1350        );
1351
1352        assert_eq!(
1353            crate::from_str(
1354                r#"{ "temperature": 20, "source": { "station": "dock", "sensors": ["front", "back"] } }"#
1355            ),
1356            Ok((Temperature { temperature: 20 }, 84))
1357        );
1358
1359        assert_eq!(
1360            crate::from_str(r#"{ "temperature": 20, "invalid": this-is-ignored }"#),
1361            Ok((Temperature { temperature: 20 }, 49))
1362        );
1363
1364        assert_eq!(
1365            crate::from_str::<Temperature>(r#"{ "temperature": 20, "broken": }"#),
1366            Err(crate::de::Error::ExpectedSomeValue)
1367        );
1368
1369        assert_eq!(
1370            crate::from_str::<Temperature>(r#"{ "temperature": 20, "broken": [ }"#),
1371            Err(crate::de::Error::ExpectedSomeValue)
1372        );
1373
1374        assert_eq!(
1375            crate::from_str::<Temperature>(r#"{ "temperature": 20, "broken": ] }"#),
1376            Err(crate::de::Error::ExpectedSomeValue)
1377        );
1378    }
1379
1380    #[test]
1381    #[cfg(feature = "custom-error-messages")]
1382    fn preserve_short_error_message() {
1383        use serde::de::Error;
1384        assert_eq!(
1385            crate::de::Error::custom("something bad happened"),
1386            crate::de::Error::CustomErrorWithMessage("something bad happened".parse().unwrap())
1387        );
1388    }
1389
1390    #[test]
1391    #[cfg(feature = "custom-error-messages")]
1392    fn truncate_error_message() {
1393        use serde::de::Error;
1394        assert_eq!(
1395            crate::de::Error::custom("0123456789012345678901234567890123456789012345678901234567890123 <- after here the message should be truncated"),
1396            crate::de::Error::CustomErrorWithMessage(
1397                "0123456789012345678901234567890123456789012345678901234567890123".parse().unwrap()
1398            )
1399        );
1400    }
1401
1402    // See https://iot.mozilla.org/wot/#thing-resource
1403    #[test]
1404    fn wot() {
1405        #[derive(Debug, Deserialize, PartialEq)]
1406        struct Thing<'a> {
1407            #[serde(borrow)]
1408            properties: Properties<'a>,
1409            #[serde(rename = "type")]
1410            ty: Type,
1411        }
1412
1413        #[derive(Debug, Deserialize, PartialEq)]
1414        struct Properties<'a> {
1415            #[serde(borrow)]
1416            temperature: Property<'a>,
1417            #[serde(borrow)]
1418            humidity: Property<'a>,
1419            #[serde(borrow)]
1420            led: Property<'a>,
1421        }
1422
1423        #[derive(Debug, Deserialize, PartialEq)]
1424        struct Property<'a> {
1425            #[serde(rename = "type")]
1426            ty: Type,
1427            unit: Option<&'a str>,
1428            #[serde(borrow)]
1429            description: Option<&'a str>,
1430            href: &'a str,
1431        }
1432
1433        assert_eq!(
1434            crate::from_str::<Thing<'_>>(
1435                r#"
1436                    {
1437                    "type": "thing",
1438                    "properties": {
1439                        "temperature": {
1440                        "type": "number",
1441                        "unit": "celsius",
1442                        "description": "An ambient temperature sensor",
1443                        "href": "/properties/temperature"
1444                        },
1445                        "humidity": {
1446                        "type": "number",
1447                        "unit": "percent",
1448                        "href": "/properties/humidity"
1449                        },
1450                        "led": {
1451                        "type": "boolean",
1452                        "description": "A red LED",
1453                        "href": "/properties/led"
1454                        }
1455                    }
1456                    }
1457                    "#
1458            ),
1459            Ok((
1460                Thing {
1461                    properties: Properties {
1462                        temperature: Property {
1463                            ty: Type::Number,
1464                            unit: Some("celsius"),
1465                            description: Some("An ambient temperature sensor"),
1466                            href: "/properties/temperature",
1467                        },
1468                        humidity: Property {
1469                            ty: Type::Number,
1470                            unit: Some("percent"),
1471                            description: None,
1472                            href: "/properties/humidity",
1473                        },
1474                        led: Property {
1475                            ty: Type::Boolean,
1476                            unit: None,
1477                            description: Some("A red LED"),
1478                            href: "/properties/led",
1479                        },
1480                    },
1481                    ty: Type::Thing,
1482                },
1483                852
1484            ))
1485        )
1486    }
1487}