//! `num_conv` is a crate to convert between integer types without using `as` casts. This provides //! better certainty when refactoring, makes the exact behavior of code more explicit, and allows //! using turbofish syntax.
#![no_std]
/// Anonymously import all extension traits. /// /// This allows you to use the methods without worrying about polluting the namespace or importing /// them individually. /// /// ```rust /// use num_conv::prelude::*; /// ``` pubmod prelude { pubusecrate::{CastSigned as _, CastUnsigned as _, Extend as _, Truncate as _};
}
/// Cast to a signed integer of the same size. /// /// This trait is implemented for all integers. Unsigned to signed casts are equivalent to /// `0.wrapping_add_signed(value)`, while signed to signed casts are an identity conversion. /// /// ```rust /// # use num_conv::CastSigned; /// assert_eq!(u8::MAX.cast_signed(), -1_i8); /// assert_eq!(u16::MAX.cast_signed(), -1_i16); /// assert_eq!(u32::MAX.cast_signed(), -1_i32); /// assert_eq!(u64::MAX.cast_signed(), -1_i64); /// assert_eq!(u128::MAX.cast_signed(), -1_i128); /// assert_eq!(usize::MAX.cast_signed(), -1_isize); /// ``` /// /// ```rust /// # use num_conv::CastSigned; /// assert_eq!(0_i8.cast_signed(), 0_i8); /// assert_eq!(0_i16.cast_signed(), 0_i16); /// assert_eq!(0_i32.cast_signed(), 0_i32); /// assert_eq!(0_i64.cast_signed(), 0_i64); /// assert_eq!(0_i128.cast_signed(), 0_i128); /// assert_eq!(0_isize.cast_signed(), 0_isize); /// ``` pubtrait CastSigned: sealed::Integer { /// The signed integer type with the same size as `Self`. type Signed;
/// Cast an integer to the signed integer of the same size. fn cast_signed(self) -> Self::Signed;
}
/// Cast to an unsigned integer of the same size. /// /// This trait is implemented for all integers. Signed to unsigned casts are equivalent to /// `0.wrapping_add_unsigned(value)`, while unsigned to unsigned casts are an identity conversion. /// /// ```rust /// # use num_conv::CastUnsigned; /// assert_eq!((-1_i8).cast_unsigned(), u8::MAX); /// assert_eq!((-1_i16).cast_unsigned(), u16::MAX); /// assert_eq!((-1_i32).cast_unsigned(), u32::MAX); /// assert_eq!((-1_i64).cast_unsigned(), u64::MAX); /// assert_eq!((-1_i128).cast_unsigned(), u128::MAX); /// assert_eq!((-1_isize).cast_unsigned(), usize::MAX); /// ``` /// /// ```rust /// # use num_conv::CastUnsigned; /// assert_eq!(0_u8.cast_unsigned(), 0_u8); /// assert_eq!(0_u16.cast_unsigned(), 0_u16); /// assert_eq!(0_u32.cast_unsigned(), 0_u32); /// assert_eq!(0_u64.cast_unsigned(), 0_u64); /// assert_eq!(0_u128.cast_unsigned(), 0_u128); /// assert_eq!(0_usize.cast_unsigned(), 0_usize); /// ``` pubtrait CastUnsigned: sealed::Integer { /// The unsigned integer type with the same size as `Self`. type Unsigned;
/// Cast an integer to the unsigned integer of the same size. fn cast_unsigned(self) -> Self::Unsigned;
}
/// A type that can be used with turbofish syntax in [`Extend::extend`]. /// /// It is unlikely that you will want to use this trait directly. You are probably looking for the /// [`Extend`] trait. pubtrait ExtendTarget<T>: sealed::ExtendTargetSealed<T> {}
/// A type that can be used with turbofish syntax in [`Truncate::truncate`]. /// /// It is unlikely that you will want to use this trait directly. You are probably looking for the /// [`Truncate`] trait. pubtrait TruncateTarget<T>: sealed::TruncateTargetSealed<T> {}
/// Extend to an integer of the same size or larger, preserving its value. /// /// ```rust /// # use num_conv::Extend; /// assert_eq!(0_u8.extend::<u16>(), 0_u16); /// assert_eq!(0_u16.extend::<u32>(), 0_u32); /// assert_eq!(0_u32.extend::<u64>(), 0_u64); /// assert_eq!(0_u64.extend::<u128>(), 0_u128); /// ``` /// /// ```rust /// # use num_conv::Extend; /// assert_eq!((-1_i8).extend::<i16>(), -1_i16); /// assert_eq!((-1_i16).extend::<i32>(), -1_i32); /// assert_eq!((-1_i32).extend::<i64>(), -1_i64); /// assert_eq!((-1_i64).extend::<i128>(), -1_i128); /// ``` pubtrait Extend: sealed::Integer { /// Extend an integer to an integer of the same size or larger, preserving its value. fn extend<T>(self) -> T where Self: ExtendTarget<T>;
}
impl<T: sealed::Integer> Extend for T { fn extend<U>(self) -> U where
T: ExtendTarget<U>,
{
sealed::ExtendTargetSealed::extend(self)
}
}
/// Truncate to an integer of the same size or smaller, preserving the least significant bits. /// /// ```rust /// # use num_conv::Truncate; /// assert_eq!(u16::MAX.truncate::<u8>(), u8::MAX); /// assert_eq!(u32::MAX.truncate::<u16>(), u16::MAX); /// assert_eq!(u64::MAX.truncate::<u32>(), u32::MAX); /// assert_eq!(u128::MAX.truncate::<u64>(), u64::MAX); /// ``` /// /// ```rust /// # use num_conv::Truncate; /// assert_eq!((-1_i16).truncate::<i8>(), -1_i8); /// assert_eq!((-1_i32).truncate::<i16>(), -1_i16); /// assert_eq!((-1_i64).truncate::<i32>(), -1_i32); /// assert_eq!((-1_i128).truncate::<i64>(), -1_i64); /// ``` pubtrait Truncate: sealed::Integer { /// Truncate an integer to an integer of the same size or smaller, preserving the least /// significant bits. fn truncate<T>(self) -> T where Self: TruncateTarget<T>;
}
impl<T: sealed::Integer> Truncate for T { fn truncate<U>(self) -> U where
T: TruncateTarget<U>,
{
sealed::TruncateTargetSealed::truncate(self)
}
}
macro_rules! impl_cast_signed {
($($($from:ty),+ => $to:ty;)*) => {$($( const _: () = assert!(
core::mem::size_of::<$from>() == core::mem::size_of::<$to>(),
concat!( "cannot cast ",
stringify!($from), " to ",
stringify!($to), " because they are different sizes"
)
);
impl CastSigned for $from { type Signed = $to; fn cast_signed(self) -> Self::Signed { selfas _
}
}
)+)*};
}
macro_rules! impl_cast_unsigned {
($($($from:ty),+ => $to:ty;)*) => {$($( const _: () = assert!(
core::mem::size_of::<$from>() == core::mem::size_of::<$to>(),
concat!( "cannot cast ",
stringify!($from), " to ",
stringify!($to), " because they are different sizes"
)
);
impl CastUnsigned for $from { type Unsigned = $to; fn cast_unsigned(self) -> Self::Unsigned { selfas _
}
}
)+)*};
}
macro_rules! impl_extend {
($($from:ty => $($to:ty),+;)*) => {$($( const _: () = assert!(
core::mem::size_of::<$from>() <= core::mem::size_of::<$to>(),
concat!( "cannot extend ",
stringify!($from), " to ",
stringify!($to), " because ",
stringify!($from), " is larger than ",
stringify!($to)
)
);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.