Skip to content

Commit

Permalink
Merge pull request #59 from CosmWasm/54-serialize-128bit-numbers
Browse files Browse the repository at this point in the history
Serialize / Deserialize u128 and i128 as numbers instead of strings
  • Loading branch information
chipshort authored Jul 28, 2023
2 parents be32160 + 73bd5ec commit ccb8fbd
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 95 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed

- Serialize / deserialize `u128`/`i128` types as numbers instead of strings
([#59]).<br/> **Please note:** this breaks deserialization of `u128`/`i128`
serialized with older versions of `serde-json-wasm`.

[#59]: https://github.com/CosmWasm/serde-json-wasm/pull/59

## [0.5.1] - 2023-04-11

### Added
Expand Down
5 changes: 2 additions & 3 deletions src/de/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,7 @@ impl<'de, 'a> de::Deserializer<'de> for MapKey<'a, 'de> {
where
V: Visitor<'de>,
{
// default implementation includes string unparsing
self.de.deserialize_i128(visitor)
deserialize_signed_key!(self, visitor, i128, visit_i128)
}

fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
Expand Down Expand Up @@ -196,7 +195,7 @@ impl<'de, 'a> de::Deserializer<'de> for MapKey<'a, 'de> {
where
V: Visitor<'de>,
{
self.de.deserialize_u128(visitor)
deserialize_unsigned_key!(self, visitor, u128, visit_u128)
}

fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
Expand Down
74 changes: 22 additions & 52 deletions src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,25 +358,7 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: Visitor<'de>,
{
match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
b'"' => self.eat_char(),
_ => return Err(Error::InvalidType),
};

let result = match self.peek() {
// after rust merged or-patterns feature, these two clause can be merged.
// error[E0658]: or-patterns syntax is experimental
Some(b'0'..=b'9') => deserialize_signed!(self, visitor, i128, visit_i128),
Some(b'-') => deserialize_signed!(self, visitor, i128, visit_i128),
_ => return Err(Error::InvalidType),
};
match self.peek() {
Some(b'"') => {
self.eat_char();
result
}
_ => Err(Error::InvalidType),
}
deserialize_signed!(self, visitor, i128, visit_i128)
}

fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
Expand Down Expand Up @@ -411,25 +393,7 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: Visitor<'de>,
{
match self.parse_whitespace().ok_or(Error::EofWhileParsingValue)? {
b'"' => {
self.eat_char();
}
_ => return Err(Error::InvalidType),
};

let result = match self.peek() {
Some(b'-') => return Err(Error::InvalidNumber),
Some(b'0'..=b'9') => deserialize_unsigned!(self, visitor, u128, visit_u128),
_ => return Err(Error::InvalidType),
};
match self.peek() {
Some(b'"') => {
self.eat_char();
result
}
_ => Err(Error::InvalidType),
}
deserialize_unsigned!(self, visitor, u128, visit_u128)
}

fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value>
Expand Down Expand Up @@ -755,43 +719,49 @@ mod tests {

#[test]
fn integer128() {
assert_eq!(from_str::<i128>(r#"0"#), Err(crate::de::Error::InvalidType));
assert_eq!(from_str::<i128>(r#""0""#), Ok(0));
assert_eq!(from_str::<i128>(r#""1""#), Ok(1));
assert_eq!(from_str::<i128>(r#""-1""#), Ok(-1));
assert_eq!(
from_str::<i128>(r#""0""#),
Err(crate::de::Error::InvalidType)
);
assert_eq!(from_str::<i128>(r#"0"#), Ok(0));
assert_eq!(from_str::<i128>(r#"1"#), Ok(1));
assert_eq!(from_str::<i128>(r#"-1"#), Ok(-1));
// max i128
assert_eq!(
from_str::<i128>(r#""170141183460469231731687303715884105727""#),
from_str::<i128>(r#"170141183460469231731687303715884105727"#),
Ok(170141183460469231731687303715884105727)
);
assert_eq!(
from_str::<i128>(r#""170141183460469231731687303715884105728""#),
from_str::<i128>(r#"170141183460469231731687303715884105728"#),
Err(crate::de::Error::InvalidNumber)
);
// min i128
assert_eq!(
from_str::<i128>(r#""-170141183460469231731687303715884105728""#),
from_str::<i128>(r#"-170141183460469231731687303715884105728"#),
Ok(-170141183460469231731687303715884105728)
);
assert_eq!(
from_str::<i128>(r#""-170141183460469231731687303715884105729""#),
from_str::<i128>(r#"-170141183460469231731687303715884105729"#),
Err(crate::de::Error::InvalidNumber)
);

assert_eq!(from_str::<u128>(r#"0"#), Err(crate::de::Error::InvalidType));
assert_eq!(from_str::<u128>(r#""0""#), Ok(0));
assert_eq!(from_str::<u128>(r#""1""#), Ok(1));
assert_eq!(
from_str::<u128>(r#""-1""#),
from_str::<u128>(r#""0""#),
Err(crate::de::Error::InvalidType)
);
assert_eq!(from_str::<u128>(r#"0"#), Ok(0));
assert_eq!(from_str::<u128>(r#"1"#), Ok(1));
assert_eq!(
from_str::<u128>(r#"-1"#),
Err(crate::de::Error::InvalidNumber)
);
// max u128
assert_eq!(
from_str::<u128>(r#""340282366920938463463374607431768211455""#),
from_str::<u128>(r#"340282366920938463463374607431768211455"#),
Ok(340282366920938463463374607431768211455)
);
assert_eq!(
from_str::<u128>(r#""340282366920938463463374607431768211456""#),
from_str::<u128>(r#"340282366920938463463374607431768211456"#),
Err(crate::de::Error::InvalidNumber)
)
}
Expand Down
69 changes: 29 additions & 40 deletions src/ser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,7 @@ impl<'a> ser::Serializer for &'a mut Serializer {

fn serialize_i128(self, v: i128) -> Result<Self::Ok> {
// -170141183460469231731687303715884105728
self.buf.push(b'"');
let res: Result<Self::Ok> = serialize_signed!(self, 40, v, i128, u128);
res?;
self.buf.push(b'"');
Ok(())
serialize_signed!(self, 40, v, i128, u128)
}

fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
Expand All @@ -223,11 +219,7 @@ impl<'a> ser::Serializer for &'a mut Serializer {

fn serialize_u128(self, v: u128) -> Result<Self::Ok> {
// 340282366920938463463374607431768211455
self.buf.push(b'"');
let res: Result<Self::Ok> = serialize_unsigned!(self, 39, v);
res?;
self.buf.push(b'"');
Ok(())
serialize_unsigned!(self, 39, v)
}

fn serialize_f32(self, _v: f32) -> Result<Self::Ok> {
Expand Down Expand Up @@ -632,66 +624,64 @@ mod tests {
"-9223372036854775808"
);

assert_eq!(to_string::<u128>(&0).unwrap(), r#""0""#);
assert_eq!(to_string::<u128>(&1).unwrap(), r#""1""#);
assert_eq!(to_string::<u128>(&456789).unwrap(), r#""456789""#);
assert_eq!(to_string::<u128>(&4294967295).unwrap(), r#""4294967295""#);
assert_eq!(to_string::<u128>(&4294967296).unwrap(), r#""4294967296""#);
assert_eq!(to_string::<u128>(&0).unwrap(), r#"0"#);
assert_eq!(to_string::<u128>(&1).unwrap(), r#"1"#);
assert_eq!(to_string::<u128>(&456789).unwrap(), r#"456789"#);
assert_eq!(to_string::<u128>(&4294967295).unwrap(), r#"4294967295"#);
assert_eq!(to_string::<u128>(&4294967296).unwrap(), r#"4294967296"#);
assert_eq!(
to_string::<u128>(&9007199254740991).unwrap(),
r#""9007199254740991""#
r#"9007199254740991"#
); // Number.MAX_SAFE_INTEGER
assert_eq!(
to_string::<u128>(&9007199254740992).unwrap(),
r#""9007199254740992""#
r#"9007199254740992"#
); // Number.MAX_SAFE_INTEGER+1
assert_eq!(
to_string::<u128>(&9223372036854775807).unwrap(),
r#""9223372036854775807""#
r#"9223372036854775807"#
);
assert_eq!(
to_string::<u128>(&9223372036854775808).unwrap(),
r#""9223372036854775808""#
r#"9223372036854775808"#
);
assert_eq!(
to_string::<u128>(&u128::MAX).unwrap(),
r#""340282366920938463463374607431768211455""#
r#"340282366920938463463374607431768211455"#
);
// Currently failing, see https://github.com/CosmWasm/serde-json-wasm/issues/54
// assert_serde_json_serialize_eq!(&u128::MAX);

assert_eq!(to_string::<i128>(&0).unwrap(), r#""0""#);
assert_eq!(to_string::<i128>(&1).unwrap(), r#""1""#);
assert_eq!(to_string::<i128>(&456789).unwrap(), r#""456789""#);
assert_eq!(to_string::<i128>(&4294967295).unwrap(), r#""4294967295""#);
assert_eq!(to_string::<i128>(&4294967296).unwrap(), r#""4294967296""#);
assert_serde_json_serialize_eq!(&u128::MAX);

assert_eq!(to_string::<i128>(&0).unwrap(), r#"0"#);
assert_eq!(to_string::<i128>(&1).unwrap(), r#"1"#);
assert_eq!(to_string::<i128>(&456789).unwrap(), r#"456789"#);
assert_eq!(to_string::<i128>(&4294967295).unwrap(), r#"4294967295"#);
assert_eq!(to_string::<i128>(&4294967296).unwrap(), r#"4294967296"#);
assert_eq!(
to_string::<i128>(&9007199254740991).unwrap(),
r#""9007199254740991""#
r#"9007199254740991"#
); // Number.MAX_SAFE_INTEGER
assert_eq!(
to_string::<i128>(&9007199254740992).unwrap(),
r#""9007199254740992""#
r#"9007199254740992"#
); // Number.MAX_SAFE_INTEGER+1
assert_eq!(
to_string::<i128>(&9223372036854775807).unwrap(),
r#""9223372036854775807""#
r#"9223372036854775807"#
);
assert_eq!(
to_string::<i128>(&9223372036854775808).unwrap(),
r#""9223372036854775808""#
r#"9223372036854775808"#
);
assert_eq!(
to_string::<i128>(&i128::MAX).unwrap(),
r#""170141183460469231731687303715884105727""#
r#"170141183460469231731687303715884105727"#
);
assert_eq!(to_string::<i128>(&-1).unwrap(), r#""-1""#);
assert_eq!(to_string::<i128>(&-1).unwrap(), r#"-1"#);
assert_eq!(
to_string::<i128>(&i128::MIN).unwrap(),
r#""-170141183460469231731687303715884105728""#
r#"-170141183460469231731687303715884105728"#
);
// Currently failing, see https://github.com/CosmWasm/serde-json-wasm/issues/54
// assert_serde_json_serialize_eq!(&i128::MIN);
assert_serde_json_serialize_eq!(&i128::MIN);
}

#[test]
Expand Down Expand Up @@ -725,10 +715,9 @@ mod tests {

assert_eq!(
to_string(&pair).unwrap(),
r#"["340282366920938463463374607431768211455","340282366920938463463374607431768211455"]"#
r#"[340282366920938463463374607431768211455,340282366920938463463374607431768211455]"#
);
// Currently failing, see https://github.com/CosmWasm/serde-json-wasm/issues/54
// assert_serde_json_serialize_eq!(&pair);
assert_serde_json_serialize_eq!(&pair);
}

#[test]
Expand Down

0 comments on commit ccb8fbd

Please sign in to comment.