diff --git a/Cargo.toml b/Cargo.toml index e1c698f0..8b182594 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ keywords = ["yaml", "serde"] [dependencies] dtoa = "0.4" linked-hash-map = "0.5" -serde = "1.0" +serde = "1.0.60" yaml-rust = "0.4" [dev-dependencies] diff --git a/src/de.rs b/src/de.rs index 8d6b1fe2..e7ee6b00 100644 --- a/src/de.rs +++ b/src/de.rs @@ -565,9 +565,19 @@ where if let Ok(n) = v.parse() { return visitor.visit_u64(n); } + serde_if_integer128! { + if let Ok(n) = v.parse() { + return visitor.visit_u128(n); + } + } if let Ok(n) = v.parse() { return visitor.visit_i64(n); } + serde_if_integer128! { + if let Ok(n) = v.parse() { + return visitor.visit_i128(n); + } + } match v.trim_left_matches('+') { ".inf" | ".Inf" | ".INF" => return visitor.visit_f64(f64::INFINITY), _ => (), @@ -685,6 +695,15 @@ impl<'de, 'a, 'r> de::Deserializer<'de> for &'r mut Deserializer<'a> { self.deserialize_scalar(visitor) } + serde_if_integer128! { + fn deserialize_i128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + } + fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, @@ -713,6 +732,15 @@ impl<'de, 'a, 'r> de::Deserializer<'de> for &'r mut Deserializer<'a> { self.deserialize_scalar(visitor) } + serde_if_integer128! { + fn deserialize_u128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + } + fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, diff --git a/src/number.rs b/src/number.rs index 7081ab57..964ba688 100644 --- a/src/number.rs +++ b/src/number.rs @@ -436,8 +436,8 @@ impl<'de> Deserializer<'de> for Number { } forward_to_deserialize_any! { - bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes - byte_buf option unit unit_struct newtype_struct seq tuple + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } } @@ -458,8 +458,8 @@ impl<'de, 'a> Deserializer<'de> for &'a Number { } forward_to_deserialize_any! { - bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes - byte_buf option unit unit_struct newtype_struct seq tuple + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } } diff --git a/src/ser.rs b/src/ser.rs index 61f10ed5..370aa6b1 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -53,6 +53,17 @@ impl ser::Serializer for Serializer { Ok(Yaml::Integer(v)) } + serde_if_integer128! { + #[cfg_attr(feature = "cargo-clippy", allow(cast_possible_truncation))] + fn serialize_i128(self, v: i128) -> Result { + if v <= i64::max_value() as i128 && v >= i64::min_value() as i128 { + self.serialize_i64(v as i64) + } else { + Ok(Yaml::Real(v.to_string())) + } + } + } + fn serialize_u8(self, v: u8) -> Result { self.serialize_i64(v as i64) } @@ -73,6 +84,17 @@ impl ser::Serializer for Serializer { } } + serde_if_integer128! { + #[cfg_attr(feature = "cargo-clippy", allow(cast_possible_truncation))] + fn serialize_u128(self, v: u128) -> Result { + if v <= i64::max_value() as u128 { + self.serialize_i64(v as i64) + } else { + Ok(Yaml::Real(v.to_string())) + } + } + } + fn serialize_f32(self, v: f32) -> Result { self.serialize_f64(v as f64) } diff --git a/src/value/de.rs b/src/value/de.rs index 53613ee4..9fdee7e3 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -213,6 +213,15 @@ impl<'de> Deserializer<'de> for Value { self.deserialize_number(visitor) } + serde_if_integer128! { + fn deserialize_i128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + } + fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, @@ -241,6 +250,15 @@ impl<'de> Deserializer<'de> for Value { self.deserialize_number(visitor) } + serde_if_integer128! { + fn deserialize_u128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + } + fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, diff --git a/src/value/mod.rs b/src/value/mod.rs index deb5c351..020785df 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -311,7 +311,7 @@ impl Value { self.as_u64().is_some() } - /// If the `Value` is an integer, represent it as i64 if possible. Returns + /// If the `Value` is an integer, represent it as u64 if possible. Returns /// None otherwise. /// /// ```rust diff --git a/tests/test_de.rs b/tests/test_de.rs index 89b23d26..17482463 100644 --- a/tests/test_de.rs +++ b/tests/test_de.rs @@ -9,7 +9,9 @@ #[macro_use] extern crate serde_derive; +#[macro_use] extern crate serde; + extern crate serde_yaml; extern crate unindent; @@ -169,14 +171,39 @@ fn test_number_as_string() { let yaml = unindent( " --- - value: 123456789012345678901234567890", + # Cannot be represented as u128 + value: 340282366920938463463374607431768211457", ); let expected = Num { - value: "123456789012345678901234567890".to_owned(), + value: "340282366920938463463374607431768211457".to_owned(), }; test_de(&yaml, &expected); } +serde_if_integer128! { + #[test] + fn test_i128_big() { + let expected: i128 = ::std::i64::MIN as i128 - 1; + let yaml = unindent( + " + --- + -9223372036854775809", + ); + assert_eq!(expected, serde_yaml::from_str::(&yaml).unwrap()); + } + + #[test] + fn test_u128_big() { + let expected: u128 = ::std::u64::MAX as u128 + 1; + let yaml = unindent( + " + --- + 18446744073709551616", + ); + assert_eq!(expected, serde_yaml::from_str::(&yaml).unwrap()); + } +} + #[test] fn test_number_alias_as_string() { #[derive(Deserialize, PartialEq, Debug)] diff --git a/tests/test_serde.rs b/tests/test_serde.rs index b36beb36..81fee70e 100644 --- a/tests/test_serde.rs +++ b/tests/test_serde.rs @@ -14,7 +14,9 @@ #[macro_use] extern crate serde_derive; +#[macro_use] extern crate serde; + extern crate serde_yaml; extern crate unindent; @@ -91,6 +93,30 @@ fn test_int_max_i64() { test_serde(&thing, &yaml); } +serde_if_integer128! { + #[test] + fn test_i128_small() { + let thing: i128 = -256; + let yaml = unindent( + " + --- + -256", + ); + test_serde(&thing, &yaml); + } + + #[test] + fn test_u128_small() { + let thing: u128 = 256; + let yaml = unindent( + " + --- + 256", + ); + test_serde(&thing, &yaml); + } +} + #[test] fn test_float() { let thing = 25.6;