From eeb2bcd3f2fd2300de21381e23b3cebd33bfca30 Mon Sep 17 00:00:00 2001 From: baishen Date: Tue, 6 Jan 2026 16:16:52 +0800 Subject: [PATCH] =?UTF-8?q?Align=20`arbitrary=5Fprecision`=20number=20stri?= =?UTF-8?q?ngs=20with=20zmij=E2=80=99s=20formatting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/de.rs | 18 ++++++++++++------ src/number.rs | 7 +++++-- tests/test.rs | 24 +++++++++++++++--------- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/de.rs b/src/de.rs index 4080c54..f41890a 100644 --- a/src/de.rs +++ b/src/de.rs @@ -993,7 +993,7 @@ impl<'de, R: Read<'de>> Deserializer { fn scan_number(&mut self, buf: &mut String) -> Result<()> { match tri!(self.peek_or_null()) { b'.' => self.scan_decimal(buf), - e @ (b'e' | b'E') => self.scan_exponent(e as char, buf), + b'e' | b'E' => self.scan_exponent(buf), _ => Ok(()), } } @@ -1018,26 +1018,32 @@ impl<'de, R: Read<'de>> Deserializer { } match tri!(self.peek_or_null()) { - e @ (b'e' | b'E') => self.scan_exponent(e as char, buf), + b'e' | b'E' => self.scan_exponent(buf), _ => Ok(()), } } #[cfg(feature = "arbitrary_precision")] - fn scan_exponent(&mut self, e: char, buf: &mut String) -> Result<()> { + fn scan_exponent(&mut self, buf: &mut String) -> Result<()> { self.eat_char(); - buf.push(e); + buf.push('e'); - match tri!(self.peek_or_null()) { + let has_sign = match tri!(self.peek_or_null()) { b'+' => { self.eat_char(); buf.push('+'); + true } b'-' => { self.eat_char(); buf.push('-'); + true } - _ => {} + _ => false, + }; + + if !has_sign { + buf.push('+'); } // Make sure a digit follows the exponent place. diff --git a/src/number.rs b/src/number.rs index 51c2d6d..dfd35e4 100644 --- a/src/number.rs +++ b/src/number.rs @@ -279,8 +279,11 @@ impl Number { Some(Number { n }) } - /// Returns the exact original JSON representation that this Number was - /// parsed from. + /// Returns the JSON representation that this Number was parsed from. + /// + /// When parsing with serde_json's `arbitrary_precision` feature enabled, + /// positive exponents are normalized to include an explicit `+` sign so + /// that `1e140` becomes `1e+140`. /// /// For numbers constructed not via parsing, such as by `From`, returns /// the JSON representation that serde\_json would serialize for this diff --git a/tests/test.rs b/tests/test.rs index f371f6f..4e15da7 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1037,22 +1037,28 @@ fn test_parse_number() { #[cfg(feature = "arbitrary_precision")] test_parse_ok(vec![ - ("1e999", Number::from_string_unchecked("1e999".to_owned())), + ("1e999", Number::from_string_unchecked("1e+999".to_owned())), ("1e+999", Number::from_string_unchecked("1e+999".to_owned())), - ("-1e999", Number::from_string_unchecked("-1e999".to_owned())), + ( + "-1e999", + Number::from_string_unchecked("-1e+999".to_owned()), + ), ("1e-999", Number::from_string_unchecked("1e-999".to_owned())), - ("1E999", Number::from_string_unchecked("1E999".to_owned())), - ("1E+999", Number::from_string_unchecked("1E+999".to_owned())), - ("-1E999", Number::from_string_unchecked("-1E999".to_owned())), - ("1E-999", Number::from_string_unchecked("1E-999".to_owned())), - ("1E+000", Number::from_string_unchecked("1E+000".to_owned())), + ("1E999", Number::from_string_unchecked("1e+999".to_owned())), + ("1E+999", Number::from_string_unchecked("1e+999".to_owned())), + ( + "-1E999", + Number::from_string_unchecked("-1e+999".to_owned()), + ), + ("1E-999", Number::from_string_unchecked("1e-999".to_owned())), + ("1E+000", Number::from_string_unchecked("1e+000".to_owned())), ( "2.3e999", - Number::from_string_unchecked("2.3e999".to_owned()), + Number::from_string_unchecked("2.3e+999".to_owned()), ), ( "-2.3e999", - Number::from_string_unchecked("-2.3e999".to_owned()), + Number::from_string_unchecked("-2.3e+999".to_owned()), ), ]); }