use num_traits::{AsPrimitive, NumCast, PrimInt, Signed};
use core::fmt::{Debug, Display};
pub trait Integer: Copy + Ord + PrimInt + Debug + Display + NumCast + Signed {}
impl Integer for i8 {}
impl Integer for i16 {}
impl Integer for i32 {}
impl Integer for i64 {}
impl Integer for i128 {}
pub(crate) trait FullInt:
Copy
+ PrimInt
+ IntConvert
+ AsPrimitive<i8>
+ AsPrimitive<i16>
+ AsPrimitive<i32>
+ AsPrimitive<i64>
+ AsPrimitive<i128>
+ AsPrimitive<isize>
+ AsPrimitive<u8>
+ AsPrimitive<u16>
+ AsPrimitive<u32>
+ AsPrimitive<u64>
+ AsPrimitive<u128>
+ AsPrimitive<usize>
+ 'static
{
}
pub(crate) trait IntConvert {
fn saturate<I: FullInt>(self) -> I;
fn sa<I: FullInt>(self) -> I
where
Self: AsPrimitive<I>,
i8: AsPrimitive<I>,
i16: AsPrimitive<I>,
i32: AsPrimitive<I>,
i64: AsPrimitive<I>,
i128: AsPrimitive<I>,
isize: AsPrimitive<I>,
u8: AsPrimitive<I>,
u16: AsPrimitive<I>,
u32: AsPrimitive<I>,
u64: AsPrimitive<I>,
u128: AsPrimitive<I>,
usize: AsPrimitive<I>;
}
macro_rules! impl_int_convert {
($($t:ty),*) => {
$(
impl IntConvert for $t {
#[inline]
fn saturate<I: FullInt>(self) -> I {
if let Some(val) = I::from(self) {
val
} else if self > 0 {
I::max_value()
} else {
I::min_value()
}
}
#[inline]
fn sa<I: FullInt>(self) -> I
where
$t: AsPrimitive<I>,
{
let src_bits = core::mem::size_of::<$t>().wrapping_mul(8);
let dst_bits = core::mem::size_of::<I>().wrapping_mul(8);
if src_bits < dst_bits {
(self.as_() << dst_bits.wrapping_sub(src_bits))
} else if src_bits > dst_bits {
(self >> src_bits.wrapping_sub(dst_bits)).as_()
} else {
self.as_()
}
}
}
)*
}
}
impl_int_convert!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);
impl FullInt for i8 {}
impl FullInt for i16 {}
impl FullInt for i32 {}
impl FullInt for i64 {}
impl FullInt for i128 {}
impl FullInt for isize {}
impl FullInt for u8 {}
impl FullInt for u16 {}
impl FullInt for u32 {}
impl FullInt for u64 {}
impl FullInt for u128 {}
impl FullInt for usize {}