Repository: serde-rs/serde
File: serde/src/de/impls.rs (Rust)

Code before:
    };
}

macro_rules! impl_deserialize_saturating_num {
    ($primitive:ident, $deserialize:ident ) => {
        #[cfg(not(no_core_num_saturating))]
        impl<'de> Deserialize<'de> for Saturating<$primitive> {
            #[inline]
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: Deserializer<'de>,
            {
                struct SaturatingVisitor;

                fn convert_saturating<T: core::convert::TryInto<$primitive> + Default + Ord + Copy>(
                    v: T,
                ) -> Saturating<$primitive> {
                    // We are taking advantage of T::Default being 0 for all numeric types
                    // (except for NonZero<T> which we ignore here)
                    Saturating(v.try_into().unwrap_or_else(|_| {
                        if v < T::default() {
                            $primitive::MIN
                        } else {
                            $primitive::MAX
                        }
                    }))
                }

                impl<'de> Visitor<'de> for SaturatingVisitor {
                    type Value = Saturating<$primitive>;

                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("An integer with support for saturating semantics")
                    }

                    visit_saturating!(u8:visit_u8);
                    visit_saturating!(u16:visit_u16);
                    visit_saturating!(u32:visit_u32);
                    visit_saturating!(u64:visit_u64);
                    visit_saturating!(i8:visit_i8);
                    visit_saturating!(i16:visit_i16);
                    visit_saturating!(i32:visit_i32);
                    visit_saturating!(i64:visit_i64);
                }

                deserializer.$deserialize(SaturatingVisitor)
            }
        }
    };
}


Review comment (suggestion):
you could inline this directly into `visit_saturating` by using `core::convert::TryFrom::<$ty>::try_from(v)`. That way you can also use `0`.

Code after:
    };
}

macro_rules! num_self {
    ($ty:ident : $visit:ident) => {
        #[inline]
        fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
        where
            E: Error,
        {
            Ok(v)
        }
    };

    (nonzero $primitive:ident $ty:ident : $visit:ident) => {
        fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
        where
            E: Error,
        {
            if let Some(nonzero) = Self::Value::new(v) {
                Ok(nonzero)
            } else {
                Err(Error::invalid_value(Unexpected::Unsigned(0), &self))
            }
        }
    };
}

macro_rules! num_as_self {
    ($ty:ident : $visit:ident) => {
        #[inline]
        fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
        where
            E: Error,
        {
            Ok(v as Self::Value)
        }
    };

    (nonzero $primitive:ident $ty:ident : $visit:ident) => {
        fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
        where
            E: Error,
        {
            if let Some(nonzero) = Self::Value::new(v as $primitive) {
                Ok(nonzero)
            } else {
                Err(Error::invalid_value(Unexpected::Unsigned(0), &self))
            }
        }
    };