Repository: nushell/nushell
File: crates/nu-protocol/src/value/from_value.rs (Rust)

Code before:
impl FromValue for NonZeroUsize {
    fn from_value(v: Value) -> Result<Self, ShellError> {
        let span = v.span();
        let v_ty = v.get_type();

        match v {
            Value::Int { val, .. } => {
                NonZeroUsize::new(val as usize).ok_or_else(|| ShellError::IncorrectValue {
                    msg: "use a value other than 0".into(),
                    val_span: span,
                    call_span: span,
                })
            }
            _ => Err(ShellError::CantConvert {
                to_type: Self::expected_type().to_string(),
                from_type: v_ty.to_string(),
                span,
                help: Some("expected a non-zero positive integer".into()),
            }),
        }
    }

    fn expected_type() -> Type {
        Type::Int
    }
}

macro_rules! impl_from_value_for_int {
    ($type:ty) => {
        impl FromValue for $type {
            fn from_value(v: Value) -> Result<Self, ShellError> {
                let span = v.span();
                let int = i64::from_value(v)?;
                const MIN: i64 = <$type>::MIN as i64;
                const MAX: i64 = <$type>::MAX as i64;
                #[allow(overlapping_range_endpoints)] // calculating MIN-1 is not possible for i64::MIN
                #[allow(unreachable_patterns)] // isize might max out i64 number range
                <$type>::try_from(int).map_err(|_| match int {
                    MIN..=MAX => unreachable!(
                        "int should be within the valid range for {}",
                        stringify!($type)
                    ),
                    i64::MIN..=MIN => int_too_small_error(int, <$type>::MIN, span),
                    MAX..=i64::MAX => int_too_large_error(int, <$type>::MAX, span),
                })
            }

            fn expected_type() -> Type {
                i64::expected_type()
            }
        }

Review comment (suggestion):
I think you can make it more useful if you implement `FromValue` for [`NonZero`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html) where `T: FromValue`. Then in the impl you can first use `T::from_value` and then put that into the `NonZero`.

Code after:
    }
}

//
// We can not use impl<T: FromValue> FromValue for NonZero<T> as NonZero requires an unstable trait
// As a result, we use this macro to implement FromValue for each NonZero type.
//

macro_rules! impl_from_value_for_nonzero {
    ($nonzero:ty, $base:ty) => {
        impl FromValue for $nonzero {
            fn from_value(v: Value) -> Result<Self, ShellError> {
                let span = v.span();
                let val = <$base>::from_value(v)?;
                <$nonzero>::new(val).ok_or_else(|| ShellError::IncorrectValue {
                    msg: "use a value other than 0".into(),
                    val_span: span,
                    call_span: span,
                })
            }

            fn expected_type() -> Type {
                Type::Int
            }
        }
    };
}

impl_from_value_for_nonzero!(NonZeroU16, u16);
impl_from_value_for_nonzero!(NonZeroU32, u32);
impl_from_value_for_nonzero!(NonZeroU64, u64);
impl_from_value_for_nonzero!(NonZeroUsize, usize);

impl_from_value_for_nonzero!(NonZeroI8, i8);
impl_from_value_for_nonzero!(NonZeroI16, i16);
impl_from_value_for_nonzero!(NonZeroI32, i32);
impl_from_value_for_nonzero!(NonZeroI64, i64);
impl_from_value_for_nonzero!(NonZeroIsize, isize);

macro_rules! impl_from_value_for_int {
    ($type:ty) => {
        impl FromValue for $type {
            fn from_value(v: Value) -> Result<Self, ShellError> {
                let span = v.span();
                let int = i64::from_value(v)?;
                const MIN: i64 = <$type>::MIN as i64;
                const MAX: i64 = <$type>::MAX as i64;
                #[allow(overlapping_range_endpoints)] // calculating MIN-1 is not possible for i64::MIN
                #[allow(unreachable_patterns)] // isize might max out i64 number range
                <$type>::try_from(int).map_err(|_| match int {
                    MIN..=MAX => unreachable!(