From 5927cc36283c3674d72a3bf6da02d02c07c1b757 Mon Sep 17 00:00:00 2001 From: NAlexandrov Date: Tue, 13 Dec 2022 18:33:21 +0700 Subject: [PATCH 1/2] fix: parsing numbers more than i32 and u32 --- pbjson-types/src/value.rs | 44 +++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/pbjson-types/src/value.rs b/pbjson-types/src/value.rs index 9ea05ad..98e9e67 100644 --- a/pbjson-types/src/value.rs +++ b/pbjson-types/src/value.rs @@ -152,14 +152,20 @@ impl<'de> serde::de::Visitor<'de> for KindVisitor { where E: de::Error, { - self.visit_i32(v.try_into().map_err(de::Error::custom)?) + if v > -(1 << 53) && v < 1 << 53 { + return Ok(Kind::NumberValue(v as f64)); + } + + Err(de::Error::custom( + "out of range integral type conversion attempted", + )) } fn visit_i128(self, v: i128) -> Result where E: de::Error, { - self.visit_i32(v.try_into().map_err(de::Error::custom)?) + self.visit_i64(v.try_into().map_err(de::Error::custom)?) } fn visit_u8(self, v: u8) -> Result @@ -187,14 +193,20 @@ impl<'de> serde::de::Visitor<'de> for KindVisitor { where E: de::Error, { - self.visit_u32(v.try_into().map_err(de::Error::custom)?) + if v < 1 << 53 { + return Ok(Kind::NumberValue(v as f64)); + } + + Err(de::Error::custom( + "out of range integral type conversion attempted", + )) } fn visit_u128(self, v: u128) -> Result where E: de::Error, { - self.visit_u32(v.try_into().map_err(de::Error::custom)?) + self.visit_u64(v.try_into().map_err(de::Error::custom)?) } fn visit_f32(self, v: f32) -> Result @@ -325,4 +337,28 @@ mod tests { assert!(serde_json::to_value(Value::from(f64::INFINITY)).is_err()); assert!(serde_json::to_value(Value::from(f64::NEG_INFINITY)).is_err()); } + + #[test] + fn parse_max_safe_integer() { + let max_safe_integer: i64 = 9007199254740991; + let json = serde_json::json!(max_safe_integer); + let vec = serde_json::to_vec(&json).unwrap(); + let pb = serde_json::from_slice::(&vec).unwrap(); + assert_eq!( + serde_json::to_value(pb).unwrap(), + serde_json::json!(max_safe_integer as f64) + ); + } + + #[test] + fn parse_min_safe_integer() { + let min_safe_integer: i64 = -9007199254740991; + let json = serde_json::json!(min_safe_integer); + let vec = serde_json::to_vec(&json).unwrap(); + let pb = serde_json::from_slice::(&vec).unwrap(); + assert_eq!( + serde_json::to_value(pb).unwrap(), + serde_json::json!(min_safe_integer as f64) + ); + } } From baa7397008a18df3c7e8a7590c70c625052aaa05 Mon Sep 17 00:00:00 2001 From: NAlexandrov Date: Mon, 9 Jan 2023 17:14:07 +0700 Subject: [PATCH 2/2] fix: f64::MANTISSA_DIGITS instead of 53 --- pbjson-types/src/value.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pbjson-types/src/value.rs b/pbjson-types/src/value.rs index 98e9e67..c3fc87b 100644 --- a/pbjson-types/src/value.rs +++ b/pbjson-types/src/value.rs @@ -152,7 +152,7 @@ impl<'de> serde::de::Visitor<'de> for KindVisitor { where E: de::Error, { - if v > -(1 << 53) && v < 1 << 53 { + if v > -(1 << f64::MANTISSA_DIGITS) && v < 1 << f64::MANTISSA_DIGITS { return Ok(Kind::NumberValue(v as f64)); } @@ -193,7 +193,7 @@ impl<'de> serde::de::Visitor<'de> for KindVisitor { where E: de::Error, { - if v < 1 << 53 { + if v < 1 << f64::MANTISSA_DIGITS { return Ok(Kind::NumberValue(v as f64)); }