From 48556a4c7f2a4343ce03367eb71bff42a33367f8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 24 Jan 2021 17:36:20 -0800 Subject: [PATCH] Reduce post-macro-expansion code in integer deserialize impls --- serde/src/de/from_primitive.rs | 260 -------------------------- serde/src/de/impls.rs | 329 +++++++++++++++++++-------------- serde/src/de/mod.rs | 1 - 3 files changed, 194 insertions(+), 396 deletions(-) delete mode 100644 serde/src/de/from_primitive.rs diff --git a/serde/src/de/from_primitive.rs b/serde/src/de/from_primitive.rs deleted file mode 100644 index 544f3f1b..00000000 --- a/serde/src/de/from_primitive.rs +++ /dev/null @@ -1,260 +0,0 @@ -use lib::*; - -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 { - Some($n as $dst) - } else { - None - } - }; -} - -macro_rules! int_to_uint { - ($dst:ident, $n:ident) => { - if 0 <= $n && $n as u64 <= $dst::max_value() as u64 { - Some($n as $dst) - } else { - None - } - }; -} - -macro_rules! uint_to { - ($dst:ident, $n:ident) => { - if $n as u64 <= $dst::max_value() as u64 { - Some($n as $dst) - } else { - None - } - }; -} - -pub trait FromPrimitive: Sized { - fn from_i8(n: i8) -> Option; - fn from_i16(n: i16) -> Option; - fn from_i32(n: i32) -> Option; - fn from_i64(n: i64) -> 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; -} - -macro_rules! impl_from_primitive_for_int { - ($t:ident) => { - impl FromPrimitive for $t { - #[inline] - fn from_i8(n: i8) -> Option { - int_to_int!($t, n) - } - #[inline] - fn from_i16(n: i16) -> Option { - int_to_int!($t, n) - } - #[inline] - fn from_i32(n: i32) -> Option { - int_to_int!($t, n) - } - #[inline] - fn from_i64(n: i64) -> Option { - int_to_int!($t, n) - } - #[inline] - fn from_u8(n: u8) -> Option { - uint_to!($t, n) - } - #[inline] - fn from_u16(n: u16) -> Option { - uint_to!($t, n) - } - #[inline] - fn from_u32(n: u32) -> Option { - uint_to!($t, n) - } - #[inline] - fn from_u64(n: u64) -> Option { - uint_to!($t, n) - } - } - }; -} - -macro_rules! impl_from_primitive_for_uint { - ($t:ident) => { - impl FromPrimitive for $t { - #[inline] - fn from_i8(n: i8) -> Option { - int_to_uint!($t, n) - } - #[inline] - fn from_i16(n: i16) -> Option { - int_to_uint!($t, n) - } - #[inline] - fn from_i32(n: i32) -> Option { - int_to_uint!($t, n) - } - #[inline] - fn from_i64(n: i64) -> Option { - int_to_uint!($t, n) - } - #[inline] - fn from_u8(n: u8) -> Option { - uint_to!($t, n) - } - #[inline] - fn from_u16(n: u16) -> Option { - uint_to!($t, n) - } - #[inline] - fn from_u32(n: u32) -> Option { - uint_to!($t, n) - } - #[inline] - fn from_u64(n: u64) -> Option { - uint_to!($t, n) - } - } - }; -} - -macro_rules! impl_from_primitive_for_float { - ($t:ident) => { - impl FromPrimitive for $t { - #[inline] - fn from_i8(n: i8) -> Option { - Some(n as Self) - } - #[inline] - fn from_i16(n: i16) -> Option { - Some(n as Self) - } - #[inline] - fn from_i32(n: i32) -> Option { - Some(n as Self) - } - #[inline] - fn from_i64(n: i64) -> Option { - Some(n as Self) - } - #[inline] - fn from_u8(n: u8) -> Option { - Some(n as Self) - } - #[inline] - fn from_u16(n: u16) -> Option { - Some(n as Self) - } - #[inline] - fn from_u32(n: u32) -> Option { - Some(n as Self) - } - #[inline] - fn from_u64(n: u64) -> Option { - Some(n as Self) - } - } - }; -} - -impl_from_primitive_for_int!(isize); -impl_from_primitive_for_int!(i8); -impl_from_primitive_for_int!(i16); -impl_from_primitive_for_int!(i32); -impl_from_primitive_for_int!(i64); -impl_from_primitive_for_uint!(usize); -impl_from_primitive_for_uint!(u8); -impl_from_primitive_for_uint!(u16); -impl_from_primitive_for_uint!(u32); -impl_from_primitive_for_uint!(u64); -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) - } - } -} diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 5f74ea77..352b6508 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -8,7 +8,6 @@ use de::{ use de::MapAccess; use __private::de::InPlaceSeed; -use de::from_primitive::FromPrimitive; #[cfg(any(feature = "std", feature = "alloc"))] use __private::de::size_hint; @@ -81,38 +80,8 @@ impl<'de> Deserialize<'de> for bool { //////////////////////////////////////////////////////////////////////////////// -macro_rules! visit_integer_method { - ($src_ty:ident, $method:ident, $from_method:ident, $group:ident, $group_ty:ident) => { - #[inline] - fn $method(self, v: $src_ty) -> Result - where - E: Error, - { - match FromPrimitive::$from_method(v) { - Some(v) => Ok(v), - None => Err(Error::invalid_value( - Unexpected::$group(v as $group_ty), - &self, - )), - } - } - }; -} - -macro_rules! visit_float_method { - ($src_ty:ident, $method:ident) => { - #[inline] - fn $method(self, v: $src_ty) -> Result - where - E: Error, - { - Ok(v as Self::Value) - } - }; -} - macro_rules! impl_deserialize_num { - ($ty:ident, $method:ident, $($visit:ident),*) => { + ($ty:ident, $deserialize:ident $($methods:tt)*) => { impl<'de> Deserialize<'de> for $ty { #[inline] fn deserialize(deserializer: D) -> Result @@ -128,131 +97,221 @@ macro_rules! impl_deserialize_num { formatter.write_str(stringify!($ty)) } - $( - impl_deserialize_num!($visit); - )* + $($methods)* } - deserializer.$method(PrimitiveVisitor) + deserializer.$deserialize(PrimitiveVisitor) } } }; - - (integer) => { - 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); - }; - - (float) => { - visit_float_method!(f32, visit_f32); - visit_float_method!(f64, visit_f64); - }; } -impl_deserialize_num!(i8, deserialize_i8, integer); -impl_deserialize_num!(i16, deserialize_i16, integer); -impl_deserialize_num!(i32, deserialize_i32, integer); -impl_deserialize_num!(i64, deserialize_i64, integer); -impl_deserialize_num!(isize, deserialize_i64, integer); - -impl_deserialize_num!(u8, deserialize_u8, integer); -impl_deserialize_num!(u16, deserialize_u16, integer); -impl_deserialize_num!(u32, deserialize_u32, integer); -impl_deserialize_num!(u64, deserialize_u64, integer); -impl_deserialize_num!(usize, deserialize_u64, integer); - -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 { +macro_rules! num_self { + ($ty:ident : $visit:ident) => { #[inline] - fn deserialize(deserializer: D) -> Result + fn $visit(self, v: $ty) -> Result where - D: Deserializer<'de>, + E: Error, { - struct PrimitiveVisitor; + Ok(v) + } + }; +} - impl<'de> Visitor<'de> for PrimitiveVisitor { - type Value = i128; +macro_rules! num_as_self { + ($($ty:ident : $visit:ident)*) => { + $( + #[inline] + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + Ok(v as Self::Value) + } + )* + }; +} - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("i128") - } - - impl_deserialize_num!(integer); - - #[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)) - } +macro_rules! int_to_int { + ($($ty:ident : $visit:ident)*) => { + $( + #[inline] + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if Self::Value::min_value() as i64 <= v as i64 && v as i64 <= Self::Value::max_value() as i64 { + Ok(v as Self::Value) + } else { + Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) } } + )* + }; +} - deserializer.deserialize_i128(PrimitiveVisitor) +macro_rules! int_to_uint { + ($($ty:ident : $visit:ident)*) => { + $( + #[inline] + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if 0 <= v && v as u64 <= Self::Value::max_value() as u64 { + Ok(v as Self::Value) + } else { + Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) + } + } + )* + }; +} + +macro_rules! uint_to_self { + ($($ty:ident : $visit:ident)*) => { + $( + #[inline] + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if v as u64 <= Self::Value::max_value() as u64 { + Ok(v as Self::Value) + } else { + Err(Error::invalid_value(Unexpected::Unsigned(v as u64), &self)) + } + } + )* + }; +} + +impl_deserialize_num! { + i8, deserialize_i8 + num_self!(i8:visit_i8); + int_to_int!(i16:visit_i16 i32:visit_i32 i64:visit_i64); + uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); +} + +impl_deserialize_num! { + i16, deserialize_i16 + num_self!(i16:visit_i16); + num_as_self!(i8:visit_i8); + int_to_int!(i32:visit_i32 i64:visit_i64); + uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); +} + +impl_deserialize_num! { + i32, deserialize_i32 + num_self!(i32:visit_i32); + num_as_self!(i8:visit_i8 i16:visit_i16); + int_to_int!(i64:visit_i64); + uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); +} + +impl_deserialize_num! { + i64, deserialize_i64 + num_self!(i64:visit_i64); + num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32); + uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); +} + +impl_deserialize_num! { + isize, deserialize_i64 + num_as_self!(i8:visit_i8 i16:visit_i16); + int_to_int!(i32:visit_i32 i64:visit_i64); + uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); +} + +impl_deserialize_num! { + u8, deserialize_u8 + num_self!(u8:visit_u8); + int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); + uint_to_self!(u16:visit_u16 u32:visit_u32 u64:visit_u64); +} + +impl_deserialize_num! { + u16, deserialize_u16 + num_self!(u16:visit_u16); + num_as_self!(u8:visit_u8); + int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); + uint_to_self!(u32:visit_u32 u64:visit_u64); +} + +impl_deserialize_num! { + u32, deserialize_u32 + num_self!(u32:visit_u32); + num_as_self!(u8:visit_u8 u16:visit_u16); + int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); + uint_to_self!(u64:visit_u64); +} + +impl_deserialize_num! { + u64, deserialize_u64 + num_self!(u64:visit_u64); + num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32); + int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); +} + +impl_deserialize_num! { + usize, deserialize_u64 + num_as_self!(u8:visit_u8 u16:visit_u16); + int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); + uint_to_self!(u32:visit_u32 u64:visit_u64); +} + +impl_deserialize_num! { + f32, deserialize_f32 + num_self!(f32:visit_f32); + num_as_self!(f64:visit_f64); + num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); + num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); +} + +impl_deserialize_num! { + f64, deserialize_f64 + num_self!(f64:visit_f64); + num_as_self!(f32:visit_f32); + num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); + num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); +} + +serde_if_integer128! { + impl_deserialize_num! { + i128, deserialize_i128 + num_self!(i128:visit_i128); + num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); + num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); + + #[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)) + } } } - impl<'de> Deserialize<'de> for u128 { + impl_deserialize_num! { + u128, deserialize_u128 + num_self!(u128:visit_u128); + num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); + int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); + #[inline] - fn deserialize(deserializer: D) -> Result + fn visit_i128(self, v: i128) -> Result where - D: Deserializer<'de>, + E: Error, { - 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); - - #[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) - } + if 0 <= v { + Ok(v as u128) + } else { + Err(Error::invalid_value(Unexpected::Other("i128"), &self)) } - - deserializer.deserialize_u128(PrimitiveVisitor) } } } diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 375d4b42..1ed7b4f6 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -118,7 +118,6 @@ use lib::*; pub mod value; -mod from_primitive; mod ignored_any; mod impls; mod utf8;