numeric_cast 0.3.0

Safely cast between numbers
Documentation
#[inline(always)]
#[must_use]
pub fn extending_cast<X, Y>(x: X) -> Y
where
    Y: ExtendingCastFrom<X>,
{
    Y::extending_cast_from(x)
}

pub trait ExtendingCast: Sized {
    #[inline(always)]
    #[must_use]
    fn extending_cast<T: ExtendingCastFrom<Self>>(self) -> T {
        T::extending_cast_from(self)
    }
}

macro_rules! impl_extending_cast {
($($t:ty,)*) => {
    $(
        impl ExtendingCast for $t {}
    )*
};
}

impl_extending_cast!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize,);

pub trait ExtendingCastFrom<T>: Sized {
    fn extending_cast_from(val: T) -> Self;
}

macro_rules! extending_cast {
    ($lhs: ty=>$rhs:ty) => {
        impl ExtendingCastFrom<$lhs> for $rhs {
            #[inline(always)]
            #[must_use]
            fn extending_cast_from(val: $lhs) -> $rhs {
                val as $rhs
            }
        }
    };
}

extending_cast!(u8  => u16  );
extending_cast!(u8  => u32  );
extending_cast!(u8  => u64  );
extending_cast!(u8  => u128 );
extending_cast!(u16 => u32  );
extending_cast!(u16 => u64  );
extending_cast!(u16 => u128 );
extending_cast!(u32 => u64  );
extending_cast!(u32 => u128 );
extending_cast!(u64 => u128 );

extending_cast!(i8  => i16  );
extending_cast!(i8  => i32  );
extending_cast!(i8  => i64  );
extending_cast!(i8  => i128 );
extending_cast!(i16 => i32  );
extending_cast!(i16 => i64  );
extending_cast!(i16 => i128 );
extending_cast!(i32 => i64  );
extending_cast!(i32 => i128 );
extending_cast!(i64 => i128 );

extending_cast!(u8    => usize);
extending_cast!(u16   => usize);
extending_cast!(usize => u64  );
extending_cast!(usize => u128 );

extending_cast!(i8    => isize);
extending_cast!(i16   => isize);
extending_cast!(isize => i64  );
extending_cast!(isize => i128 );

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn extending() {
        let x: i8 = -1;
        let y: i16 = extending_cast(x);
        assert_eq!(y, -1);

        let y: u32 = 255u8.extending_cast();
        assert_eq!(y, 255);

        let y = 255u8.extending_cast::<u32>();
        assert_eq!(y, 255);
    }
}