From 1a739c167747a80fe93a14ea0c4e4db8406d89ec Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 30 Jun 2020 10:27:58 +0200 Subject: [PATCH 01/34] refactor: Factor out whitespace skipping into helpers Should hopefully reduce the amount of code being generated --- src/de.rs | 183 ++++++++++++++++++++---------------------------------- 1 file changed, 67 insertions(+), 116 deletions(-) diff --git a/src/de.rs b/src/de.rs index ffd0d48c2..5ddec782b 100644 --- a/src/de.rs +++ b/src/de.rs @@ -243,6 +243,24 @@ impl<'de, R: Read<'de>> Deserializer { Error::syntax(reason, position.line, position.column) } + /// Returns the first non-whitespace byte without consuming it, or `Err` if + /// EOF is encountered. + fn parse_whitespace_in_value(&mut self) -> Result { + match tri!(self.parse_whitespace()) { + Some(b) => Ok(b), + None => Err(self.peek_error(ErrorCode::EofWhileParsingValue)), + } + } + + /// Returns the first non-whitespace byte without consuming it, or `Err` if + /// EOF is encountered. + fn parse_whitespace_in_object(&mut self) -> Result { + match tri!(self.parse_whitespace()) { + Some(b) => Ok(b), + None => Err(self.peek_error(ErrorCode::EofWhileParsingObject)), + } + } + /// Returns the first non-whitespace byte without consuming it, or `None` if /// EOF is encountered. fn parse_whitespace(&mut self) -> Result> { @@ -313,12 +331,7 @@ impl<'de, R: Read<'de>> Deserializer { where V: de::Visitor<'de>, { - let peek = match tri!(self.parse_whitespace()) { - Some(b) => b, - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + let peek = tri!(self.parse_whitespace_in_value()); let value = match peek { b'-' => { @@ -980,13 +993,12 @@ impl<'de, R: Read<'de>> Deserializer { } fn parse_object_colon(&mut self) -> Result<()> { - match tri!(self.parse_whitespace()) { - Some(b':') => { + match tri!(self.parse_whitespace_in_object()) { + b':' => { self.eat_char(); Ok(()) } - Some(_) => Err(self.peek_error(ErrorCode::ExpectedColon)), - None => Err(self.peek_error(ErrorCode::EofWhileParsingObject)), + _ => Err(self.peek_error(ErrorCode::ExpectedColon)), } } @@ -1009,14 +1021,13 @@ impl<'de, R: Read<'de>> Deserializer { } fn end_map(&mut self) -> Result<()> { - match tri!(self.parse_whitespace()) { - Some(b'}') => { + match tri!(self.parse_whitespace_in_object()) { + b'}' => { self.eat_char(); Ok(()) } - Some(b',') => Err(self.peek_error(ErrorCode::TrailingComma)), - Some(_) => Err(self.peek_error(ErrorCode::TrailingCharacters)), - None => Err(self.peek_error(ErrorCode::EofWhileParsingObject)), + b',' => Err(self.peek_error(ErrorCode::TrailingComma)), + _ => Err(self.peek_error(ErrorCode::TrailingCharacters)), } } @@ -1025,12 +1036,7 @@ impl<'de, R: Read<'de>> Deserializer { let mut enclosing = None; loop { - let peek = match tri!(self.parse_whitespace()) { - Some(b) => b, - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + let peek = tri!(self.parse_whitespace_in_value()); let frame = match peek { b'n' => { @@ -1118,16 +1124,14 @@ impl<'de, R: Read<'de>> Deserializer { } if frame == b'{' { - match tri!(self.parse_whitespace()) { - Some(b'"') => self.eat_char(), - Some(_) => return Err(self.peek_error(ErrorCode::KeyMustBeAString)), - None => return Err(self.peek_error(ErrorCode::EofWhileParsingObject)), + match tri!(self.parse_whitespace_in_object()) { + b'"' => self.eat_char(), + _ => return Err(self.peek_error(ErrorCode::KeyMustBeAString)), } tri!(self.read.ignore_str()); - match tri!(self.parse_whitespace()) { - Some(b':') => self.eat_char(), - Some(_) => return Err(self.peek_error(ErrorCode::ExpectedColon)), - None => return Err(self.peek_error(ErrorCode::EofWhileParsingObject)), + match tri!(self.parse_whitespace_in_object()) { + b':' => self.eat_char(), + _ => return Err(self.peek_error(ErrorCode::ExpectedColon)), } } @@ -1311,12 +1315,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = match tri!(self.parse_whitespace()) { - Some(b) => b, - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + let peek = tri!(self.parse_whitespace_in_value()); let value = match peek { b'n' => { @@ -1387,12 +1386,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = match tri!(self.parse_whitespace()) { - Some(b) => b, - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + let peek = tri!(self.parse_whitespace_in_value()); let value = match peek { b't' => { @@ -1444,15 +1438,12 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { { let mut buf = String::new(); - match tri!(self.parse_whitespace()) { - Some(b'-') => { + match tri!(self.parse_whitespace_in_value()) { + b'-' => { self.eat_char(); buf.push('-'); } - Some(_) => {} - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } + _ => {} }; tri!(self.scan_integer128(&mut buf)); @@ -1474,14 +1465,11 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - match tri!(self.parse_whitespace()) { - Some(b'-') => { + match tri!(self.parse_whitespace_in_value()) { + b'-' => { return Err(self.peek_error(ErrorCode::NumberOutOfRange)); } - Some(_) => {} - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } + _ => {} } let mut buf = String::new(); @@ -1512,12 +1500,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = match tri!(self.parse_whitespace()) { - Some(b) => b, - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + let peek = tri!(self.parse_whitespace_in_value()); let value = match peek { b'"' => { @@ -1618,12 +1601,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = match tri!(self.parse_whitespace()) { - Some(b) => b, - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + let peek = tri!(self.parse_whitespace_in_value()); let value = match peek { b'"' => { @@ -1672,12 +1650,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = match tri!(self.parse_whitespace()) { - Some(b) => b, - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + let peek = tri!(self.parse_whitespace_in_value()); let value = match peek { b'n' => { @@ -1722,12 +1695,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = match tri!(self.parse_whitespace()) { - Some(b) => b, - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + let peek = tri!(self.parse_whitespace_in_value()); let value = match peek { b'[' => { @@ -1773,12 +1741,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = match tri!(self.parse_whitespace()) { - Some(b) => b, - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + let peek = tri!(self.parse_whitespace_in_value()); let value = match peek { b'{' => { @@ -1810,12 +1773,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = match tri!(self.parse_whitespace()) { - Some(b) => b, - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + let peek = tri!(self.parse_whitespace_in_value()); let value = match peek { b'[' => { @@ -1861,25 +1819,23 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - match tri!(self.parse_whitespace()) { - Some(b'{') => { + match tri!(self.parse_whitespace_in_value()) { + b'{' => { check_recursion! { self.eat_char(); let value = tri!(visitor.visit_enum(VariantAccess::new(self))); } - match tri!(self.parse_whitespace()) { - Some(b'}') => { + match tri!(self.parse_whitespace_in_object()) { + b'}' => { self.eat_char(); Ok(value) } - Some(_) => Err(self.error(ErrorCode::ExpectedSomeValue)), - None => Err(self.error(ErrorCode::EofWhileParsingObject)), + _ => Err(self.error(ErrorCode::ExpectedSomeValue)), } } - Some(b'"') => visitor.visit_enum(UnitVariantAccess::new(self)), - Some(_) => Err(self.peek_error(ErrorCode::ExpectedSomeValue)), - None => Err(self.peek_error(ErrorCode::EofWhileParsingValue)), + b'"' => visitor.visit_enum(UnitVariantAccess::new(self)), + _ => Err(self.peek_error(ErrorCode::ExpectedSomeValue)), } } @@ -1923,12 +1879,12 @@ impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> { } Some(b',') if !self.first => { self.de.eat_char(); - tri!(self.de.parse_whitespace()) + tri!(self.de.parse_whitespace_in_value()) } Some(b) => { if self.first { self.first = false; - Some(b) + b } else { return Err(self.de.peek_error(ErrorCode::ExpectedListCommaOrEnd)); } @@ -1939,9 +1895,8 @@ impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> { }; match peek { - Some(b']') => Err(self.de.peek_error(ErrorCode::TrailingComma)), - Some(_) => Ok(Some(tri!(seed.deserialize(&mut *self.de)))), - None => Err(self.de.peek_error(ErrorCode::EofWhileParsingValue)), + b']' => Err(self.de.peek_error(ErrorCode::TrailingComma)), + _ => Ok(Some(tri!(seed.deserialize(&mut *self.de)))), } } } @@ -1964,32 +1919,28 @@ impl<'de, 'a, R: Read<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, R> { where K: de::DeserializeSeed<'de>, { - let peek = match tri!(self.de.parse_whitespace()) { - Some(b'}') => { + let peek = match tri!(self.de.parse_whitespace_in_object()) { + b'}' => { return Ok(None); } - Some(b',') if !self.first => { + b',' if !self.first => { self.de.eat_char(); - tri!(self.de.parse_whitespace()) + tri!(self.de.parse_whitespace_in_value()) } - Some(b) => { + b => { if self.first { self.first = false; - Some(b) + b } else { return Err(self.de.peek_error(ErrorCode::ExpectedObjectCommaOrEnd)); } } - None => { - return Err(self.de.peek_error(ErrorCode::EofWhileParsingObject)); - } }; match peek { - Some(b'"') => seed.deserialize(MapKey { de: &mut *self.de }).map(Some), - Some(b'}') => Err(self.de.peek_error(ErrorCode::TrailingComma)), - Some(_) => Err(self.de.peek_error(ErrorCode::KeyMustBeAString)), - None => Err(self.de.peek_error(ErrorCode::EofWhileParsingValue)), + b'"' => seed.deserialize(MapKey { de: &mut *self.de }).map(Some), + b'}' => Err(self.de.peek_error(ErrorCode::TrailingComma)), + _ => Err(self.de.peek_error(ErrorCode::KeyMustBeAString)), } } From b01ff9157d15012930dae443415357d271c9d3d9 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 12:23:34 +0200 Subject: [PATCH 02/34] refactor: Add next_char_or_error --- src/de.rs | 50 ++++++++++++++++---------------------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/src/de.rs b/src/de.rs index 5ddec782b..1aa02c90a 100644 --- a/src/de.rs +++ b/src/de.rs @@ -229,6 +229,13 @@ impl<'de, R: Read<'de>> Deserializer { Ok(tri!(self.next_char()).unwrap_or(b'\x00')) } + fn next_char_or_error(&mut self) -> Result { + match tri!(self.read.next()) { + Some(next) => Ok(next), + None => Err(self.error(ErrorCode::EofWhileParsingValue)), + } + } + /// Error caused by a byte from next_char(). #[cold] fn error(&self, reason: ErrorCode) -> Error { @@ -383,15 +390,9 @@ impl<'de, R: Read<'de>> Deserializer { fn parse_ident(&mut self, ident: &[u8]) -> Result<()> { for expected in ident { - match tri!(self.next_char()) { - None => { - return Err(self.error(ErrorCode::EofWhileParsingValue)); - } - Some(next) => { - if next != *expected { - return Err(self.error(ErrorCode::ExpectedSomeIdent)); - } - } + let next = tri!(self.next_char_or_error()); + if next != *expected { + return Err(self.error(ErrorCode::ExpectedSomeIdent)); } } @@ -399,12 +400,7 @@ impl<'de, R: Read<'de>> Deserializer { } fn parse_integer(&mut self, positive: bool) -> Result { - let next = match tri!(self.next_char()) { - Some(b) => b, - None => { - return Err(self.error(ErrorCode::EofWhileParsingValue)); - } - }; + let next = tri!(self.next_char_or_error()); match next { b'0' => { @@ -520,12 +516,7 @@ impl<'de, R: Read<'de>> Deserializer { _ => true, }; - let next = match tri!(self.next_char()) { - Some(b) => b, - None => { - return Err(self.error(ErrorCode::EofWhileParsingValue)); - } - }; + let next = tri!(self.next_char_or_error()); // Make sure a digit follows the exponent place. let mut exp = match next { @@ -712,12 +703,7 @@ impl<'de, R: Read<'de>> Deserializer { _ => true, }; - let next = match tri!(self.next_char()) { - Some(b) => b, - None => { - return Err(self.error(ErrorCode::EofWhileParsingValue)); - } - }; + let next = tri!(self.next_char_or_error()); // Make sure a digit follows the exponent place. let mut exp = match next { @@ -891,13 +877,9 @@ impl<'de, R: Read<'de>> Deserializer { #[cfg(feature = "arbitrary_precision")] fn scan_or_eof(&mut self, buf: &mut String) -> Result { - match tri!(self.next_char()) { - Some(b) => { - buf.push(b as char); - Ok(b) - } - None => Err(self.error(ErrorCode::EofWhileParsingValue)), - } + let b = tri!(self.next_char_or_error()); + buf.push(b as char); + Ok(b) } #[cfg(feature = "arbitrary_precision")] From fcd4dc1358d40782019be41b26894e70e441b940 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 12:44:38 +0200 Subject: [PATCH 03/34] Move more non-generic code out of the generic path --- src/de.rs | 111 ++++++++++++++++++++---------------------------------- 1 file changed, 41 insertions(+), 70 deletions(-) diff --git a/src/de.rs b/src/de.rs index 1aa02c90a..c4a41b57a 100644 --- a/src/de.rs +++ b/src/de.rs @@ -259,6 +259,14 @@ impl<'de, R: Read<'de>> Deserializer { } } + fn parse_whitespace_until(&mut self, expected: u8, visitor: &dyn Expected) -> Result<()> { + if tri!(self.parse_whitespace_in_value()) == expected { + Ok(()) + } else { + Err(self.peek_invalid_type(visitor)) + } + } + /// Returns the first non-whitespace byte without consuming it, or `Err` if /// EOF is encountered. fn parse_whitespace_in_object(&mut self) -> Result { @@ -1482,18 +1490,13 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = tri!(self.parse_whitespace_in_value()); + tri!(self.parse_whitespace_until(b'"', &visitor)); - let value = match peek { - b'"' => { - self.eat_char(); - self.scratch.clear(); - match tri!(self.read.parse_str(&mut self.scratch)) { - Reference::Borrowed(s) => visitor.visit_borrowed_str(s), - Reference::Copied(s) => visitor.visit_str(s), - } - } - _ => Err(self.peek_invalid_type(&visitor)), + self.eat_char(); + self.scratch.clear(); + let value = match tri!(self.read.parse_str(&mut self.scratch)) { + Reference::Borrowed(s) => visitor.visit_borrowed_str(s), + Reference::Copied(s) => visitor.visit_str(s), }; match value { @@ -1632,18 +1635,12 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = tri!(self.parse_whitespace_in_value()); + tri!(self.parse_whitespace_until(b'n', &visitor)); - let value = match peek { - b'n' => { - self.eat_char(); - tri!(self.parse_ident(b"ull")); - visitor.visit_unit() - } - _ => Err(self.peek_invalid_type(&visitor)), - }; + self.eat_char(); + tri!(self.parse_ident(b"ull")); - match value { + match visitor.visit_unit() { Ok(value) => Ok(value), Err(err) => Err(self.fix_position(err)), } @@ -1677,26 +1674,16 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = tri!(self.parse_whitespace_in_value()); + tri!(self.parse_whitespace_until(b'[', &visitor)); - let value = match peek { - b'[' => { - check_recursion! { - self.eat_char(); - let ret = visitor.visit_seq(SeqAccess::new(self)); - } - - match (ret, self.end_seq()) { - (Ok(ret), Ok(())) => Ok(ret), - (Err(err), _) | (_, Err(err)) => Err(err), - } - } - _ => Err(self.peek_invalid_type(&visitor)), - }; + check_recursion! { + self.eat_char(); + let ret = visitor.visit_seq(SeqAccess::new(self)); + } - match value { - Ok(value) => Ok(value), - Err(err) => Err(self.fix_position(err)), + match (ret, self.end_seq()) { + (Ok(ret), Ok(())) => Ok(ret), + (Err(err), _) | (_, Err(err)) => Err(self.fix_position(err)), } } @@ -1723,26 +1710,16 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = tri!(self.parse_whitespace_in_value()); + tri!(self.parse_whitespace_until(b'{', &visitor)); - let value = match peek { - b'{' => { - check_recursion! { - self.eat_char(); - let ret = visitor.visit_map(MapAccess::new(self)); - } - - match (ret, self.end_map()) { - (Ok(ret), Ok(())) => Ok(ret), - (Err(err), _) | (_, Err(err)) => Err(err), - } - } - _ => Err(self.peek_invalid_type(&visitor)), - }; + check_recursion! { + self.eat_char(); + let ret = visitor.visit_map(MapAccess::new(self)); + } - match value { - Ok(value) => Ok(value), - Err(err) => Err(self.fix_position(err)), + match (ret, self.end_map()) { + (Ok(ret), Ok(())) => Ok(ret), + (Err(err), _) | (_, Err(err)) => Err(self.fix_position(err)), } } @@ -1757,17 +1734,14 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { { let peek = tri!(self.parse_whitespace_in_value()); - let value = match peek { + let (ret, ret2) = match peek { b'[' => { check_recursion! { self.eat_char(); let ret = visitor.visit_seq(SeqAccess::new(self)); } - match (ret, self.end_seq()) { - (Ok(ret), Ok(())) => Ok(ret), - (Err(err), _) | (_, Err(err)) => Err(err), - } + (ret, self.end_seq()) } b'{' => { check_recursion! { @@ -1775,17 +1749,14 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { let ret = visitor.visit_map(MapAccess::new(self)); } - match (ret, self.end_map()) { - (Ok(ret), Ok(())) => Ok(ret), - (Err(err), _) | (_, Err(err)) => Err(err), - } + (ret, self.end_map()) } - _ => Err(self.peek_invalid_type(&visitor)), + _ => (Err(self.peek_invalid_type(&visitor)), Ok(())), }; - match value { - Ok(value) => Ok(value), - Err(err) => Err(self.fix_position(err)), + match (ret, ret2) { + (Ok(ret), Ok(())) => Ok(ret), + (Err(err), _) | (_, Err(err)) => Err(self.fix_position(err)), } } From 57dc798f2729d61d8dd05f02220c367dca7cb348 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 12:57:57 +0200 Subject: [PATCH 04/34] Move eat_char into the _until function --- src/de.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/de.rs b/src/de.rs index c4a41b57a..f97e41133 100644 --- a/src/de.rs +++ b/src/de.rs @@ -261,6 +261,7 @@ impl<'de, R: Read<'de>> Deserializer { fn parse_whitespace_until(&mut self, expected: u8, visitor: &dyn Expected) -> Result<()> { if tri!(self.parse_whitespace_in_value()) == expected { + self.eat_char(); Ok(()) } else { Err(self.peek_invalid_type(visitor)) @@ -1281,15 +1282,15 @@ macro_rules! if_checking_recursion_limit { } macro_rules! check_recursion { - ($this:ident $($body:tt)*) => { + ($this:ident; $($body:tt)*) => { if_checking_recursion_limit! { $this.remaining_depth -= 1; if $this.remaining_depth == 0 { - return Err($this.peek_error(ErrorCode::RecursionLimitExceeded)); + return Err($this.error(ErrorCode::RecursionLimitExceeded)); } } - $this $($body)* + $($body)* if_checking_recursion_limit! { $this.remaining_depth += 1; @@ -1337,8 +1338,9 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { } } b'[' => { + self.eat_char(); check_recursion! { - self.eat_char(); + self; let ret = visitor.visit_seq(SeqAccess::new(self)); } @@ -1348,8 +1350,9 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { } } b'{' => { + self.eat_char(); check_recursion! { - self.eat_char(); + self; let ret = visitor.visit_map(MapAccess::new(self)); } @@ -1492,7 +1495,6 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { { tri!(self.parse_whitespace_until(b'"', &visitor)); - self.eat_char(); self.scratch.clear(); let value = match tri!(self.read.parse_str(&mut self.scratch)) { Reference::Borrowed(s) => visitor.visit_borrowed_str(s), @@ -1637,7 +1639,6 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { { tri!(self.parse_whitespace_until(b'n', &visitor)); - self.eat_char(); tri!(self.parse_ident(b"ull")); match visitor.visit_unit() { @@ -1677,7 +1678,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { tri!(self.parse_whitespace_until(b'[', &visitor)); check_recursion! { - self.eat_char(); + self; let ret = visitor.visit_seq(SeqAccess::new(self)); } @@ -1713,7 +1714,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { tri!(self.parse_whitespace_until(b'{', &visitor)); check_recursion! { - self.eat_char(); + self; let ret = visitor.visit_map(MapAccess::new(self)); } @@ -1736,16 +1737,18 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { let (ret, ret2) = match peek { b'[' => { + self.eat_char(); check_recursion! { - self.eat_char(); + self; let ret = visitor.visit_seq(SeqAccess::new(self)); } (ret, self.end_seq()) } b'{' => { + self.eat_char(); check_recursion! { - self.eat_char(); + self; let ret = visitor.visit_map(MapAccess::new(self)); } @@ -1774,8 +1777,9 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { { match tri!(self.parse_whitespace_in_value()) { b'{' => { + self.eat_char(); check_recursion! { - self.eat_char(); + self; let value = tri!(visitor.visit_enum(VariantAccess::new(self))); } From b9540a7110240804e18ea1d0751be98a75abb7ae Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 13:06:07 +0200 Subject: [PATCH 05/34] Move even more code out of the generic deserialize_struct --- src/de.rs | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/de.rs b/src/de.rs index f97e41133..ffe1d2af7 100644 --- a/src/de.rs +++ b/src/de.rs @@ -132,6 +132,13 @@ impl ParserNumber { } } +/// Flattened `Result`. Helps llvm when optimizing +enum StructResult { + Array, + Map, + Error(Error), +} + impl<'de, R: Read<'de>> Deserializer { /// The `Deserializer::end` method should be called after a value has been fully deserialized. /// This allows the `Deserializer` to validate that the input stream is at the end or that it @@ -250,6 +257,24 @@ impl<'de, R: Read<'de>> Deserializer { Error::syntax(reason, position.line, position.column) } + fn parse_struct_prefix(&mut self, exp: &dyn Expected) -> StructResult { + match self.parse_whitespace_in_value() { + Ok(b'[') => { + self.eat_char(); + StructResult::Array + } + Ok(b'{') => { + self.eat_char(); + StructResult::Map + } + Ok(_) => { + let err = self.peek_invalid_type(exp); + StructResult::Error(self.fix_position(err)) + } + Err(err) => StructResult::Error(err), + } + } + /// Returns the first non-whitespace byte without consuming it, or `Err` if /// EOF is encountered. fn parse_whitespace_in_value(&mut self) -> Result { @@ -1733,11 +1758,8 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = tri!(self.parse_whitespace_in_value()); - - let (ret, ret2) = match peek { - b'[' => { - self.eat_char(); + let (ret, ret2) = match self.parse_struct_prefix(&visitor) { + StructResult::Array => { check_recursion! { self; let ret = visitor.visit_seq(SeqAccess::new(self)); @@ -1745,8 +1767,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { (ret, self.end_seq()) } - b'{' => { - self.eat_char(); + StructResult::Map => { check_recursion! { self; let ret = visitor.visit_map(MapAccess::new(self)); @@ -1754,7 +1775,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { (ret, self.end_map()) } - _ => (Err(self.peek_invalid_type(&visitor)), Ok(())), + StructResult::Error(err) => return Err(err), }; match (ret, ret2) { From 3e0d09692d288f16b9cc510020c7967510230ce4 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 13:20:49 +0200 Subject: [PATCH 06/34] Move recursion checking out of the generic path --- src/de.rs | 116 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 49 deletions(-) diff --git a/src/de.rs b/src/de.rs index ffe1d2af7..7d555e57f 100644 --- a/src/de.rs +++ b/src/de.rs @@ -139,6 +139,39 @@ enum StructResult { Error(Error), } +#[cfg(not(feature = "unbounded_depth"))] +macro_rules! if_checking_recursion_limit { + ($($body:tt)*) => { + $($body)* + }; +} + +#[cfg(feature = "unbounded_depth")] +macro_rules! if_checking_recursion_limit { + ($this:ident $($body:tt)*) => { + if !$this.disable_recursion_limit { + $this $($body)* + } + }; +} + +macro_rules! check_recursion { + ($this:ident; $($body:tt)*) => { + if_checking_recursion_limit! { + $this.remaining_depth -= 1; + if $this.remaining_depth == 0 { + return Err($this.error(ErrorCode::RecursionLimitExceeded)); + } + } + + $($body)* + + if_checking_recursion_limit! { + $this.remaining_depth += 1; + } + }; +} + impl<'de, R: Read<'de>> Deserializer { /// The `Deserializer::end` method should be called after a value has been fully deserialized. /// This allows the `Deserializer` to validate that the input stream is at the end or that it @@ -261,10 +294,22 @@ impl<'de, R: Read<'de>> Deserializer { match self.parse_whitespace_in_value() { Ok(b'[') => { self.eat_char(); + if_checking_recursion_limit! { + self.remaining_depth -= 1; + if self.remaining_depth == 0 { + return StructResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); + } + } StructResult::Array } Ok(b'{') => { self.eat_char(); + if_checking_recursion_limit! { + self.remaining_depth -= 1; + if self.remaining_depth == 0 { + return StructResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); + } + } StructResult::Map } Ok(_) => { @@ -1018,6 +1063,13 @@ impl<'de, R: Read<'de>> Deserializer { } } + fn end_recursion_and_seq(&mut self) -> Result<()> { + if_checking_recursion_limit! { + self.remaining_depth += 1; + } + self.end_seq() + } + fn end_seq(&mut self) -> Result<()> { match tri!(self.parse_whitespace()) { Some(b']') => { @@ -1036,6 +1088,13 @@ impl<'de, R: Read<'de>> Deserializer { } } + fn end_recursion_and_map(&mut self) -> Result<()> { + if_checking_recursion_limit! { + self.remaining_depth += 1; + } + self.end_map() + } + fn end_map(&mut self) -> Result<()> { match tri!(self.parse_whitespace_in_object()) { b'}' => { @@ -1290,39 +1349,6 @@ macro_rules! deserialize_number { }; } -#[cfg(not(feature = "unbounded_depth"))] -macro_rules! if_checking_recursion_limit { - ($($body:tt)*) => { - $($body)* - }; -} - -#[cfg(feature = "unbounded_depth")] -macro_rules! if_checking_recursion_limit { - ($this:ident $($body:tt)*) => { - if !$this.disable_recursion_limit { - $this $($body)* - } - }; -} - -macro_rules! check_recursion { - ($this:ident; $($body:tt)*) => { - if_checking_recursion_limit! { - $this.remaining_depth -= 1; - if $this.remaining_depth == 0 { - return Err($this.error(ErrorCode::RecursionLimitExceeded)); - } - } - - $($body)* - - if_checking_recursion_limit! { - $this.remaining_depth += 1; - } - }; -} - impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { type Error = Error; @@ -1759,22 +1785,14 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { V: de::Visitor<'de>, { let (ret, ret2) = match self.parse_struct_prefix(&visitor) { - StructResult::Array => { - check_recursion! { - self; - let ret = visitor.visit_seq(SeqAccess::new(self)); - } - - (ret, self.end_seq()) - } - StructResult::Map => { - check_recursion! { - self; - let ret = visitor.visit_map(MapAccess::new(self)); - } - - (ret, self.end_map()) - } + StructResult::Array => ( + visitor.visit_seq(SeqAccess::new(self)), + self.end_recursion_and_seq(), + ), + StructResult::Map => ( + visitor.visit_map(MapAccess::new(self)), + self.end_recursion_and_map(), + ), StructResult::Error(err) => return Err(err), }; From b63097f070f675e367a0706618047d438fa3216e Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 14:05:58 +0200 Subject: [PATCH 07/34] Factor out non-generic parts of next_element_seed --- src/de.rs | 61 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/de.rs b/src/de.rs index 7d555e57f..4eaf9d68d 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1862,37 +1862,62 @@ impl<'a, R: 'a> SeqAccess<'a, R> { } } -impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> { - type Error = Error; +enum FieldResult { + Error(Error), + Field, + Done, +} - fn next_element_seed(&mut self, seed: T) -> Result> - where - T: de::DeserializeSeed<'de>, - { - let peek = match tri!(self.de.parse_whitespace()) { - Some(b']') => { - return Ok(None); +impl<'de, 'a, R: Read<'de> + 'a> SeqAccess<'a, R> { + fn parse_field_prefix(&mut self) -> FieldResult { + let peek = match self.de.parse_whitespace() { + Ok(Some(peek)) => peek, + Ok(None) => { + return FieldResult::Error(self.de.peek_error(ErrorCode::EofWhileParsingList)); } - Some(b',') if !self.first => { + Err(err) => return FieldResult::Error(err), + }; + let peek = match peek { + b']' => { + return FieldResult::Done; + } + b',' if !self.first => { self.de.eat_char(); - tri!(self.de.parse_whitespace_in_value()) + match self.de.parse_whitespace_in_value() { + Ok(peek) => peek, + Err(err) => return FieldResult::Error(err), + } } - Some(b) => { + b => { if self.first { self.first = false; b } else { - return Err(self.de.peek_error(ErrorCode::ExpectedListCommaOrEnd)); + return FieldResult::Error( + self.de.peek_error(ErrorCode::ExpectedListCommaOrEnd), + ); } } - None => { - return Err(self.de.peek_error(ErrorCode::EofWhileParsingList)); - } }; match peek { - b']' => Err(self.de.peek_error(ErrorCode::TrailingComma)), - _ => Ok(Some(tri!(seed.deserialize(&mut *self.de)))), + b']' => FieldResult::Error(self.de.peek_error(ErrorCode::TrailingComma)), + _ => FieldResult::Field, + } + } +} + +impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> { + type Error = Error; + + fn next_element_seed(&mut self, seed: T) -> Result> + where + T: de::DeserializeSeed<'de>, + { + match self.parse_field_prefix() { + FieldResult::Field => Ok(Some(tri!(seed.deserialize(&mut *self.de)))), + FieldResult::Done => Ok(None), + FieldResult::Error(err) => Err(err), } } } From 3c327b0897336070a0dc5ea88c36d55e88b5cc79 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 14:19:33 +0200 Subject: [PATCH 08/34] Factor out non-generic parts of next_key_seed --- src/de.rs | 56 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/src/de.rs b/src/de.rs index 4eaf9d68d..37c746897 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1933,35 +1933,65 @@ impl<'a, R: 'a> MapAccess<'a, R> { } } -impl<'de, 'a, R: Read<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, R> { - type Error = Error; +macro_rules! try_with { + ($e:expr, $wrap:expr) => { + match $e { + crate::lib::Result::Ok(val) => val, + crate::lib::Result::Err(err) => return $wrap(err), + } + }; + ($e:expr, $wrap:expr,) => { + try_with!($e, $wrap) + }; +} - fn next_key_seed(&mut self, seed: K) -> Result> - where - K: de::DeserializeSeed<'de>, - { - let peek = match tri!(self.de.parse_whitespace_in_object()) { +enum KeyResult { + Error(Error), + Key, + Done, +} + +impl<'de, 'a, R: Read<'de> + 'a> MapAccess<'a, R> { + fn parse_key_prefix(&mut self) -> KeyResult { + let peek = match try_with!(self.de.parse_whitespace_in_object(), KeyResult::Error) { b'}' => { - return Ok(None); + return KeyResult::Done; } b',' if !self.first => { self.de.eat_char(); - tri!(self.de.parse_whitespace_in_value()) + try_with!(self.de.parse_whitespace_in_value(), KeyResult::Error) } b => { if self.first { self.first = false; b } else { - return Err(self.de.peek_error(ErrorCode::ExpectedObjectCommaOrEnd)); + return KeyResult::Error( + self.de.peek_error(ErrorCode::ExpectedObjectCommaOrEnd), + ); } } }; match peek { - b'"' => seed.deserialize(MapKey { de: &mut *self.de }).map(Some), - b'}' => Err(self.de.peek_error(ErrorCode::TrailingComma)), - _ => Err(self.de.peek_error(ErrorCode::KeyMustBeAString)), + b'"' => KeyResult::Key, + b'}' => KeyResult::Error(self.de.peek_error(ErrorCode::TrailingComma)), + _ => KeyResult::Error(self.de.peek_error(ErrorCode::KeyMustBeAString)), + } + } +} + +impl<'de, 'a, R: Read<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, R> { + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result> + where + K: de::DeserializeSeed<'de>, + { + match self.parse_key_prefix() { + KeyResult::Key => seed.deserialize(MapKey { de: &mut *self.de }).map(Some), + KeyResult::Done => Ok(None), + KeyResult::Error(err) => Err(err), } } From 4e9851281d686d404561ffea8aebdf67fe7fd938 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 14:20:58 +0200 Subject: [PATCH 09/34] Use try_with! --- src/de.rs | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/de.rs b/src/de.rs index 37c746897..71a091d90 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1851,6 +1851,18 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { } } +macro_rules! try_with { + ($e:expr, $wrap:expr) => { + match $e { + crate::lib::Result::Ok(val) => val, + crate::lib::Result::Err(err) => return $wrap(err), + } + }; + ($e:expr, $wrap:expr,) => { + try_with!($e, $wrap) + }; +} + struct SeqAccess<'a, R: 'a> { de: &'a mut Deserializer, first: bool, @@ -1870,12 +1882,11 @@ enum FieldResult { impl<'de, 'a, R: Read<'de> + 'a> SeqAccess<'a, R> { fn parse_field_prefix(&mut self) -> FieldResult { - let peek = match self.de.parse_whitespace() { - Ok(Some(peek)) => peek, - Ok(None) => { + let peek = match try_with!(self.de.parse_whitespace(), FieldResult::Error) { + Some(peek) => peek, + None => { return FieldResult::Error(self.de.peek_error(ErrorCode::EofWhileParsingList)); } - Err(err) => return FieldResult::Error(err), }; let peek = match peek { b']' => { @@ -1883,10 +1894,7 @@ impl<'de, 'a, R: Read<'de> + 'a> SeqAccess<'a, R> { } b',' if !self.first => { self.de.eat_char(); - match self.de.parse_whitespace_in_value() { - Ok(peek) => peek, - Err(err) => return FieldResult::Error(err), - } + try_with!(self.de.parse_whitespace_in_value(), FieldResult::Error) } b => { if self.first { @@ -1933,18 +1941,6 @@ impl<'a, R: 'a> MapAccess<'a, R> { } } -macro_rules! try_with { - ($e:expr, $wrap:expr) => { - match $e { - crate::lib::Result::Ok(val) => val, - crate::lib::Result::Err(err) => return $wrap(err), - } - }; - ($e:expr, $wrap:expr,) => { - try_with!($e, $wrap) - }; -} - enum KeyResult { Error(Error), Key, From e6216e6804257d1b9f37a4c86d99431a0e862709 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 16:34:20 +0200 Subject: [PATCH 10/34] Move non-generic code out of deserialize_any --- src/de.rs | 177 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 103 insertions(+), 74 deletions(-) diff --git a/src/de.rs b/src/de.rs index 71a091d90..594832777 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1,28 +1,39 @@ //! Deserialize JSON data to a Rust data structure. -use crate::error::{Error, ErrorCode, Result}; -#[cfg(feature = "float_roundtrip")] -use crate::lexical; -use crate::number::Number; -use crate::read::{self, Fused, Reference}; -use alloc::string::String; -use alloc::vec::Vec; +use alloc::{string::String, vec::Vec}; #[cfg(feature = "float_roundtrip")] use core::iter; -use core::iter::FusedIterator; -use core::marker::PhantomData; -use core::result; -use core::str::FromStr; -use serde::de::{self, Expected, Unexpected}; -use serde::{forward_to_deserialize_any, serde_if_integer128}; +use core::{iter::FusedIterator, marker::PhantomData, result, str::FromStr}; +use serde::{ + de::{self, Expected, Unexpected}, + forward_to_deserialize_any, serde_if_integer128, +}; + +#[cfg(feature = "float_roundtrip")] +use crate::lexical; #[cfg(feature = "arbitrary_precision")] use crate::number::NumberDeserializer; - -pub use crate::read::{Read, SliceRead, StrRead}; - #[cfg(feature = "std")] pub use crate::read::IoRead; +pub use crate::read::{Read, SliceRead, StrRead}; +use crate::{ + error::{Error, ErrorCode, Result}, + number::Number, + read::{self, Fused, Reference}, +}; + +macro_rules! try_with { + ($e:expr, $wrap:expr) => { + match $e { + core::result::Result::Ok(val) => val, + core::result::Result::Err(err) => return $wrap(err), + } + }; + ($e:expr, $wrap:expr,) => { + try_with!($e, $wrap) + }; +} ////////////////////////////////////////////////////////////////////////////// @@ -172,6 +183,16 @@ macro_rules! check_recursion { }; } +enum AnyResult { + Null, + Bool(bool), + Number(bool), + String, + Array, + Map, + Error(Error), +} + impl<'de, R: Read<'de>> Deserializer { /// The `Deserializer::end` method should be called after a value has been fully deserialized. /// This allows the `Deserializer` to validate that the input stream is at the end or that it @@ -290,6 +311,57 @@ impl<'de, R: Read<'de>> Deserializer { Error::syntax(reason, position.line, position.column) } + fn parse_any_prefix(&mut self) -> AnyResult { + match try_with!(self.parse_whitespace_in_value(), AnyResult::Error) { + b'n' => { + self.eat_char(); + try_with!(self.parse_ident(b"ull"), AnyResult::Error); + AnyResult::Null + } + b't' => { + self.eat_char(); + try_with!(self.parse_ident(b"rue"), AnyResult::Error); + AnyResult::Bool(true) + } + b'f' => { + self.eat_char(); + try_with!(self.parse_ident(b"alse"), AnyResult::Error); + AnyResult::Bool(false) + } + b'-' => { + self.eat_char(); + AnyResult::Number(false) + } + b'0'..=b'9' => AnyResult::Number(true), + b'"' => { + self.eat_char(); + self.scratch.clear(); + AnyResult::String + } + b'[' => { + self.eat_char(); + if_checking_recursion_limit! { + self.remaining_depth -= 1; + if self.remaining_depth == 0 { + return AnyResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); + } + } + AnyResult::Array + } + b'{' => { + self.eat_char(); + if_checking_recursion_limit! { + self.remaining_depth -= 1; + if self.remaining_depth == 0 { + return AnyResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); + } + } + AnyResult::Map + } + _ => AnyResult::Error(self.peek_error(ErrorCode::ExpectedSomeValue)), + } + } + fn parse_struct_prefix(&mut self, exp: &dyn Expected) -> StructResult { match self.parse_whitespace_in_value() { Ok(b'[') => { @@ -1357,62 +1429,31 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - let peek = tri!(self.parse_whitespace_in_value()); - - let value = match peek { - b'n' => { - self.eat_char(); - tri!(self.parse_ident(b"ull")); - visitor.visit_unit() - } - b't' => { - self.eat_char(); - tri!(self.parse_ident(b"rue")); - visitor.visit_bool(true) - } - b'f' => { - self.eat_char(); - tri!(self.parse_ident(b"alse")); - visitor.visit_bool(false) - } - b'-' => { - self.eat_char(); - tri!(self.parse_any_number(false)).visit(visitor) - } - b'0'..=b'9' => tri!(self.parse_any_number(true)).visit(visitor), - b'"' => { - self.eat_char(); - self.scratch.clear(); - match tri!(self.read.parse_str(&mut self.scratch)) { - Reference::Borrowed(s) => visitor.visit_borrowed_str(s), - Reference::Copied(s) => visitor.visit_str(s), - } - } - b'[' => { - self.eat_char(); - check_recursion! { - self; - let ret = visitor.visit_seq(SeqAccess::new(self)); - } + let value = match self.parse_any_prefix() { + AnyResult::Null => visitor.visit_unit(), + AnyResult::Bool(b) => visitor.visit_bool(b), + AnyResult::Number(positive) => tri!(self.parse_any_number(positive)).visit(visitor), + AnyResult::String => match tri!(self.read.parse_str(&mut self.scratch)) { + Reference::Borrowed(s) => visitor.visit_borrowed_str(s), + Reference::Copied(s) => visitor.visit_str(s), + }, + AnyResult::Array => { + let ret = visitor.visit_seq(SeqAccess::new(self)); - match (ret, self.end_seq()) { + match (ret, self.end_recursion_and_seq()) { (Ok(ret), Ok(())) => Ok(ret), (Err(err), _) | (_, Err(err)) => Err(err), } } - b'{' => { - self.eat_char(); - check_recursion! { - self; - let ret = visitor.visit_map(MapAccess::new(self)); - } + AnyResult::Map => { + let ret = visitor.visit_map(MapAccess::new(self)); - match (ret, self.end_map()) { + match (ret, self.end_recursion_and_map()) { (Ok(ret), Ok(())) => Ok(ret), (Err(err), _) | (_, Err(err)) => Err(err), } } - _ => Err(self.peek_error(ErrorCode::ExpectedSomeValue)), + AnyResult::Error(err) => Err(err), }; match value { @@ -1851,18 +1892,6 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { } } -macro_rules! try_with { - ($e:expr, $wrap:expr) => { - match $e { - crate::lib::Result::Ok(val) => val, - crate::lib::Result::Err(err) => return $wrap(err), - } - }; - ($e:expr, $wrap:expr,) => { - try_with!($e, $wrap) - }; -} - struct SeqAccess<'a, R: 'a> { de: &'a mut Deserializer, first: bool, From 1ca5734d23e50e97ec2f88eed0ccfeb899474337 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 19:10:46 +0200 Subject: [PATCH 11/34] s/field/element/ --- src/de.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/de.rs b/src/de.rs index 594832777..467a0c1db 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1903,34 +1903,34 @@ impl<'a, R: 'a> SeqAccess<'a, R> { } } -enum FieldResult { +enum ElementResult { Error(Error), Field, Done, } impl<'de, 'a, R: Read<'de> + 'a> SeqAccess<'a, R> { - fn parse_field_prefix(&mut self) -> FieldResult { - let peek = match try_with!(self.de.parse_whitespace(), FieldResult::Error) { + fn parse_element_prefix(&mut self) -> ElementResult { + let peek = match try_with!(self.de.parse_whitespace(), ElementResult::Error) { Some(peek) => peek, None => { - return FieldResult::Error(self.de.peek_error(ErrorCode::EofWhileParsingList)); + return ElementResult::Error(self.de.peek_error(ErrorCode::EofWhileParsingList)); } }; let peek = match peek { b']' => { - return FieldResult::Done; + return ElementResult::Done; } b',' if !self.first => { self.de.eat_char(); - try_with!(self.de.parse_whitespace_in_value(), FieldResult::Error) + try_with!(self.de.parse_whitespace_in_value(), ElementResult::Error) } b => { if self.first { self.first = false; b } else { - return FieldResult::Error( + return ElementResult::Error( self.de.peek_error(ErrorCode::ExpectedListCommaOrEnd), ); } @@ -1938,8 +1938,8 @@ impl<'de, 'a, R: Read<'de> + 'a> SeqAccess<'a, R> { }; match peek { - b']' => FieldResult::Error(self.de.peek_error(ErrorCode::TrailingComma)), - _ => FieldResult::Field, + b']' => ElementResult::Error(self.de.peek_error(ErrorCode::TrailingComma)), + _ => ElementResult::Field, } } } @@ -1951,10 +1951,10 @@ impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> { where T: de::DeserializeSeed<'de>, { - match self.parse_field_prefix() { - FieldResult::Field => Ok(Some(tri!(seed.deserialize(&mut *self.de)))), - FieldResult::Done => Ok(None), - FieldResult::Error(err) => Err(err), + match self.parse_element_prefix() { + ElementResult::Field => Ok(Some(tri!(seed.deserialize(&mut *self.de)))), + ElementResult::Done => Ok(None), + ElementResult::Error(err) => Err(err), } } } From 061247ba2697b8b9e4811017fc95196480f5d6c3 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 19:19:26 +0200 Subject: [PATCH 12/34] Avoid using map in generic functions --- src/de.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/de.rs b/src/de.rs index 467a0c1db..d4b477dc4 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1951,11 +1951,11 @@ impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> { where T: de::DeserializeSeed<'de>, { - match self.parse_element_prefix() { - ElementResult::Field => Ok(Some(tri!(seed.deserialize(&mut *self.de)))), - ElementResult::Done => Ok(None), - ElementResult::Error(err) => Err(err), - } + Ok(match self.parse_element_prefix() { + ElementResult::Field => Some(tri!(seed.deserialize(&mut *self.de))), + ElementResult::Done => None, + ElementResult::Error(err) => return Err(err), + }) } } @@ -2013,11 +2013,11 @@ impl<'de, 'a, R: Read<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, R> { where K: de::DeserializeSeed<'de>, { - match self.parse_key_prefix() { - KeyResult::Key => seed.deserialize(MapKey { de: &mut *self.de }).map(Some), - KeyResult::Done => Ok(None), - KeyResult::Error(err) => Err(err), - } + Ok(match self.parse_key_prefix() { + KeyResult::Key => Some(tri!(seed.deserialize(MapKey { de: &mut *self.de }))), + KeyResult::Done => None, + KeyResult::Error(err) => return Err(err), + }) } fn next_value_seed(&mut self, seed: V) -> Result From 52259b9f27d0c59a66bc9854e31855cc8bf061e6 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 2 Jul 2020 19:33:27 +0200 Subject: [PATCH 13/34] refactor: Add helpers for serializing begin/end key/object Avoids generating duplicates of the map_err per key/value type --- src/ser.rs | 67 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index 64cb00e1a..19c95353b 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -672,17 +672,12 @@ where Compound::Map { ser, state } => { tri!(ser .formatter - .begin_object_key(&mut ser.writer, *state == State::First) - .map_err(Error::io)); + .begin_object_key_io(&mut ser.writer, *state == State::First)); *state = State::Rest; tri!(key.serialize(MapKeySerializer { ser: *ser })); - tri!(ser - .formatter - .end_object_key(&mut ser.writer) - .map_err(Error::io)); - Ok(()) + ser.formatter.end_object_key_io(&mut ser.writer) } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -698,16 +693,9 @@ where { match self { Compound::Map { ser, .. } => { - tri!(ser - .formatter - .begin_object_value(&mut ser.writer) - .map_err(Error::io)); + tri!(ser.formatter.begin_object_value_io(&mut ser.writer)); tri!(value.serialize(&mut **ser)); - tri!(ser - .formatter - .end_object_value(&mut ser.writer) - .map_err(Error::io)); - Ok(()) + ser.formatter.end_object_value_io(&mut ser.writer) } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -719,13 +707,10 @@ where #[inline] fn end(self) -> Result<()> { match self { - Compound::Map { ser, state } => { - match state { - State::Empty => {} - _ => tri!(ser.formatter.end_object(&mut ser.writer).map_err(Error::io)), - } - Ok(()) - } + Compound::Map { ser, state } => match state { + State::Empty => Ok(()), + _ => ser.formatter.end_object(&mut ser.writer).map_err(Error::io), + }, #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), #[cfg(feature = "raw_value")] @@ -1918,6 +1903,42 @@ pub trait Formatter { } } +trait FormatterExt: Formatter { + #[inline] + fn begin_object_key_io(&mut self, writer: &mut W, first: bool) -> Result<()> + where + W: ?Sized + io::Write, + { + self.begin_object_key(writer, first).map_err(Error::io) + } + + #[inline] + fn end_object_key_io(&mut self, writer: &mut W) -> Result<()> + where + W: ?Sized + io::Write, + { + self.end_object_key(writer).map_err(Error::io) + } + + #[inline] + fn begin_object_value_io(&mut self, writer: &mut W) -> Result<()> + where + W: ?Sized + io::Write, + { + self.begin_object_value(writer).map_err(Error::io) + } + + #[inline] + fn end_object_value_io(&mut self, writer: &mut W) -> Result<()> + where + W: ?Sized + io::Write, + { + self.end_object_value(writer).map_err(Error::io) + } +} + +impl FormatterExt for T where T: Formatter {} + /// This structure compacts a JSON value with no extra whitespace. #[derive(Clone, Debug)] pub struct CompactFormatter; From 87d36a5a8eaaba8ef326b2a0b1812cef96047cd9 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Fri, 3 Jul 2020 10:11:08 +0200 Subject: [PATCH 14/34] Move out code from the generic string deserialization methods --- src/de.rs | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/de.rs b/src/de.rs index d4b477dc4..4b88ba118 100644 --- a/src/de.rs +++ b/src/de.rs @@ -362,6 +362,19 @@ impl<'de, R: Read<'de>> Deserializer { } } + fn parse_str<'s>(&'s mut self) -> Result> { + self.eat_char(); + self.scratch.clear(); + self.read.parse_str(&mut self.scratch) + } + + fn parse_str_prefix<'s>(&'s mut self, exp: &dyn Expected) -> Result> { + tri!(self.parse_whitespace_until(b'"', exp)); + + self.scratch.clear(); + self.read.parse_str(&mut self.scratch) + } + fn parse_struct_prefix(&mut self, exp: &dyn Expected) -> StructResult { match self.parse_whitespace_in_value() { Ok(b'[') => { @@ -469,14 +482,10 @@ impl<'de, R: Read<'de>> Deserializer { Ok(n) => n.invalid_type(exp), Err(err) => return err, }, - b'"' => { - self.eat_char(); - self.scratch.clear(); - match self.read.parse_str(&mut self.scratch) { - Ok(s) => de::Error::invalid_type(Unexpected::Str(&s), exp), - Err(err) => return err, - } - } + b'"' => match self.parse_str() { + Ok(s) => de::Error::invalid_type(Unexpected::Str(&s), exp), + Err(err) => return err, + }, b'[' => de::Error::invalid_type(Unexpected::Seq, exp), b'{' => de::Error::invalid_type(Unexpected::Map, exp), _ => self.peek_error(ErrorCode::ExpectedSomeValue), @@ -1585,10 +1594,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - tri!(self.parse_whitespace_until(b'"', &visitor)); - - self.scratch.clear(); - let value = match tri!(self.read.parse_str(&mut self.scratch)) { + let value = match tri!(self.parse_str_prefix(&visitor)) { Reference::Borrowed(s) => visitor.visit_borrowed_str(s), Reference::Copied(s) => visitor.visit_str(s), }; @@ -2156,9 +2162,7 @@ macro_rules! deserialize_integer_key { where V: de::Visitor<'de>, { - self.de.eat_char(); - self.de.scratch.clear(); - let string = tri!(self.de.read.parse_str(&mut self.de.scratch)); + let string = tri!(self.de.parse_str()); match (string.parse(), string) { (Ok(integer), _) => visitor.$visit(integer), (Err(_), Reference::Borrowed(s)) => visitor.visit_borrowed_str(s), @@ -2179,9 +2183,7 @@ where where V: de::Visitor<'de>, { - self.de.eat_char(); - self.de.scratch.clear(); - match tri!(self.de.read.parse_str(&mut self.de.scratch)) { + match tri!(self.de.parse_str()) { Reference::Borrowed(s) => visitor.visit_borrowed_str(s), Reference::Copied(s) => visitor.visit_str(s), } From 322f8c4357f95ff800106c4fb09786285295ccf2 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Fri, 3 Jul 2020 10:14:25 +0200 Subject: [PATCH 15/34] Shrink deserialize_struct a bit more --- src/de.rs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/de.rs b/src/de.rs index 4b88ba118..236b5d751 100644 --- a/src/de.rs +++ b/src/de.rs @@ -144,9 +144,9 @@ impl ParserNumber { } /// Flattened `Result`. Helps llvm when optimizing -enum StructResult { - Array, - Map, +enum StructResult<'a, R> { + Array(SeqAccess<'a, R>), + Map(MapAccess<'a, R>), Error(Error), } @@ -375,7 +375,7 @@ impl<'de, R: Read<'de>> Deserializer { self.read.parse_str(&mut self.scratch) } - fn parse_struct_prefix(&mut self, exp: &dyn Expected) -> StructResult { + fn parse_struct_prefix(&mut self, exp: &dyn Expected) -> StructResult<'_, R> { match self.parse_whitespace_in_value() { Ok(b'[') => { self.eat_char(); @@ -385,7 +385,7 @@ impl<'de, R: Read<'de>> Deserializer { return StructResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); } } - StructResult::Array + StructResult::Array(SeqAccess::new(self)) } Ok(b'{') => { self.eat_char(); @@ -395,7 +395,7 @@ impl<'de, R: Read<'de>> Deserializer { return StructResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); } } - StructResult::Map + StructResult::Map(MapAccess::new(self)) } Ok(_) => { let err = self.peek_invalid_type(exp); @@ -1832,14 +1832,10 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { V: de::Visitor<'de>, { let (ret, ret2) = match self.parse_struct_prefix(&visitor) { - StructResult::Array => ( - visitor.visit_seq(SeqAccess::new(self)), - self.end_recursion_and_seq(), - ), - StructResult::Map => ( - visitor.visit_map(MapAccess::new(self)), - self.end_recursion_and_map(), - ), + StructResult::Array(access) => { + (visitor.visit_seq(access), self.end_recursion_and_seq()) + } + StructResult::Map(access) => (visitor.visit_map(access), self.end_recursion_and_map()), StructResult::Error(err) => return Err(err), }; From 5d5ad07a069aa926cf4a6aafcc6c9e8da154d1e3 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Mon, 4 Jan 2021 17:31:23 +0100 Subject: [PATCH 16/34] refactor: Factor out the duplicated variant serialization --- src/ser.rs | 99 ++++++++++++++++++++++-------------------------------- 1 file changed, 40 insertions(+), 59 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index 19c95353b..03baf2d23 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -1,13 +1,23 @@ //! Serialize a Rust data structure into JSON data. -use crate::error::{Error, ErrorCode, Result}; -use crate::io; -use alloc::string::{String, ToString}; -use alloc::vec::Vec; -use core::fmt::{self, Display}; -use core::num::FpCategory; -use serde::ser::{self, Impossible, Serialize}; -use serde::serde_if_integer128; +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; +use core::{ + fmt::{self, Display}, + num::FpCategory, +}; + +use serde::{ + ser::{self, Impossible, Serialize, Serializer as _}, + serde_if_integer128, +}; + +use crate::{ + error::{Error, ErrorCode, Result}, + io, +}; /// A structure for serializing Rust values into JSON. #[cfg_attr(docsrs, doc(cfg(feature = "std")))] @@ -55,6 +65,25 @@ where pub fn into_inner(self) -> W { self.writer } + + fn serialize_variant(&mut self, variant: &'static str) -> Result<()> { + tri!(self + .formatter + .begin_object(&mut self.writer) + .map_err(Error::io)); + tri!(self + .formatter + .begin_object_key(&mut self.writer, true) + .map_err(Error::io)); + tri!(self.serialize_str(variant)); + tri!(self + .formatter + .end_object_key(&mut self.writer) + .map_err(Error::io)); + self.formatter + .begin_object_value(&mut self.writer) + .map_err(Error::io) + } } impl<'a, W, F> ser::Serializer for &'a mut Serializer @@ -275,23 +304,7 @@ where where T: ?Sized + Serialize, { - tri!(self - .formatter - .begin_object(&mut self.writer) - .map_err(Error::io)); - tri!(self - .formatter - .begin_object_key(&mut self.writer, true) - .map_err(Error::io)); - tri!(self.serialize_str(variant)); - tri!(self - .formatter - .end_object_key(&mut self.writer) - .map_err(Error::io)); - tri!(self - .formatter - .begin_object_value(&mut self.writer) - .map_err(Error::io)); + tri!(self.serialize_variant(variant)); tri!(value.serialize(&mut *self)); tri!(self .formatter @@ -362,23 +375,7 @@ where variant: &'static str, len: usize, ) -> Result { - tri!(self - .formatter - .begin_object(&mut self.writer) - .map_err(Error::io)); - tri!(self - .formatter - .begin_object_key(&mut self.writer, true) - .map_err(Error::io)); - tri!(self.serialize_str(variant)); - tri!(self - .formatter - .end_object_key(&mut self.writer) - .map_err(Error::io)); - tri!(self - .formatter - .begin_object_value(&mut self.writer) - .map_err(Error::io)); + tri!(self.serialize_variant(variant)); self.serialize_seq(Some(len)) } @@ -424,23 +421,7 @@ where variant: &'static str, len: usize, ) -> Result { - tri!(self - .formatter - .begin_object(&mut self.writer) - .map_err(Error::io)); - tri!(self - .formatter - .begin_object_key(&mut self.writer, true) - .map_err(Error::io)); - tri!(self.serialize_str(variant)); - tri!(self - .formatter - .end_object_key(&mut self.writer) - .map_err(Error::io)); - tri!(self - .formatter - .begin_object_value(&mut self.writer) - .map_err(Error::io)); + tri!(self.serialize_variant(variant)); self.serialize_map(Some(len)) } From 33ef8027e95f2879e6b9f426e522455a0761814b Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Mon, 4 Jan 2021 17:57:24 +0100 Subject: [PATCH 17/34] refactor: add begin/end_string helpers --- src/ser.rs | 137 +++++++++++++---------------------------------------- 1 file changed, 33 insertions(+), 104 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index 03baf2d23..2eb53aaf0 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -66,6 +66,18 @@ where self.writer } + fn begin_string(&mut self) -> Result<()> { + self.formatter + .begin_string(&mut self.writer) + .map_err(Error::io) + } + + fn end_string(&mut self) -> Result<()> { + self.formatter + .end_string(&mut self.writer) + .map_err(Error::io) + } + fn serialize_variant(&mut self, variant: &'static str) -> Result<()> { tri!(self .formatter @@ -454,10 +466,7 @@ where } } - tri!(self - .formatter - .begin_string(&mut self.writer) - .map_err(Error::io)); + tri!(self.begin_string()); { let mut adapter = Adapter { writer: &mut self.writer, @@ -855,195 +864,115 @@ where } fn serialize_i8(self, value: i8) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.begin_string()); tri!(self .ser .formatter .write_i8(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.end_string()); Ok(()) } fn serialize_i16(self, value: i16) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.begin_string()); tri!(self .ser .formatter .write_i16(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.end_string()); Ok(()) } fn serialize_i32(self, value: i32) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.begin_string()); tri!(self .ser .formatter .write_i32(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.end_string()); Ok(()) } fn serialize_i64(self, value: i64) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.begin_string()); tri!(self .ser .formatter .write_i64(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.end_string()); Ok(()) } serde_if_integer128! { fn serialize_i128(self, value: i128) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.begin_string()); tri!(self .ser .formatter .write_number_str(&mut self.ser.writer, &value.to_string()) .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.end_string()); Ok(()) } } fn serialize_u8(self, value: u8) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.begin_string()); tri!(self .ser .formatter .write_u8(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.end_string()); Ok(()) } fn serialize_u16(self, value: u16) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.begin_string()); tri!(self .ser .formatter .write_u16(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.end_string()); Ok(()) } fn serialize_u32(self, value: u32) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.begin_string()); tri!(self .ser .formatter .write_u32(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.end_string()); Ok(()) } fn serialize_u64(self, value: u64) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.begin_string()); tri!(self .ser .formatter .write_u64(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.end_string()); Ok(()) } serde_if_integer128! { fn serialize_u128(self, value: u128) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.begin_string()); tri!(self .ser .formatter .write_number_str(&mut self.ser.writer, &value.to_string()) .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); + tri!(self.ser.end_string()); Ok(()) } } From 5cf7a6f1a51bb65584ccda9279a460106f261702 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Mon, 4 Jan 2021 18:10:55 +0100 Subject: [PATCH 18/34] refactor: Avoid a tri! in commonly instantiated code --- src/ser.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index 2eb53aaf0..14dc75a68 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -531,11 +531,9 @@ where .map_err(Error::io)); *state = State::Rest; tri!(value.serialize(&mut **ser)); - tri!(ser - .formatter + ser.formatter .end_array_value(&mut ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), From cacd1b768e0d7df93004dcdd4228d88b40364320 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Mon, 4 Jan 2021 18:22:29 +0100 Subject: [PATCH 19/34] refactor: Various shortenings --- src/ser.rs | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index 14dc75a68..c7201284e 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -480,11 +480,7 @@ where } } } - tri!(self - .formatter - .end_string(&mut self.writer) - .map_err(Error::io)); - Ok(()) + self.end_string() } } @@ -1667,7 +1663,8 @@ pub trait Formatter { { use self::CharEscape::*; - let s = match char_escape { + let bytes; + let s: &[u8] = match char_escape { Quote => b"\\\"", ReverseSolidus => b"\\\\", Solidus => b"\\/", @@ -1678,7 +1675,7 @@ pub trait Formatter { Tab => b"\\t", AsciiControl(byte) => { static HEX_DIGITS: [u8; 16] = *b"0123456789abcdef"; - let bytes = &[ + bytes = [ b'\\', b'u', b'0', @@ -1686,7 +1683,7 @@ pub trait Formatter { HEX_DIGITS[(byte >> 4) as usize], HEX_DIGITS[(byte & 0xF) as usize], ]; - return writer.write_all(bytes); + &bytes } }; @@ -1914,11 +1911,7 @@ impl<'a> Formatter for PrettyFormatter<'a> { where W: ?Sized + io::Write, { - if first { - tri!(writer.write_all(b"\n")); - } else { - tri!(writer.write_all(b",\n")); - } + tri!(writer.write_all(if first { b"\n" } else { b",\n" })); tri!(indent(writer, self.current_indent, self.indent)); Ok(()) } @@ -1962,11 +1955,7 @@ impl<'a> Formatter for PrettyFormatter<'a> { where W: ?Sized + io::Write, { - if first { - tri!(writer.write_all(b"\n")); - } else { - tri!(writer.write_all(b",\n")); - } + tri!(writer.write_all(if first { b"\n" } else { b",\n" })); indent(writer, self.current_indent, self.indent) } From 6fd698c9e164becd580db4d184d00ec04438fd14 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 5 Jan 2021 11:10:43 +0100 Subject: [PATCH 20/34] Further extract code out of deserialize_any --- src/de.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/de.rs b/src/de.rs index 236b5d751..3c5bf98ff 100644 --- a/src/de.rs +++ b/src/de.rs @@ -183,11 +183,12 @@ macro_rules! check_recursion { }; } -enum AnyResult { +enum AnyResult<'de, 's> { Null, Bool(bool), Number(bool), - String, + BorrowedString(&'de str), + CopiedString(&'s str), Array, Map, Error(Error), @@ -311,7 +312,7 @@ impl<'de, R: Read<'de>> Deserializer { Error::syntax(reason, position.line, position.column) } - fn parse_any_prefix(&mut self) -> AnyResult { + fn parse_any_prefix(&mut self) -> AnyResult<'de, '_> { match try_with!(self.parse_whitespace_in_value(), AnyResult::Error) { b'n' => { self.eat_char(); @@ -336,7 +337,10 @@ impl<'de, R: Read<'de>> Deserializer { b'"' => { self.eat_char(); self.scratch.clear(); - AnyResult::String + match try_with!(self.read.parse_str(&mut self.scratch), AnyResult::Error) { + Reference::Borrowed(s) => AnyResult::BorrowedString(s), + Reference::Copied(s) => AnyResult::CopiedString(s), + } } b'[' => { self.eat_char(); @@ -1442,10 +1446,8 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { AnyResult::Null => visitor.visit_unit(), AnyResult::Bool(b) => visitor.visit_bool(b), AnyResult::Number(positive) => tri!(self.parse_any_number(positive)).visit(visitor), - AnyResult::String => match tri!(self.read.parse_str(&mut self.scratch)) { - Reference::Borrowed(s) => visitor.visit_borrowed_str(s), - Reference::Copied(s) => visitor.visit_str(s), - }, + AnyResult::BorrowedString(s) => visitor.visit_borrowed_str(s), + AnyResult::CopiedString(s) => visitor.visit_str(s), AnyResult::Array => { let ret = visitor.visit_seq(SeqAccess::new(self)); From 9f16c61c0f352f9f6601dfcc86f417e7be3e5dc1 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 5 Jan 2021 11:22:11 +0100 Subject: [PATCH 21/34] refactor: Extract parse_option --- src/de.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/de.rs b/src/de.rs index 3c5bf98ff..d83d38893 100644 --- a/src/de.rs +++ b/src/de.rs @@ -409,6 +409,18 @@ impl<'de, R: Read<'de>> Deserializer { } } + #[inline] + fn parse_option(&mut self) -> Result> { + match tri!(self.parse_whitespace()) { + Some(b'n') => { + self.eat_char(); + tri!(self.parse_ident(b"ull")); + Ok(None) + } + _ => Ok(Some(())), + } + } + /// Returns the first non-whitespace byte without consuming it, or `Err` if /// EOF is encountered. fn parse_whitespace_in_value(&mut self) -> Result { @@ -1723,13 +1735,9 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - match tri!(self.parse_whitespace()) { - Some(b'n') => { - self.eat_char(); - tri!(self.parse_ident(b"ull")); - visitor.visit_none() - } - _ => visitor.visit_some(self), + match tri!(self.parse_option()) { + Some(()) => visitor.visit_some(self), + None => visitor.visit_none(), } } From d28a020426ad8a35dfe291a7e221a1d26728323a Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 5 Jan 2021 14:01:09 +0100 Subject: [PATCH 22/34] Shorten unit deserializing --- src/de.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/de.rs b/src/de.rs index d83d38893..573bb40a4 100644 --- a/src/de.rs +++ b/src/de.rs @@ -430,6 +430,12 @@ impl<'de, R: Read<'de>> Deserializer { } } + fn parse_whitespace_until_null(&mut self, visitor: &dyn Expected) -> Result<()> { + tri!(self.parse_whitespace_until(b'n', visitor)); + + self.parse_ident(b"ull") + } + fn parse_whitespace_until(&mut self, expected: u8, visitor: &dyn Expected) -> Result<()> { if tri!(self.parse_whitespace_in_value()) == expected { self.eat_char(); @@ -1745,9 +1751,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - tri!(self.parse_whitespace_until(b'n', &visitor)); - - tri!(self.parse_ident(b"ull")); + tri!(self.parse_whitespace_until_null(&visitor)); match visitor.visit_unit() { Ok(value) => Ok(value), From f77905a782a32d8909090b87d8f7754fd46b0886 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 5 Jan 2021 14:20:37 +0100 Subject: [PATCH 23/34] Extract helpers to reduce map_err calls --- src/ser.rs | 213 ++++++++++++++++++++++++++--------------------------- 1 file changed, 103 insertions(+), 110 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index c7201284e..7de99463f 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -78,23 +78,92 @@ where .map_err(Error::io) } + #[inline] + fn begin_object_key(&mut self, first: bool) -> Result<()> { + self.formatter + .begin_object_key(&mut self.writer, first) + .map_err(Error::io) + } + + #[inline] + fn end_object_key(&mut self) -> Result<()> { + self.formatter + .end_object_key(&mut self.writer) + .map_err(Error::io) + } + + #[inline] + fn begin_object(&mut self) -> Result<()> { + self.formatter + .begin_object(&mut self.writer) + .map_err(Error::io) + } + + #[inline] + fn begin_object_value(&mut self) -> Result<()> { + self.formatter + .begin_object_value(&mut self.writer) + .map_err(Error::io) + } + + #[inline] + fn end_object_value(&mut self) -> Result<()> { + self.formatter + .end_object_value(&mut self.writer) + .map_err(Error::io) + } + + #[inline] + fn end_object(&mut self) -> Result<()> { + self.formatter + .end_object(&mut self.writer) + .map_err(Error::io) + } + + #[inline] + fn begin_array(&mut self) -> Result<()> { + self.formatter + .begin_array(&mut self.writer) + .map_err(Error::io) + } + + #[inline] + fn begin_array_value(&mut self, first: bool) -> Result<()> { + self.formatter + .begin_array_value(&mut self.writer, first) + .map_err(Error::io) + } + + #[inline] + fn end_array_value(&mut self) -> Result<()> { + self.formatter + .end_array_value(&mut self.writer) + .map_err(Error::io) + } + + #[inline] + fn end_array(&mut self) -> Result<()> { + self.formatter + .end_array(&mut self.writer) + .map_err(Error::io) + } + + #[inline] + fn write_null(&mut self) -> Result<()> { + self.formatter + .write_null(&mut self.writer) + .map_err(Error::io) + } + fn serialize_variant(&mut self, variant: &'static str) -> Result<()> { tri!(self .formatter .begin_object(&mut self.writer) .map_err(Error::io)); - tri!(self - .formatter - .begin_object_key(&mut self.writer, true) - .map_err(Error::io)); + tri!(self.begin_object_key(true)); tri!(self.serialize_str(variant)); - tri!(self - .formatter - .end_object_key(&mut self.writer) - .map_err(Error::io)); - self.formatter - .begin_object_value(&mut self.writer) - .map_err(Error::io) + tri!(self.end_object_key()); + self.begin_object_value() } } @@ -215,10 +284,7 @@ where fn serialize_f32(self, value: f32) -> Result<()> { match value.classify() { FpCategory::Nan | FpCategory::Infinite => { - tri!(self - .formatter - .write_null(&mut self.writer) - .map_err(Error::io)); + tri!(self.write_null()); } _ => { tri!(self @@ -234,10 +300,7 @@ where fn serialize_f64(self, value: f64) -> Result<()> { match value.classify() { FpCategory::Nan | FpCategory::Infinite => { - tri!(self - .formatter - .write_null(&mut self.writer) - .map_err(Error::io)); + tri!(self.write_null()); } _ => { tri!(self @@ -274,10 +337,7 @@ where #[inline] fn serialize_unit(self) -> Result<()> { - tri!(self - .formatter - .write_null(&mut self.writer) - .map_err(Error::io)); + tri!(self.write_null()); Ok(()) } @@ -318,14 +378,8 @@ where { tri!(self.serialize_variant(variant)); tri!(value.serialize(&mut *self)); - tri!(self - .formatter - .end_object_value(&mut self.writer) - .map_err(Error::io)); - tri!(self - .formatter - .end_object(&mut self.writer) - .map_err(Error::io)); + tri!(self.end_object_value()); + tri!(self.end_object()); Ok(()) } @@ -344,15 +398,9 @@ where #[inline] fn serialize_seq(self, len: Option) -> Result { - tri!(self - .formatter - .begin_array(&mut self.writer) - .map_err(Error::io)); + tri!(self.begin_array()); if len == Some(0) { - tri!(self - .formatter - .end_array(&mut self.writer) - .map_err(Error::io)); + tri!(self.end_array()); Ok(Compound::Map { ser: self, state: State::Empty, @@ -393,15 +441,9 @@ where #[inline] fn serialize_map(self, len: Option) -> Result { - tri!(self - .formatter - .begin_object(&mut self.writer) - .map_err(Error::io)); + tri!(self.begin_object()); if len == Some(0) { - tri!(self - .formatter - .end_object(&mut self.writer) - .map_err(Error::io)); + tri!(self.end_object()); Ok(Compound::Map { ser: self, state: State::Empty, @@ -521,15 +563,10 @@ where { match self { Compound::Map { ser, state } => { - tri!(ser - .formatter - .begin_array_value(&mut ser.writer, *state == State::First) - .map_err(Error::io)); + tri!(ser.begin_array_value(*state == State::First)); *state = State::Rest; tri!(value.serialize(&mut **ser)); - ser.formatter - .end_array_value(&mut ser.writer) - .map_err(Error::io) + ser.end_array_value() } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -544,7 +581,7 @@ where Compound::Map { ser, state } => { match state { State::Empty => {} - _ => tri!(ser.formatter.end_array(&mut ser.writer).map_err(Error::io)), + _ => tri!(ser.end_array()), } Ok(()) } @@ -622,13 +659,10 @@ where Compound::Map { ser, state } => { match state { State::Empty => {} - _ => tri!(ser.formatter.end_array(&mut ser.writer).map_err(Error::io)), + _ => tri!(ser.end_array()), } - tri!(ser - .formatter - .end_object_value(&mut ser.writer) - .map_err(Error::io)); - tri!(ser.formatter.end_object(&mut ser.writer).map_err(Error::io)); + tri!(ser.end_object_value()); + tri!(ser.end_object()); Ok(()) } #[cfg(feature = "arbitrary_precision")] @@ -654,14 +688,12 @@ where { match self { Compound::Map { ser, state } => { - tri!(ser - .formatter - .begin_object_key_io(&mut ser.writer, *state == State::First)); + tri!(ser.begin_object_key(*state == State::First)); *state = State::Rest; tri!(key.serialize(MapKeySerializer { ser: *ser })); - ser.formatter.end_object_key_io(&mut ser.writer) + ser.end_object_key() } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -677,9 +709,9 @@ where { match self { Compound::Map { ser, .. } => { - tri!(ser.formatter.begin_object_value_io(&mut ser.writer)); + tri!(ser.begin_object_value()); tri!(value.serialize(&mut **ser)); - ser.formatter.end_object_value_io(&mut ser.writer) + ser.end_object_value() } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -693,7 +725,7 @@ where match self { Compound::Map { ser, state } => match state { State::Empty => Ok(()), - _ => ser.formatter.end_object(&mut ser.writer).map_err(Error::io), + _ => ser.end_object(), }, #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -779,13 +811,10 @@ where Compound::Map { ser, state } => { match state { State::Empty => {} - _ => tri!(ser.formatter.end_object(&mut ser.writer).map_err(Error::io)), + _ => tri!(ser.end_object()), } - tri!(ser - .formatter - .end_object_value(&mut ser.writer) - .map_err(Error::io)); - tri!(ser.formatter.end_object(&mut ser.writer).map_err(Error::io)); + tri!(ser.end_object_value()); + tri!(ser.end_object()); Ok(()) } #[cfg(feature = "arbitrary_precision")] @@ -1808,42 +1837,6 @@ pub trait Formatter { } } -trait FormatterExt: Formatter { - #[inline] - fn begin_object_key_io(&mut self, writer: &mut W, first: bool) -> Result<()> - where - W: ?Sized + io::Write, - { - self.begin_object_key(writer, first).map_err(Error::io) - } - - #[inline] - fn end_object_key_io(&mut self, writer: &mut W) -> Result<()> - where - W: ?Sized + io::Write, - { - self.end_object_key(writer).map_err(Error::io) - } - - #[inline] - fn begin_object_value_io(&mut self, writer: &mut W) -> Result<()> - where - W: ?Sized + io::Write, - { - self.begin_object_value(writer).map_err(Error::io) - } - - #[inline] - fn end_object_value_io(&mut self, writer: &mut W) -> Result<()> - where - W: ?Sized + io::Write, - { - self.end_object_value(writer).map_err(Error::io) - } -} - -impl FormatterExt for T where T: Formatter {} - /// This structure compacts a JSON value with no extra whitespace. #[derive(Clone, Debug)] pub struct CompactFormatter; From 760ccb2f4e15a113a40a274e4f9667bce035e86b Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 5 Jan 2021 14:26:31 +0100 Subject: [PATCH 24/34] refactor: Remove unnecessary tri! calls --- src/ser.rs | 158 ++++++++++++++++++----------------------------------- 1 file changed, 53 insertions(+), 105 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index 7de99463f..22b2d0c69 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -185,47 +185,37 @@ where #[inline] fn serialize_bool(self, value: bool) -> Result<()> { - tri!(self - .formatter + self.formatter .write_bool(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_i8(self, value: i8) -> Result<()> { - tri!(self - .formatter + self.formatter .write_i8(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_i16(self, value: i16) -> Result<()> { - tri!(self - .formatter + self.formatter .write_i16(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_i32(self, value: i32) -> Result<()> { - tri!(self - .formatter + self.formatter .write_i32(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_i64(self, value: i64) -> Result<()> { - tri!(self - .formatter + self.formatter .write_i64(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } serde_if_integer128! { @@ -238,38 +228,30 @@ where #[inline] fn serialize_u8(self, value: u8) -> Result<()> { - tri!(self - .formatter + self.formatter .write_u8(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_u16(self, value: u16) -> Result<()> { - tri!(self - .formatter + self.formatter .write_u16(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_u32(self, value: u32) -> Result<()> { - tri!(self - .formatter + self.formatter .write_u32(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_u64(self, value: u64) -> Result<()> { - tri!(self - .formatter + self.formatter .write_u64(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } serde_if_integer128! { @@ -283,33 +265,23 @@ where #[inline] fn serialize_f32(self, value: f32) -> Result<()> { match value.classify() { - FpCategory::Nan | FpCategory::Infinite => { - tri!(self.write_null()); - } - _ => { - tri!(self - .formatter - .write_f32(&mut self.writer, value) - .map_err(Error::io)); - } + FpCategory::Nan | FpCategory::Infinite => self.write_null(), + _ => self + .formatter + .write_f32(&mut self.writer, value) + .map_err(Error::io), } - Ok(()) } #[inline] fn serialize_f64(self, value: f64) -> Result<()> { match value.classify() { - FpCategory::Nan | FpCategory::Infinite => { - tri!(self.write_null()); - } - _ => { - tri!(self - .formatter - .write_f64(&mut self.writer, value) - .map_err(Error::io)); - } + FpCategory::Nan | FpCategory::Infinite => self.write_null(), + _ => self + .formatter + .write_f64(&mut self.writer, value) + .map_err(Error::io), } - Ok(()) } #[inline] @@ -321,8 +293,7 @@ where #[inline] fn serialize_str(self, value: &str) -> Result<()> { - tri!(format_escaped_str(&mut self.writer, &mut self.formatter, value).map_err(Error::io)); - Ok(()) + format_escaped_str(&mut self.writer, &mut self.formatter, value).map_err(Error::io) } #[inline] @@ -337,8 +308,7 @@ where #[inline] fn serialize_unit(self) -> Result<()> { - tri!(self.write_null()); - Ok(()) + self.write_null() } #[inline] @@ -379,8 +349,7 @@ where tri!(self.serialize_variant(variant)); tri!(value.serialize(&mut *self)); tri!(self.end_object_value()); - tri!(self.end_object()); - Ok(()) + self.end_object() } #[inline] @@ -578,13 +547,10 @@ where #[inline] fn end(self) -> Result<()> { match self { - Compound::Map { ser, state } => { - match state { - State::Empty => {} - _ => tri!(ser.end_array()), - } - Ok(()) - } + Compound::Map { ser, state } => match state { + State::Empty => Ok(()), + _ => ser.end_array(), + }, #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), #[cfg(feature = "raw_value")] @@ -662,8 +628,7 @@ where _ => tri!(ser.end_array()), } tri!(ser.end_object_value()); - tri!(ser.end_object()); - Ok(()) + ser.end_object() } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -753,8 +718,7 @@ where #[cfg(feature = "arbitrary_precision")] Compound::Number { ser, .. } => { if key == crate::number::TOKEN { - tri!(value.serialize(NumberStrEmitter(ser))); - Ok(()) + value.serialize(NumberStrEmitter(ser)) } else { Err(invalid_number()) } @@ -762,8 +726,7 @@ where #[cfg(feature = "raw_value")] Compound::RawValue { ser, .. } => { if key == crate::raw::TOKEN { - tri!(value.serialize(RawValueStrEmitter(ser))); - Ok(()) + value.serialize(RawValueStrEmitter(ser)) } else { Err(invalid_raw_value()) } @@ -814,8 +777,7 @@ where _ => tri!(ser.end_object()), } tri!(ser.end_object_value()); - tri!(ser.end_object()); - Ok(()) + ser.end_object() } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -893,8 +855,7 @@ where .formatter .write_i8(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self.ser.end_string()); - Ok(()) + self.ser.end_string() } fn serialize_i16(self, value: i16) -> Result<()> { @@ -904,8 +865,7 @@ where .formatter .write_i16(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self.ser.end_string()); - Ok(()) + self.ser.end_string() } fn serialize_i32(self, value: i32) -> Result<()> { @@ -915,8 +875,7 @@ where .formatter .write_i32(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self.ser.end_string()); - Ok(()) + self.ser.end_string() } fn serialize_i64(self, value: i64) -> Result<()> { @@ -926,8 +885,7 @@ where .formatter .write_i64(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self.ser.end_string()); - Ok(()) + self.ser.end_string() } serde_if_integer128! { @@ -938,8 +896,7 @@ where .formatter .write_number_str(&mut self.ser.writer, &value.to_string()) .map_err(Error::io)); - tri!(self.ser.end_string()); - Ok(()) + self.ser.end_string() } } @@ -950,8 +907,7 @@ where .formatter .write_u8(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self.ser.end_string()); - Ok(()) + self.ser.end_string() } fn serialize_u16(self, value: u16) -> Result<()> { @@ -961,8 +917,7 @@ where .formatter .write_u16(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self.ser.end_string()); - Ok(()) + self.ser.end_string() } fn serialize_u32(self, value: u32) -> Result<()> { @@ -972,8 +927,7 @@ where .formatter .write_u32(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self.ser.end_string()); - Ok(()) + self.ser.end_string() } fn serialize_u64(self, value: u64) -> Result<()> { @@ -983,8 +937,7 @@ where .formatter .write_u64(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self.ser.end_string()); - Ok(()) + self.ser.end_string() } serde_if_integer128! { @@ -995,8 +948,7 @@ where .formatter .write_number_str(&mut self.ser.writer, &value.to_string()) .map_err(Error::io)); - tri!(self.ser.end_string()); - Ok(()) + self.ser.end_string() } } @@ -1905,8 +1857,7 @@ impl<'a> Formatter for PrettyFormatter<'a> { W: ?Sized + io::Write, { tri!(writer.write_all(if first { b"\n" } else { b",\n" })); - tri!(indent(writer, self.current_indent, self.indent)); - Ok(()) + indent(writer, self.current_indent, self.indent) } #[inline] @@ -1977,8 +1928,7 @@ where { tri!(formatter.begin_string(writer)); tri!(format_escaped_str_contents(writer, formatter, value)); - tri!(formatter.end_string(writer)); - Ok(()) + formatter.end_string(writer) } fn format_escaped_str_contents( @@ -2063,8 +2013,7 @@ where T: ?Sized + Serialize, { let mut ser = Serializer::new(writer); - tri!(value.serialize(&mut ser)); - Ok(()) + value.serialize(&mut ser) } /// Serialize the given data structure as pretty-printed JSON into the IO @@ -2082,8 +2031,7 @@ where T: ?Sized + Serialize, { let mut ser = Serializer::pretty(writer); - tri!(value.serialize(&mut ser)); - Ok(()) + value.serialize(&mut ser) } /// Serialize the given data structure as a JSON byte vector. From 9956638e24e402d4f3b557965062c2f6e5415e21 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 5 Jan 2021 14:35:18 +0100 Subject: [PATCH 25/34] refactor: Extract a less generic part of deserialize_number --- src/de.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/de.rs b/src/de.rs index 573bb40a4..e6eae0820 100644 --- a/src/de.rs +++ b/src/de.rs @@ -366,6 +366,19 @@ impl<'de, R: Read<'de>> Deserializer { } } + fn parse_number_prefix(&mut self, exp: &dyn Expected) -> Result { + let peek = tri!(self.parse_whitespace_in_value()); + + match peek { + b'-' => { + self.eat_char(); + self.parse_integer(false) + } + b'0'..=b'9' => self.parse_integer(true), + _ => Err(self.peek_invalid_type(exp)), + } + } + fn parse_str<'s>(&'s mut self) -> Result> { self.eat_char(); self.scratch.clear(); @@ -520,16 +533,7 @@ impl<'de, R: Read<'de>> Deserializer { where V: de::Visitor<'de>, { - let peek = tri!(self.parse_whitespace_in_value()); - - let value = match peek { - b'-' => { - self.eat_char(); - tri!(self.parse_integer(false)).visit(visitor) - } - b'0'..=b'9' => tri!(self.parse_integer(true)).visit(visitor), - _ => Err(self.peek_invalid_type(&visitor)), - }; + let value = tri!(self.parse_number_prefix(&visitor)).visit(visitor); match value { Ok(value) => Ok(value), From 0f156888c15c9a8b322a49d61ee6191a13607bbb Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 5 Jan 2021 15:16:55 +0100 Subject: [PATCH 26/34] refactor: Extract code from deserialize_enum --- src/de.rs | 61 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/de.rs b/src/de.rs index e6eae0820..a1a221f09 100644 --- a/src/de.rs +++ b/src/de.rs @@ -150,6 +150,12 @@ enum StructResult<'a, R> { Error(Error), } +enum EnumResult<'a, R> { + Variant(VariantAccess<'a, R>), + Unit(UnitVariantAccess<'a, R>), + Error(Error), +} + #[cfg(not(feature = "unbounded_depth"))] macro_rules! if_checking_recursion_limit { ($($body:tt)*) => { @@ -422,6 +428,35 @@ impl<'de, R: Read<'de>> Deserializer { } } + #[inline] + fn parse_enum_prefix(&mut self) -> EnumResult<'_, R> { + match try_with!(self.parse_whitespace_in_value(), EnumResult::Error) { + b'{' => { + self.eat_char(); + if_checking_recursion_limit! { + self.remaining_depth -= 1; + if self.remaining_depth == 0 { + return EnumResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); + } + } + EnumResult::Variant(VariantAccess::new(self)) + } + b'"' => EnumResult::Unit(UnitVariantAccess::new(self)), + _ => EnumResult::Error(self.peek_error(ErrorCode::ExpectedSomeValue)), + } + } + + #[inline] + fn parse_enum_suffix(&mut self) -> Result<()> { + match tri!(self.parse_whitespace_in_object()) { + b'}' => { + self.eat_char(); + Ok(()) + } + _ => Err(self.error(ErrorCode::ExpectedSomeValue)), + } + } + #[inline] fn parse_option(&mut self) -> Result> { match tri!(self.parse_whitespace()) { @@ -1875,24 +1910,14 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - match tri!(self.parse_whitespace_in_value()) { - b'{' => { - self.eat_char(); - check_recursion! { - self; - let value = tri!(visitor.visit_enum(VariantAccess::new(self))); - } - - match tri!(self.parse_whitespace_in_object()) { - b'}' => { - self.eat_char(); - Ok(value) - } - _ => Err(self.error(ErrorCode::ExpectedSomeValue)), - } - } - b'"' => visitor.visit_enum(UnitVariantAccess::new(self)), - _ => Err(self.peek_error(ErrorCode::ExpectedSomeValue)), + match self.parse_enum_prefix() { + EnumResult::Variant(variant) => { + let value = tri!(visitor.visit_enum(variant)); + tri!(self.parse_enum_suffix()); + Ok(value) + } + EnumResult::Unit(unit) => visitor.visit_enum(unit), + EnumResult::Error(err) => Err(err), } } From 60cdfbdfbbfd92dd807c748f797896768ffc15e3 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 5 Jan 2021 15:21:45 +0100 Subject: [PATCH 27/34] refactor: De-duplicate the recursion checking --- src/de.rs | 44 ++++++++++++++------------------------------ 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/src/de.rs b/src/de.rs index a1a221f09..8d347384e 100644 --- a/src/de.rs +++ b/src/de.rs @@ -172,6 +172,15 @@ macro_rules! if_checking_recursion_limit { }; } +macro_rules! check_recursion_prefix { + ($self_: ident, $error: ident) => { + $self_.remaining_depth -= 1; + if $self_.remaining_depth == 0 { + return $error::Error($self_.error(ErrorCode::RecursionLimitExceeded)); + } + }; +} + macro_rules! check_recursion { ($this:ident; $($body:tt)*) => { if_checking_recursion_limit! { @@ -350,22 +359,12 @@ impl<'de, R: Read<'de>> Deserializer { } b'[' => { self.eat_char(); - if_checking_recursion_limit! { - self.remaining_depth -= 1; - if self.remaining_depth == 0 { - return AnyResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); - } - } + check_recursion_prefix!(self, AnyResult); AnyResult::Array } b'{' => { self.eat_char(); - if_checking_recursion_limit! { - self.remaining_depth -= 1; - if self.remaining_depth == 0 { - return AnyResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); - } - } + check_recursion_prefix!(self, AnyResult); AnyResult::Map } _ => AnyResult::Error(self.peek_error(ErrorCode::ExpectedSomeValue)), @@ -402,22 +401,12 @@ impl<'de, R: Read<'de>> Deserializer { match self.parse_whitespace_in_value() { Ok(b'[') => { self.eat_char(); - if_checking_recursion_limit! { - self.remaining_depth -= 1; - if self.remaining_depth == 0 { - return StructResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); - } - } + check_recursion_prefix!(self, StructResult); StructResult::Array(SeqAccess::new(self)) } Ok(b'{') => { self.eat_char(); - if_checking_recursion_limit! { - self.remaining_depth -= 1; - if self.remaining_depth == 0 { - return StructResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); - } - } + check_recursion_prefix!(self, StructResult); StructResult::Map(MapAccess::new(self)) } Ok(_) => { @@ -433,12 +422,7 @@ impl<'de, R: Read<'de>> Deserializer { match try_with!(self.parse_whitespace_in_value(), EnumResult::Error) { b'{' => { self.eat_char(); - if_checking_recursion_limit! { - self.remaining_depth -= 1; - if self.remaining_depth == 0 { - return EnumResult::Error(self.error(ErrorCode::RecursionLimitExceeded)); - } - } + check_recursion_prefix!(self, EnumResult); EnumResult::Variant(VariantAccess::new(self)) } b'"' => EnumResult::Unit(UnitVariantAccess::new(self)), From 4de41fdb7315ed2931e995a57eafc8a32fd4c3ff Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Mon, 11 Jan 2021 12:26:04 +0100 Subject: [PATCH 28/34] Add an OptionResult enum --- src/de.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/de.rs b/src/de.rs index 8d347384e..9e2f6a2fd 100644 --- a/src/de.rs +++ b/src/de.rs @@ -156,6 +156,12 @@ enum EnumResult<'a, R> { Error(Error), } +enum OptionResult { + Some, + None, + Error(Error), +} + #[cfg(not(feature = "unbounded_depth"))] macro_rules! if_checking_recursion_limit { ($($body:tt)*) => { @@ -442,14 +448,14 @@ impl<'de, R: Read<'de>> Deserializer { } #[inline] - fn parse_option(&mut self) -> Result> { - match tri!(self.parse_whitespace()) { + fn parse_option(&mut self) -> OptionResult { + match try_with!(self.parse_whitespace(), OptionResult::Error) { Some(b'n') => { self.eat_char(); - tri!(self.parse_ident(b"ull")); - Ok(None) + try_with!(self.parse_ident(b"ull"), OptionResult::Error); + OptionResult::None } - _ => Ok(Some(())), + _ => OptionResult::Some, } } @@ -1764,9 +1770,10 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - match tri!(self.parse_option()) { - Some(()) => visitor.visit_some(self), - None => visitor.visit_none(), + match self.parse_option() { + OptionResult::Some => visitor.visit_some(self), + OptionResult::None => visitor.visit_none(), + OptionResult::Error(err) => Err(err), } } From 9e561871f14e17812a355f0423019bc4d8e1b884 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Mon, 11 Jan 2021 13:40:47 +0100 Subject: [PATCH 29/34] inline --- src/de.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/de.rs b/src/de.rs index 9e2f6a2fd..29399192a 100644 --- a/src/de.rs +++ b/src/de.rs @@ -423,7 +423,6 @@ impl<'de, R: Read<'de>> Deserializer { } } - #[inline] fn parse_enum_prefix(&mut self) -> EnumResult<'_, R> { match try_with!(self.parse_whitespace_in_value(), EnumResult::Error) { b'{' => { @@ -474,6 +473,7 @@ impl<'de, R: Read<'de>> Deserializer { self.parse_ident(b"ull") } + #[inline] fn parse_whitespace_until(&mut self, expected: u8, visitor: &dyn Expected) -> Result<()> { if tri!(self.parse_whitespace_in_value()) == expected { self.eat_char(); @@ -1639,6 +1639,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { self.deserialize_str(visitor) } + #[inline] fn deserialize_str(self, visitor: V) -> Result where V: de::Visitor<'de>, @@ -1777,6 +1778,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { } } + #[inline] fn deserialize_unit(self, visitor: V) -> Result where V: de::Visitor<'de>, @@ -1866,6 +1868,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { } } + #[inline] fn deserialize_struct( self, _name: &'static str, @@ -1983,6 +1986,7 @@ impl<'de, 'a, R: Read<'de> + 'a> SeqAccess<'a, R> { impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> { type Error = Error; + #[inline] fn next_element_seed(&mut self, seed: T) -> Result> where T: de::DeserializeSeed<'de>, @@ -2045,6 +2049,7 @@ impl<'de, 'a, R: Read<'de> + 'a> MapAccess<'a, R> { impl<'de, 'a, R: Read<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, R> { type Error = Error; + #[inline] fn next_key_seed(&mut self, seed: K) -> Result> where K: de::DeserializeSeed<'de>, @@ -2056,6 +2061,7 @@ impl<'de, 'a, R: Read<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, R> { }) } + #[inline] fn next_value_seed(&mut self, seed: V) -> Result where V: de::DeserializeSeed<'de>, From 010eb7cec9fdfeffc3dbfa19d3a456df038ae961 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 12 Jan 2021 10:50:55 +0100 Subject: [PATCH 30/34] Extract prefixes for deserialize_seq and map --- src/de.rs | 61 +++++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/src/de.rs b/src/de.rs index 29399192a..a5edad51e 100644 --- a/src/de.rs +++ b/src/de.rs @@ -179,27 +179,10 @@ macro_rules! if_checking_recursion_limit { } macro_rules! check_recursion_prefix { - ($self_: ident, $error: ident) => { + ($self_: ident, $error: path) => { $self_.remaining_depth -= 1; if $self_.remaining_depth == 0 { - return $error::Error($self_.error(ErrorCode::RecursionLimitExceeded)); - } - }; -} - -macro_rules! check_recursion { - ($this:ident; $($body:tt)*) => { - if_checking_recursion_limit! { - $this.remaining_depth -= 1; - if $this.remaining_depth == 0 { - return Err($this.error(ErrorCode::RecursionLimitExceeded)); - } - } - - $($body)* - - if_checking_recursion_limit! { - $this.remaining_depth += 1; + return $error($self_.error(ErrorCode::RecursionLimitExceeded)); } }; } @@ -365,12 +348,12 @@ impl<'de, R: Read<'de>> Deserializer { } b'[' => { self.eat_char(); - check_recursion_prefix!(self, AnyResult); + check_recursion_prefix!(self, AnyResult::Error); AnyResult::Array } b'{' => { self.eat_char(); - check_recursion_prefix!(self, AnyResult); + check_recursion_prefix!(self, AnyResult::Error); AnyResult::Map } _ => AnyResult::Error(self.peek_error(ErrorCode::ExpectedSomeValue)), @@ -403,16 +386,28 @@ impl<'de, R: Read<'de>> Deserializer { self.read.parse_str(&mut self.scratch) } + fn parse_seq_prefix(&mut self, exp: &dyn Expected) -> Result<()> { + tri!(self.parse_whitespace_until(b'[', exp)); + check_recursion_prefix!(self, Err); + Ok(()) + } + + fn parse_map_prefix(&mut self, exp: &dyn Expected) -> Result<()> { + tri!(self.parse_whitespace_until(b'{', exp)); + check_recursion_prefix!(self, Err); + Ok(()) + } + fn parse_struct_prefix(&mut self, exp: &dyn Expected) -> StructResult<'_, R> { match self.parse_whitespace_in_value() { Ok(b'[') => { self.eat_char(); - check_recursion_prefix!(self, StructResult); + check_recursion_prefix!(self, StructResult::Error); StructResult::Array(SeqAccess::new(self)) } Ok(b'{') => { self.eat_char(); - check_recursion_prefix!(self, StructResult); + check_recursion_prefix!(self, StructResult::Error); StructResult::Map(MapAccess::new(self)) } Ok(_) => { @@ -427,7 +422,7 @@ impl<'de, R: Read<'de>> Deserializer { match try_with!(self.parse_whitespace_in_value(), EnumResult::Error) { b'{' => { self.eat_char(); - check_recursion_prefix!(self, EnumResult); + check_recursion_prefix!(self, EnumResult::Error); EnumResult::Variant(VariantAccess::new(self)) } b'"' => EnumResult::Unit(UnitVariantAccess::new(self)), @@ -1819,14 +1814,11 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - tri!(self.parse_whitespace_until(b'[', &visitor)); + tri!(self.parse_seq_prefix(&visitor)); - check_recursion! { - self; - let ret = visitor.visit_seq(SeqAccess::new(self)); - } + let ret = visitor.visit_seq(SeqAccess::new(self)); - match (ret, self.end_seq()) { + match (ret, self.end_recursion_and_seq()) { (Ok(ret), Ok(())) => Ok(ret), (Err(err), _) | (_, Err(err)) => Err(self.fix_position(err)), } @@ -1855,14 +1847,11 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - tri!(self.parse_whitespace_until(b'{', &visitor)); + tri!(self.parse_map_prefix(&visitor)); - check_recursion! { - self; - let ret = visitor.visit_map(MapAccess::new(self)); - } + let ret = visitor.visit_map(MapAccess::new(self)); - match (ret, self.end_map()) { + match (ret, self.end_recursion_and_map()) { (Ok(ret), Ok(())) => Ok(ret), (Err(err), _) | (_, Err(err)) => Err(self.fix_position(err)), } From 206705898d216d1a6748005569ead5422b7ea751 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 12 Jan 2021 10:55:57 +0100 Subject: [PATCH 31/34] Reuse Deserialzer::parse_str --- src/de.rs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/de.rs b/src/de.rs index a5edad51e..3b36bd8ea 100644 --- a/src/de.rs +++ b/src/de.rs @@ -338,14 +338,10 @@ impl<'de, R: Read<'de>> Deserializer { AnyResult::Number(false) } b'0'..=b'9' => AnyResult::Number(true), - b'"' => { - self.eat_char(); - self.scratch.clear(); - match try_with!(self.read.parse_str(&mut self.scratch), AnyResult::Error) { - Reference::Borrowed(s) => AnyResult::BorrowedString(s), - Reference::Copied(s) => AnyResult::CopiedString(s), - } - } + b'"' => match try_with!(self.parse_str(), AnyResult::Error) { + Reference::Borrowed(s) => AnyResult::BorrowedString(s), + Reference::Copied(s) => AnyResult::CopiedString(s), + }, b'[' => { self.eat_char(); check_recursion_prefix!(self, AnyResult::Error); @@ -379,6 +375,12 @@ impl<'de, R: Read<'de>> Deserializer { self.read.parse_str(&mut self.scratch) } + fn parse_str_raw<'s>(&'s mut self) -> Result> { + self.eat_char(); + self.scratch.clear(); + self.read.parse_str_raw(&mut self.scratch) + } + fn parse_str_prefix<'s>(&'s mut self, exp: &dyn Expected) -> Result> { tri!(self.parse_whitespace_until(b'"', exp)); @@ -1734,14 +1736,10 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { let peek = tri!(self.parse_whitespace_in_value()); let value = match peek { - b'"' => { - self.eat_char(); - self.scratch.clear(); - match tri!(self.read.parse_str_raw(&mut self.scratch)) { - Reference::Borrowed(b) => visitor.visit_borrowed_bytes(b), - Reference::Copied(b) => visitor.visit_bytes(b), - } - } + b'"' => match tri!(self.parse_str_raw()) { + Reference::Borrowed(b) => visitor.visit_borrowed_bytes(b), + Reference::Copied(b) => visitor.visit_bytes(b), + }, b'[' => self.deserialize_seq(visitor), _ => Err(self.peek_invalid_type(&visitor)), }; From 0fa7a8fde89a8afd46797c39a5106d580770311a Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 12 Jan 2021 11:15:14 +0100 Subject: [PATCH 32/34] Remove end_map, end_seq --- src/de.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/de.rs b/src/de.rs index 3b36bd8ea..f08e28f85 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1196,10 +1196,6 @@ impl<'de, R: Read<'de>> Deserializer { if_checking_recursion_limit! { self.remaining_depth += 1; } - self.end_seq() - } - - fn end_seq(&mut self) -> Result<()> { match tri!(self.parse_whitespace()) { Some(b']') => { self.eat_char(); @@ -1221,10 +1217,6 @@ impl<'de, R: Read<'de>> Deserializer { if_checking_recursion_limit! { self.remaining_depth += 1; } - self.end_map() - } - - fn end_map(&mut self) -> Result<()> { match tri!(self.parse_whitespace_in_object()) { b'}' => { self.eat_char(); From f59526786cef04c187e3701570364a69430dbe3d Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 12 Jan 2021 11:17:27 +0100 Subject: [PATCH 33/34] Fix check_recursion_prefix --- src/de.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/de.rs b/src/de.rs index f08e28f85..63cca7b0d 100644 --- a/src/de.rs +++ b/src/de.rs @@ -180,9 +180,11 @@ macro_rules! if_checking_recursion_limit { macro_rules! check_recursion_prefix { ($self_: ident, $error: path) => { - $self_.remaining_depth -= 1; - if $self_.remaining_depth == 0 { - return $error($self_.error(ErrorCode::RecursionLimitExceeded)); + if_checking_recursion_limit! { + $self_.remaining_depth -= 1; + if $self_.remaining_depth == 0 { + return $error($self_.error(ErrorCode::RecursionLimitExceeded)); + } } }; } From 60e4ac239f3e8d6c570af093780e2282319ec6a4 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 12 Jan 2021 11:36:45 +0100 Subject: [PATCH 34/34] Fix clippy --- src/de.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/de.rs b/src/de.rs index 63cca7b0d..e263f333a 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1572,13 +1572,10 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { { let mut buf = String::new(); - match tri!(self.parse_whitespace_in_value()) { - b'-' => { - self.eat_char(); - buf.push('-'); - } - _ => {} - }; + if tri!(self.parse_whitespace_in_value()) == b'-' { + self.eat_char(); + buf.push('-'); + } tri!(self.scan_integer128(&mut buf)); @@ -1599,11 +1596,8 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - match tri!(self.parse_whitespace_in_value()) { - b'-' => { - return Err(self.peek_error(ErrorCode::NumberOutOfRange)); - } - _ => {} + if tri!(self.parse_whitespace_in_value()) == b'-' { + return Err(self.peek_error(ErrorCode::NumberOutOfRange)); } let mut buf = String::new();