1use super::types::*;
2use core::num::TryFromIntError;
3
4#[cold]
5#[inline(always)]
6fn neg_overflow() -> TryFromIntError {
7 match u8::try_from(-1_i8) {
8 Err(err) => err,
9 Ok(_) => unsafe { core::hint::unreachable_unchecked() },
11 }
12}
13
14#[cold]
15#[inline(always)]
16fn pos_overflow() -> TryFromIntError {
17 match u8::try_from(256_u16) {
18 Err(err) => err,
19 Ok(_) => unsafe { core::hint::unreachable_unchecked() },
21 }
22}
23
24macro_rules! to_val {
26 (P $x:expr) => {
27 $x
28 };
29 (C $x:expr) => {
30 $x.get()
31 };
32}
33
34macro_rules! lossless {
35 (P $s:ident $sb:ident => P $d:ident $db:ident) => {};
37
38 ($sk:ident $s:ident $sb:ident => P $d:ident $db:ident) => {
39 impl From<$s> for $d {
40 #[inline(always)]
41 fn from(x: $s) -> Self {
42 to_val!($sk x) as $d
43 }
44 }
45 };
46
47 ($sk:ident $s:ident $sb:ident => C $d:ident $db:ident) => {
48 impl From<$s> for $d {
49 #[inline(always)]
50 fn from(x: $s) -> Self {
51 unsafe { <$d>::new_unchecked(to_val!($sk x) as $db) }
53 }
54 }
55 };
56}
57
58macro_rules! fallible {
59 (P $s:ident $sb:ident => P $d:ident $db:ident) => {};
60
61 ($sk:ident $s:ident $sb:ident => $dk:ident $d:ident $db:ident) => {
62 impl TryFrom<$s> for $d {
63 type Error = TryFromIntError;
64
65 #[inline]
66 fn try_from(x: $s) -> Result<Self, Self::Error> {
67 match <$db as TryFrom<$sb>>::try_from(to_val!($sk x)) {
70 Ok(v) => fallible!(@finish $dk $d v; $db),
71 Err(err) => Err(TryFromIntError::from(err)),
72 }
73 }
74 }
75 };
76 (@finish P $d:ident $v:ident; $db: ident) => { Ok($v) };
78
79 (@finish C $d:ident $v:ident; $db: ident) => {{
80 const MIN: $db = $d::MIN.get();
81 const MAX: $db = $d::MAX.get();
82
83 let value = $v;
88 if value < MIN {
89 Err(neg_overflow())
90 } else if value > MAX {
91 Err(pos_overflow())
92 } else {
93 Ok(unsafe { $d::new_unchecked(value) })
94 }
95 }};
96}
97
98macro_rules! conv_pair {
99 (
101 ($sk:ident $si:ident $su:ident as $sib:ident $sub:ident)
102 ($bk:ident $bi:ident $bu:ident as $bib:ident $bub:ident)
103 ) => {
104 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 }
112 fallible! { $bk $bi $bib => $sk $su $sub }
113 fallible! { $bk $bu $bub => $sk $si $sib }
114 fallible! { $bk $bu $bub => $sk $su $sub }
115 };
116}
117
118macro_rules! conversions {
119 () => {};
120 (
121 ($k:ident $i:ident $u:ident as $ib:ident $ub:ident)
122 $($rest:tt)*
123 ) => {
124 fallible! { $k $i $ib => $k $u $ub }
126 fallible! { $k $u $ub => $k $i $ib }
127
128 $(conv_pair! { ($k $i $u as $ib $ub) $rest })*
129
130 conversions! { $($rest)* }
131 };
132}
133
134conversions! {
136 (P i8 u8 as i8 u8)
137 (P i16 u16 as i16 u16)
138 (C i24 u24 as i32 u32)
139 (P i32 u32 as i32 u32)
140 (C i40 u40 as i64 u64)
141 (C i48 u48 as i64 u64)
142 (C i56 u56 as i64 u64)
143 (P i64 u64 as i64 u64)
144 (C i72 u72 as i128 u128)
145 (C i80 u80 as i128 u128)
146 (C i88 u88 as i128 u128)
147 (C i96 u96 as i128 u128)
148 (C i104 u104 as i128 u128)
149 (C i112 u112 as i128 u128)
150 (C i120 u120 as i128 u128)
151 (P i128 u128 as i128 u128)
152}