diff --git a/serde/src/de/from_primitive.rs b/serde/src/de/from_primitive.rs index 544f3f1b8..d3c91908b 100644 --- a/serde/src/de/from_primitive.rs +++ b/serde/src/de/from_primitive.rs @@ -1,8 +1,22 @@ use lib::*; +#[cfg(integer128)] +type SignedInt = i128; + +#[cfg(not(integer128))] +type SignedInt = i64; + +#[cfg(integer128)] +type UnsignedInt = u128; + +#[cfg(not(integer128))] +type UnsignedInt = u64; + macro_rules! int_to_int { ($dst:ident, $n:ident) => { - if $dst::min_value() as i64 <= $n as i64 && $n as i64 <= $dst::max_value() as i64 { + if $dst::min_value() as SignedInt <= $n as SignedInt && + $n as SignedInt <= $dst::max_value() as SignedInt + { Some($n as $dst) } else { None @@ -12,7 +26,7 @@ macro_rules! int_to_int { macro_rules! int_to_uint { ($dst:ident, $n:ident) => { - if 0 <= $n && $n as u64 <= $dst::max_value() as u64 { + if 0 <= $n && $n as UnsignedInt <= $dst::max_value() as UnsignedInt { Some($n as $dst) } else { None @@ -22,7 +36,7 @@ macro_rules! int_to_uint { macro_rules! uint_to { ($dst:ident, $n:ident) => { - if $n as u64 <= $dst::max_value() as u64 { + if $n as UnsignedInt <= $dst::max_value() as UnsignedInt { Some($n as $dst) } else { None @@ -35,10 +49,14 @@ pub trait FromPrimitive: Sized { fn from_i16(n: i16) -> Option; fn from_i32(n: i32) -> Option; fn from_i64(n: i64) -> Option; + #[cfg(integer128)] + fn from_i128(n: i128) -> Option; fn from_u8(n: u8) -> Option; fn from_u16(n: u16) -> Option; fn from_u32(n: u32) -> Option; fn from_u64(n: u64) -> Option; + #[cfg(integer128)] + fn from_u128(n: u128) -> Option; } macro_rules! impl_from_primitive_for_int { @@ -60,6 +78,11 @@ macro_rules! impl_from_primitive_for_int { fn from_i64(n: i64) -> Option { int_to_int!($t, n) } + #[cfg(integer128)] + #[inline] + fn from_i128(n: i128) -> Option { + int_to_int!($t, n) + } #[inline] fn from_u8(n: u8) -> Option { uint_to!($t, n) @@ -76,6 +99,11 @@ macro_rules! impl_from_primitive_for_int { fn from_u64(n: u64) -> Option { uint_to!($t, n) } + #[cfg(integer128)] + #[inline] + fn from_u128(n: u128) -> Option { + uint_to!($t, n) + } } }; } @@ -99,6 +127,11 @@ macro_rules! impl_from_primitive_for_uint { fn from_i64(n: i64) -> Option { int_to_uint!($t, n) } + #[cfg(integer128)] + #[inline] + fn from_i128(n: i128) -> Option { + int_to_uint!($t, n) + } #[inline] fn from_u8(n: u8) -> Option { uint_to!($t, n) @@ -115,6 +148,11 @@ macro_rules! impl_from_primitive_for_uint { fn from_u64(n: u64) -> Option { uint_to!($t, n) } + #[cfg(integer128)] + #[inline] + fn from_u128(n: u128) -> Option { + uint_to!($t, n) + } } }; } @@ -138,6 +176,11 @@ macro_rules! impl_from_primitive_for_float { fn from_i64(n: i64) -> Option { Some(n as Self) } + #[cfg(integer128)] + #[inline] + fn from_i128(n: i128) -> Option { + Some(n as Self) + } #[inline] fn from_u8(n: u8) -> Option { Some(n as Self) @@ -154,6 +197,11 @@ macro_rules! impl_from_primitive_for_float { fn from_u64(n: u64) -> Option { Some(n as Self) } + #[cfg(integer128)] + #[inline] + fn from_u128(n: u128) -> Option { + Some(n as Self) + } } }; } @@ -172,89 +220,6 @@ impl_from_primitive_for_float!(f32); impl_from_primitive_for_float!(f64); serde_if_integer128! { - impl FromPrimitive for i128 { - #[inline] - fn from_i8(n: i8) -> Option { - Some(n as i128) - } - #[inline] - fn from_i16(n: i16) -> Option { - Some(n as i128) - } - #[inline] - fn from_i32(n: i32) -> Option { - Some(n as i128) - } - #[inline] - fn from_i64(n: i64) -> Option { - Some(n as i128) - } - #[inline] - fn from_u8(n: u8) -> Option { - Some(n as i128) - } - #[inline] - fn from_u16(n: u16) -> Option { - Some(n as i128) - } - #[inline] - fn from_u32(n: u32) -> Option { - Some(n as i128) - } - #[inline] - fn from_u64(n: u64) -> Option { - Some(n as i128) - } - } - - impl FromPrimitive for u128 { - #[inline] - fn from_i8(n: i8) -> Option { - if n >= 0 { - Some(n as u128) - } else { - None - } - } - #[inline] - fn from_i16(n: i16) -> Option { - if n >= 0 { - Some(n as u128) - } else { - None - } - } - #[inline] - fn from_i32(n: i32) -> Option { - if n >= 0 { - Some(n as u128) - } else { - None - } - } - #[inline] - fn from_i64(n: i64) -> Option { - if n >= 0 { - Some(n as u128) - } else { - None - } - } - #[inline] - fn from_u8(n: u8) -> Option { - Some(n as u128) - } - #[inline] - fn from_u16(n: u16) -> Option { - Some(n as u128) - } - #[inline] - fn from_u32(n: u32) -> Option { - Some(n as u128) - } - #[inline] - fn from_u64(n: u64) -> Option { - Some(n as u128) - } - } + impl_from_primitive_for_int!(i128); + impl_from_primitive_for_uint!(u128); } diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index efd194ccc..e0603cabf 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -82,7 +82,7 @@ impl<'de> Deserialize<'de> for bool { //////////////////////////////////////////////////////////////////////////////// macro_rules! visit_integer_method { - ($src_ty:ident, $method:ident, $from_method:ident, $group:ident, $group_ty:ident) => { + ($src_ty:ident, $method:ident, $from_method:ident, $group:ident $(, $err_msg:expr )*) => { #[inline] fn $method(self, v: $src_ty) -> Result where @@ -90,9 +90,17 @@ macro_rules! visit_integer_method { { match FromPrimitive::$from_method(v) { Some(v) => Ok(v), - None => Err(Error::invalid_value(Unexpected::$group(v as $group_ty), &self)), + None => visit_integer_method!(ERR self, $group, v $(, $err_msg)*), } } + }; + + (ERR $this:ident, $group:ident, $v: ident, $msg:expr) => { + Err(Error::invalid_value(Unexpected::$group($msg), &$this)) + }; + + (ERR $this:ident, $group:ident, $v:ident) => { + Err(Error::invalid_value(Unexpected::$group($v as _), &$this)) } } @@ -136,15 +144,20 @@ macro_rules! impl_deserialize_num { }; (integer $ty:ident) => { - visit_integer_method!(i8, visit_i8, from_i8, Signed, i64); - visit_integer_method!(i16, visit_i16, from_i16, Signed, i64); - visit_integer_method!(i32, visit_i32, from_i32, Signed, i64); - visit_integer_method!(i64, visit_i64, from_i64, Signed, i64); - - visit_integer_method!(u8, visit_u8, from_u8, Unsigned, u64); - visit_integer_method!(u16, visit_u16, from_u16, Unsigned, u64); - visit_integer_method!(u32, visit_u32, from_u32, Unsigned, u64); - visit_integer_method!(u64, visit_u64, from_u64, Unsigned, u64); + visit_integer_method!(i8, visit_i8, from_i8, Signed); + visit_integer_method!(i16, visit_i16, from_i16, Signed); + visit_integer_method!(i32, visit_i32, from_i32, Signed); + visit_integer_method!(i64, visit_i64, from_i64, Signed); + + visit_integer_method!(u8, visit_u8, from_u8, Unsigned); + visit_integer_method!(u16, visit_u16, from_u16, Unsigned); + visit_integer_method!(u32, visit_u32, from_u32, Unsigned); + visit_integer_method!(u64, visit_u64, from_u64, Unsigned); + + serde_if_integer128! { + visit_integer_method!(i128, visit_i128, from_i128, Other, "`i128`"); + visit_integer_method!(u128, visit_u128, from_u128, Other, "`u128`"); + } }; (float $ty:ident) => { @@ -169,89 +182,8 @@ impl_deserialize_num!(f32, deserialize_f32, integer, float); impl_deserialize_num!(f64, deserialize_f64, integer, float); serde_if_integer128! { - impl<'de> Deserialize<'de> for i128 { - #[inline] - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct PrimitiveVisitor; - - impl<'de> Visitor<'de> for PrimitiveVisitor { - type Value = i128; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("i128") - } - - impl_deserialize_num!(integer i128); - - #[inline] - fn visit_i128(self, v: i128) -> Result - where - E: Error, - { - Ok(v) - } - - #[inline] - fn visit_u128(self, v: u128) -> Result - where - E: Error, - { - if v <= i128::max_value() as u128 { - Ok(v as i128) - } else { - Err(Error::invalid_value(Unexpected::Other("u128"), &self)) - } - } - } - - deserializer.deserialize_i128(PrimitiveVisitor) - } - } - - impl<'de> Deserialize<'de> for u128 { - #[inline] - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct PrimitiveVisitor; - - impl<'de> Visitor<'de> for PrimitiveVisitor { - type Value = u128; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("u128") - } - - impl_deserialize_num!(integer u128); - - #[inline] - fn visit_i128(self, v: i128) -> Result - where - E: Error, - { - if v >= 0 { - Ok(v as u128) - } else { - Err(Error::invalid_value(Unexpected::Other("i128"), &self)) - } - } - - #[inline] - fn visit_u128(self, v: u128) -> Result - where - E: Error, - { - Ok(v) - } - } - - deserializer.deserialize_u128(PrimitiveVisitor) - } - } + impl_deserialize_num!(i128, deserialize_i128, integer); + impl_deserialize_num!(u128, deserialize_u128, integer); } //////////////////////////////////////////////////////////////////////////////// diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index ffa5012dc..bedca3d0f 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -239,11 +239,15 @@ mod content { U16(u16), U32(u32), U64(u64), + #[cfg(integer128)] + U128(u128), I8(i8), I16(i16), I32(i32), I64(i64), + #[cfg(integer128)] + I128(i128), F32(f32), F64(f64), @@ -282,10 +286,14 @@ mod content { Content::U16(n) => Unexpected::Unsigned(n as u64), Content::U32(n) => Unexpected::Unsigned(n as u64), Content::U64(n) => Unexpected::Unsigned(n), + #[cfg(integer128)] + Content::U128(_) => Unexpected::Other("unexpected `u128`"), Content::I8(n) => Unexpected::Signed(n as i64), Content::I16(n) => Unexpected::Signed(n as i64), Content::I32(n) => Unexpected::Signed(n as i64), Content::I64(n) => Unexpected::Signed(n), + #[cfg(integer128)] + Content::I128(_) => Unexpected::Other("unexpected `i128`"), Content::F32(f) => Unexpected::Float(f as f64), Content::F64(f) => Unexpected::Float(f), Content::Char(c) => Unexpected::Char(c), @@ -515,6 +523,22 @@ mod content { "untagged and internally tagged enums do not support enum input", )) } + + serde_if_integer128! { + fn visit_i128(self, value: i128) -> Result + where + F: de::Error, + { + Ok(Content::I128(value)) + } + + fn visit_u128(self, value: u128) -> Result + where + F: de::Error, + { + Ok(Content::U128(value)) + } + } } /// This is the type of the map keys in an internally tagged enum. @@ -807,6 +831,26 @@ mod content { .visit_enum(visitor) .map(TagOrContent::Content) } + + serde_if_integer128! { + fn visit_i128(self, value: i128) -> Result + where + F: de::Error, + { + ContentVisitor::new() + .visit_i128(value) + .map(TagOrContent::Content) + } + + fn visit_u128(self, value: u128) -> Result + where + F: de::Error, + { + ContentVisitor::new() + .visit_u128(value) + .map(TagOrContent::Content) + } + } } /// Used by generated code to deserialize an internally tagged enum. @@ -1029,10 +1073,14 @@ mod content { Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), Content::U64(v) => visitor.visit_u64(v), + #[cfg(integer128)] + Content::U128(v) => visitor.visit_u128(v), Content::I8(v) => visitor.visit_i8(v), Content::I16(v) => visitor.visit_i16(v), Content::I32(v) => visitor.visit_i32(v), Content::I64(v) => visitor.visit_i64(v), + #[cfg(integer128)] + Content::I128(v) => visitor.visit_i128(v), _ => Err(self.invalid_type(&visitor)), } } @@ -1085,10 +1133,14 @@ mod content { Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), Content::U64(v) => visitor.visit_u64(v), + #[cfg(integer128)] + Content::U128(v) => visitor.visit_u128(v), Content::I8(v) => visitor.visit_i8(v), Content::I16(v) => visitor.visit_i16(v), Content::I32(v) => visitor.visit_i32(v), Content::I64(v) => visitor.visit_i64(v), + #[cfg(integer128)] + Content::I128(v) => visitor.visit_i128(v), Content::F32(v) => visitor.visit_f32(v), Content::F64(v) => visitor.visit_f64(v), Content::Char(v) => visitor.visit_char(v), @@ -1432,6 +1484,22 @@ mod content { drop(self); visitor.visit_unit() } + + serde_if_integer128! { + fn deserialize_u128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_integer(visitor) + } + + fn deserialize_i128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_integer(visitor) + } + } } impl<'de, E> ContentDeserializer<'de, E> { @@ -1740,10 +1808,14 @@ mod content { Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), Content::U64(v) => visitor.visit_u64(v), + #[cfg(integer128)] + Content::U128(v) => visitor.visit_u128(v), Content::I8(v) => visitor.visit_i8(v), Content::I16(v) => visitor.visit_i16(v), Content::I32(v) => visitor.visit_i32(v), Content::I64(v) => visitor.visit_i64(v), + #[cfg(integer128)] + Content::I128(v) => visitor.visit_i128(v), _ => Err(self.invalid_type(&visitor)), } } @@ -1802,10 +1874,14 @@ mod content { Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), Content::U64(v) => visitor.visit_u64(v), + #[cfg(integer128)] + Content::U128(v) => visitor.visit_u128(v), Content::I8(v) => visitor.visit_i8(v), Content::I16(v) => visitor.visit_i16(v), Content::I32(v) => visitor.visit_i32(v), Content::I64(v) => visitor.visit_i64(v), + #[cfg(integer128)] + Content::I128(v) => visitor.visit_i128(v), Content::F32(v) => visitor.visit_f32(v), Content::F64(v) => visitor.visit_f64(v), Content::Char(v) => visitor.visit_char(v), @@ -2135,6 +2211,22 @@ mod content { { visitor.visit_unit() } + + serde_if_integer128! { + fn deserialize_u128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_integer(visitor) + } + + fn deserialize_i128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_integer(visitor) + } + } } impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> { @@ -2777,6 +2869,13 @@ where deserialize_identifier() deserialize_ignored_any() } + + serde_if_integer128! { + forward_to_deserialize_other! { + deserialize_i128() + deserialize_u128() + } + } } #[cfg(any(feature = "std", feature = "alloc"))]