1macro_rules! from_uint {
2 ($BUint: ident, $Digit: ident; $($uint: tt),*) => {
3 $(
4 impl<const N: usize> From<$uint> for $BUint<N> {
5 #[inline]
6 fn from(int: $uint) -> Self {
7 const UINT_BITS: usize = $uint::BITS as usize;
8 let mut out = Self::ZERO;
9 let mut i = 0;
10 while i << crate::digit::$Digit::BIT_SHIFT < UINT_BITS {
11 let d = (int >> (i << crate::digit::$Digit::BIT_SHIFT)) as $Digit;
12 if d != 0 {
13 out.digits[i] = d;
14 }
15 i += 1;
16 }
17 out
18 }
19 }
20 )*
21 }
22}
23
24macro_rules! try_from_iint {
25 ($BUint: ident; $($int: tt -> $uint: tt),*) => {
26 $(
27 impl<const N: usize> TryFrom<$int> for $BUint<N> {
28 type Error = TryFromIntError;
29
30 #[inline]
31 fn try_from(int: $int) -> Result<Self, Self::Error> {
32 if int.is_negative() {
33 return Err(TryFromIntError(()));
34 }
35 let bits = int as $uint;
36 Ok(Self::from(bits))
37 }
38 }
39 )*
40 }
41}
42
43macro_rules! try_from_buint {
44 ($BUint: ident, $Digit: ident; $($int: ty), *) => {
45 $(
46 impl<const N: usize> TryFrom<$BUint<N>> for $int {
47 type Error = TryFromIntError;
48
49 #[inline]
50 fn try_from(u: $BUint<N>) -> Result<$int, Self::Error> {
51 let mut out = 0;
52 let mut i = 0;
53 if $Digit::BITS > <$int>::BITS {
54 let small = u.digits[i] as $int;
55 let trunc = small as $Digit;
56 if u.digits[i] != trunc {
57 return Err(TryFromIntError(()));
58 }
59 out = small;
60 i = 1;
61 } else {
62 loop {
63 let shift = i << crate::digit::$Digit::BIT_SHIFT;
64 if i >= N || shift >= <$int>::BITS as usize {
65 break;
66 }
67 out |= u.digits[i] as $int << shift;
68 i += 1;
69 }
70 }
71
72 #[allow(unused_comparisons)]
73 if out < 0 {
74 return Err(TryFromIntError(()));
75 }
76
77 while i < N {
78 if u.digits[i] != 0 {
79 return Err(TryFromIntError(()));
80 }
81 i += 1;
82 }
83
84 Ok(out)
85 }
86 }
87 )*
88 };
89}
90
91macro_rules! uint_try_from_uint {
92 ($Trait: ident; $To: ident; $($From: ident $(<$N: ident>)?), *) => {
93 $(
94 impl<$(const $N: usize,)? const M: usize> $Trait<$From $(<$N>)?> for $To<M> {
95 type Error = TryFromIntError;
96
97 fn try_from(from: $From $(<$N>)?) -> Result<Self, Self::Error> {
98 if $From $(::<$N>)?::BITS <= Self::BITS || $From $(::<$N>)?::BITS - from.leading_zeros() <= Self::BITS {
99 Ok(Self::cast_from(from))
100 } else {
101 Err(TryFromIntError(()))
102 }
103 }
104 }
105 )*
106 };
107}
108
109macro_rules! uint_try_from_int {
110 ($Trait: ident; $To: ident; $($From: ident $(<$N: ident>)?), *) => {
111 $(
112 impl<$(const $N: usize,)? const M: usize> $Trait<$From $(<$N>)?> for $To<M> {
113 type Error = TryFromIntError;
114
115 fn try_from(from: $From $(<$N>)?) -> Result<Self, Self::Error> {
116 if from.is_negative() {
117 Err(TryFromIntError(()))
118 } else {
119 if $From $(::<$N>)?::BITS.saturating_sub(1) <= Self::BITS || $From $(::<$N>)?::BITS - from.leading_zeros() <= Self::BITS {
120 Ok(Self::cast_from(from))
121 } else {
122 Err(TryFromIntError(()))
123 }
124 }
125 }
126 }
127 )*
128 };
129}
130
131macro_rules! int_try_from_uint {
132 ($Trait: ident; $To: ident; $($From: ident $(<$N: ident>)?), *) => {
133 $(
134 impl<$(const $N: usize,)? const M: usize> $Trait<$From $(<$N>)?> for $To<M> {
135 type Error = TryFromIntError;
136
137 fn try_from(from: $From $(<$N>)?) -> Result<Self, Self::Error> {
138 if $From $(::<$N>)?::BITS <= Self::BITS - 1 || $From $(::<$N>)?::BITS - from.leading_zeros() <= Self::BITS - 1 { Ok(Self::cast_from(from))
140 } else {
141 Err(TryFromIntError(()))
142 }
143 }
144 }
145 )*
146 };
147}
148
149macro_rules! int_try_from_int {
150 ($Trait: ident; $To: ident; $($From: ident $(<$N: ident>)?), *) => {
151 $(
152 impl<$(const $N: usize,)? const M: usize> $Trait<$From $(<$N>)?> for $To<M> {
153 type Error = TryFromIntError;
154
155 fn try_from(from: $From $(<$N>)?) -> Result<Self, Self::Error> {
156 if $From $(::<$N>)?::BITS <= Self::BITS {
157 return Ok(Self::cast_from(from));
158 }
159 if from.is_negative() {
160 if $From $(::<$N>)?::BITS - from.leading_ones() <= Self::BITS - 1 {
161 Ok(Self::cast_from(from))
162 } else {
163 Err(TryFromIntError(()))
164 }
165 } else {
166 if $From $(::<$N>)?::BITS - from.leading_zeros() <= Self::BITS - 1 {
167 Ok(Self::cast_from(from))
168 } else {
169 Err(TryFromIntError(()))
170 }
171 }
172 }
173 }
174 )*
175 };
176}
177
178use crate::BTryFrom;
179
180macro_rules! mixed_try_from {
181 ($BUint: ident, $BInt: ident) => {
182 uint_try_from_uint!(BTryFrom; $BUint; BUint<N>, BUintD32<N>, BUintD16<N>, BUintD8<N>);
183 uint_try_from_int!(BTryFrom; $BUint; BInt<N>, BIntD32<N>, BIntD16<N>, BIntD8<N>);
184 int_try_from_uint!(BTryFrom; $BInt; BUint<N>, BUintD32<N>, BUintD16<N>, BUintD8<N>);
185 int_try_from_int!(BTryFrom; $BInt; BInt<N>, BIntD32<N>, BIntD16<N>, BIntD8<N>);
186 };
187}
188
189use crate::cast::CastFrom;
190use crate::errors::TryFromIntError;
191
192macro_rules! convert {
193 ($BUint: ident, $BInt: ident, $Digit: ident) => {
194 impl<const N: usize> From<bool> for $BUint<N> {
195 #[inline]
196 fn from(small: bool) -> Self {
197 Self::cast_from(small)
198 }
199 }
200
201 impl<const N: usize> From<char> for $BUint<N> {
202 #[inline]
203 fn from(c: char) -> Self {
204 Self::cast_from(c)
205 }
206 }
207
208 from_uint!($BUint, $Digit; u8, u16, u32, u64, u128, usize);
209
210 try_from_iint!($BUint; i8 -> u8, i16 -> u16, i32 -> u32, isize -> usize, i64 -> u64, i128 -> u128);
211
212 try_from_buint!($BUint, $Digit; u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
213
214 mixed_try_from!($BUint, $BInt);
215
216 impl<const N: usize> From<[$Digit; N]> for $BUint<N> {
217 #[inline]
218 fn from(digits: [$Digit; N]) -> Self {
219 Self::from_digits(digits)
220 }
221 }
222
223 impl<const N: usize> From<$BUint<N>> for [$Digit; N] {
224 #[inline]
225 fn from(uint: $BUint<N>) -> Self {
226 uint.digits
227 }
228 }
229 };
230}
231
232#[cfg(test)]
233crate::test::all_digit_tests! {
234 use crate::test::{self, types::utest};
235 use crate::test::cast_types::*;
236 use super::BTryFrom;
237
238 test::test_btryfrom!(utest; TestUint1, TestUint2, TestUint3, TestUint4, TestUint5, TestUint6, TestUint7, TestUint8, TestUint9, TestUint10, TestInt1, TestInt2, TestInt3, TestInt4, TestInt5, TestInt6, TestInt7, TestInt8, TestInt9, TestInt10);
239
240 #[cfg(not(any(test_int_bits = "16", test_int_bits = "32")))] test::test_from! {
242 function: <utest as TryFrom>::try_from,
243 from_types: (u8, u16, u32, u64, bool, char, i8, i16, i32, i64, isize, usize) }
245
246 test::test_into! {
247 function: <utest as TryInto>::try_into,
248 into_types: (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize)
249 }
250}
251
252crate::macro_impl!(convert);