1use 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
16pub type Result<T> = core::result::Result<T, Error>;
18
19#[derive(Debug, PartialEq)]
21#[non_exhaustive]
22pub enum Error {
23 EofWhileParsingList,
25
26 EofWhileParsingObject,
28
29 EofWhileParsingString,
31
32 EofWhileParsingNumber,
34
35 EofWhileParsingValue,
37
38 ExpectedColon,
40
41 ExpectedListCommaOrEnd,
43
44 ExpectedObjectCommaOrEnd,
46
47 ExpectedSomeIdent,
49
50 ExpectedSomeValue,
52
53 InvalidNumber,
55
56 InvalidType,
58
59 InvalidUnicodeCodePoint,
61
62 KeyMustBeAString,
64
65 TrailingCharacters,
67
68 TrailingComma,
70
71 CustomError,
73
74 #[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 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(); } 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 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
227macro_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 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 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 fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value>
451 where
452 V: Visitor<'de>,
453 {
454 unreachable!()
455 }
456
457 fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
459 where
460 V: Visitor<'de>,
461 {
462 unreachable!()
463 }
464
465 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 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 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 _ => loop {
638 match self.peek() {
639 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
716pub 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
729pub 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 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 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 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 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 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 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 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 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 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 #[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}