pub trait ToInteger {
fn to_exact_integer<T>(&self) -> Option<T>
where
T: FromFloat;
fn to_exact_usize(&self) -> Option<usize> {
self.to_exact_integer()
}
fn to_exact_u8(&self) -> Option<u8> {
self.to_exact_integer()
}
fn to_exact_u16(&self) -> Option<u16> {
self.to_exact_integer()
}
fn to_exact_u32(&self) -> Option<u32> {
self.to_exact_integer()
}
fn to_exact_u64(&self) -> Option<u64> {
self.to_exact_integer()
}
fn to_exact_u128(&self) -> Option<u128> {
self.to_exact_integer()
}
fn to_exact_isize(&self) -> Option<usize> {
self.to_exact_integer()
}
fn to_exact_i8(&self) -> Option<i8> {
self.to_exact_integer()
}
fn to_exact_i16(&self) -> Option<i16> {
self.to_exact_integer()
}
fn to_exact_i32(&self) -> Option<i32> {
self.to_exact_integer()
}
fn to_exact_i64(&self) -> Option<i64> {
self.to_exact_integer()
}
fn to_exact_i128(&self) -> Option<i128> {
self.to_exact_integer()
}
}
impl ToInteger for f64 {
fn to_exact_integer<T>(&self) -> Option<T>
where
T: FromFloat,
{
T::from_float(*self)
}
}
pub trait FromFloat {
fn from_float(x: f64) -> Option<Self>
where
Self: Sized;
}
macro_rules! impl_from_float {
($T:ident) => {
impl FromFloat for $T {
fn from_float(x: f64) -> Option<Self>
where
Self: Sized,
{
if x.trunc() == x && x >= $T::MIN as f64 && x <= $T::MAX as f64 {
Some(x as Self)
} else {
None
}
}
}
};
}
impl_from_float!(usize);
impl_from_float!(u8);
impl_from_float!(u16);
impl_from_float!(u32);
impl_from_float!(u64);
impl_from_float!(u128);
impl_from_float!(isize);
impl_from_float!(i8);
impl_from_float!(i16);
impl_from_float!(i32);
impl_from_float!(i64);
impl_from_float!(i128);