use super::types::*;
use core::num::TryFromIntError;
#[cold]
#[inline(always)]
fn neg_overflow() -> TryFromIntError {
match u8::try_from(-1_i8) {
Err(err) => err,
Ok(_) => unsafe { core::hint::unreachable_unchecked() },
}
}
#[cold]
#[inline(always)]
fn pos_overflow() -> TryFromIntError {
match u8::try_from(256_u16) {
Err(err) => err,
Ok(_) => unsafe { core::hint::unreachable_unchecked() },
}
}
macro_rules! to_val {
(P $x:expr) => {
$x
};
(C $x:expr) => {
$x.get()
};
}
macro_rules! lossless {
(P $s:ident $sb:ident => P $d:ident $db:ident) => {};
($sk:ident $s:ident $sb:ident => P $d:ident $db:ident) => {
impl From<$s> for $d {
#[inline(always)]
fn from(x: $s) -> Self {
to_val!($sk x) as $d
}
}
};
($sk:ident $s:ident $sb:ident => C $d:ident $db:ident) => {
impl From<$s> for $d {
#[inline(always)]
fn from(x: $s) -> Self {
unsafe { <$d>::new_unchecked(to_val!($sk x) as $db) }
}
}
};
}
macro_rules! fallible {
(P $s:ident $sb:ident => P $d:ident $db:ident) => {};
($sk:ident $s:ident $sb:ident => $dk:ident $d:ident $db:ident) => {
impl TryFrom<$s> for $d {
type Error = TryFromIntError;
#[inline]
fn try_from(x: $s) -> Result<Self, Self::Error> {
match <$db as TryFrom<$sb>>::try_from(to_val!($sk x)) {
Ok(v) => fallible!(@finish $dk $d v; $db),
Err(err) => Err(TryFromIntError::from(err)),
}
}
}
};
(@finish P $d:ident $v:ident; $db: ident) => { Ok($v) };
(@finish C $d:ident $v:ident; $db: ident) => {{
const MIN: $db = $d::MIN.get();
const MAX: $db = $d::MAX.get();
let value = $v;
if value < MIN {
Err(neg_overflow())
} else if value > MAX {
Err(pos_overflow())
} else {
Ok(unsafe { $d::new_unchecked(value) })
}
}};
}
macro_rules! conv_pair {
(
($sk:ident $si:ident $su:ident as $sib:ident $sub:ident)
($bk:ident $bi:ident $bu:ident as $bib:ident $bub:ident)
) => {
lossless! { $sk $si $sib => $bk $bi $bib } lossless! { $sk $su $sub => $bk $bu $bub } lossless! { $sk $su $sub => $bk $bi $bib } fallible! { $sk $si $sib => $bk $bu $bub }
fallible! { $bk $bi $bib => $sk $si $sib }
fallible! { $bk $bi $bib => $sk $su $sub }
fallible! { $bk $bu $bub => $sk $si $sib }
fallible! { $bk $bu $bub => $sk $su $sub }
};
}
macro_rules! conversions {
() => {};
(
($k:ident $i:ident $u:ident as $ib:ident $ub:ident)
$($rest:tt)*
) => {
fallible! { $k $i $ib => $k $u $ub }
fallible! { $k $u $ub => $k $i $ib }
$(conv_pair! { ($k $i $u as $ib $ub) $rest })*
conversions! { $($rest)* }
};
}
conversions! {
(P i8 u8 as i8 u8)
(P i16 u16 as i16 u16)
(C i24 u24 as i32 u32)
(P i32 u32 as i32 u32)
(C i40 u40 as i64 u64)
(C i48 u48 as i64 u64)
(C i56 u56 as i64 u64)
(P i64 u64 as i64 u64)
(C i72 u72 as i128 u128)
(C i80 u80 as i128 u128)
(C i88 u88 as i128 u128)
(C i96 u96 as i128 u128)
(C i104 u104 as i128 u128)
(C i112 u112 as i128 u128)
(C i120 u120 as i128 u128)
(P i128 u128 as i128 u128)
}