1macro_rules! from_int {
2 ($BInt: ident, $Digit: ident; $($int: tt),*) => {
3 $(
4 impl<const N: usize> From<$int> for $BInt<N> {
5 #[inline]
6 fn from(int: $int) -> Self {
7 let mut out = if int.is_negative() {
8 !Self::ZERO
9 } else {
10 Self::ZERO
11 };
12 let mut i = 0;
13 while i << crate::digit::$Digit::BIT_SHIFT < $int::BITS as usize {
14 let d = (int >> (i << crate::digit::$Digit::BIT_SHIFT)) as $Digit;
15 out.bits.digits[i] = d;
16 i += 1;
17 }
18 out
19 }
20 }
21 )*
22 }
23}
24
25macro_rules! from_uint {
26 ($BInt: ident, $BUint: ident; $($from: tt), *) => {
27 $(
28 impl<const N: usize> From<$from> for $BInt<N> {
29 #[inline]
30 fn from(int: $from) -> Self {
31 let out = Self::from_bits($BUint::from(int));
32 out
33 }
34 }
35 )*
36 }
37}
38
39macro_rules! int_try_from_bint {
40 { $BInt: ident, $Digit: ident; $($int: ty), * } => {
41 $(
42 impl<const N: usize> TryFrom<$BInt<N>> for $int {
43 type Error = TryFromIntError;
44
45 fn try_from(int: $BInt<N>) -> Result<$int, Self::Error> {
46 let neg = int.is_negative();
47 let (mut out, padding) = if neg {
48 (-1, $Digit::MAX)
49 } else {
50 (0, $Digit::MIN)
51 };
52 let mut i = 0;
53 if $Digit::BITS > <$int>::BITS {
54 let small = int.bits.digits[i] as $int;
55 let trunc = small as $Digit;
56 if int.bits.digits[i] != trunc {
57 return Err(TryFromIntError(()));
58 }
59 out = small;
60 i = 1;
61 } else {
62 if neg {
63 loop {
64 let shift = i << digit::$Digit::BIT_SHIFT;
65 if i >= N || shift >= <$int>::BITS as usize {
66 break;
67 }
68 out &= !((!int.bits.digits[i]) as $int << shift);
69 i += 1;
70 }
71 } else {
72 loop {
73 let shift = i << digit::$Digit::BIT_SHIFT;
74 if i >= N || shift >= <$int>::BITS as usize {
75 break;
76 }
77 out |= int.bits.digits[i] as $int << shift;
78 i += 1;
79 }
80 }
81 }
82
83 while i < N {
84 if int.bits.digits[i] != padding {
85 return Err(TryFromIntError(()));
86 }
87 i += 1;
88 }
89
90 if out.is_negative() != neg {
91 return Err(TryFromIntError(()));
92 }
93
94 Ok(out)
95 }
96 }
97 )*
98 };
99}
100
101macro_rules! uint_try_from_bint {
102 ($BInt: ident; $($uint: ty), *) => {
103 $(
104 impl<const N: usize> TryFrom<$BInt<N>> for $uint {
105 type Error = TryFromIntError;
106
107 #[inline]
108 fn try_from(int: $BInt<N>) -> Result<$uint, Self::Error> {
109 if int.is_negative() {
110 Err(TryFromIntError(()))
111 } else {
112 <$uint>::try_from(int.bits)
113 }
114 }
115 }
116 )*
117 };
118}
119
120use crate::cast::CastFrom;
121use crate::digit;
122use crate::errors::{ParseIntError, TryFromIntError};
123use core::str::FromStr;
124
125macro_rules! convert {
126 ($BUint: ident, $BInt: ident, $Digit: ident) => {
127 impl<const N: usize> FromStr for $BInt<N> {
128 type Err = ParseIntError;
129
130 #[inline]
131 fn from_str(src: &str) -> Result<Self, Self::Err> {
132 Self::from_str_radix(src, 10)
133 }
134 }
135
136 from_int!($BInt, $Digit; i8, i16, i32, i64, i128, isize);
137
138 from_uint!($BInt, $BUint; u8, u16, u32, u64, u128, usize);
139
140 impl<const N: usize> From<bool> for $BInt<N> {
141 #[inline]
142 fn from(small: bool) -> Self {
143 Self::cast_from(small)
144 }
145 }
146
147 int_try_from_bint!($BInt, $Digit; i8, i16, i32, i64, i128, isize);
148 uint_try_from_bint!($BInt; u8, u16, u32, u64, u128, usize);
149
150 };
165}
166
167#[cfg(test)]
168crate::test::all_digit_tests! {
169 use crate::test;
170 use crate::test::types::itest;
171 use crate::test::cast_types::*;
172 use crate::BTryFrom;
173
174 test::test_btryfrom!(itest; TestUint1, TestUint2, TestUint3, TestUint4, TestUint5, TestUint6, TestUint7, TestUint8, TestUint9, TestUint10, TestInt1, TestInt2, TestInt3, TestInt4, TestInt5, TestInt6, TestInt7, TestInt8, TestInt9, TestInt10);
175
176 #[cfg(test_int_bits = "128")]
177 test::test_from! {
178 function: <itest as TryFrom>::try_from,
179 from_types: (i8, i16, i32, i64, i128, u8, u16, u32, u64, bool, usize, isize)
180 }
181
182 #[cfg(test_int_bits = "64")]
183 test::test_from! {
184 function: <itest as TryFrom>::try_from,
185 from_types: (i8, i16, i32, i64, u8, u16, u32, bool, isize)
186 }
187
188 test::test_into! {
189 function: <itest as TryInto>::try_into,
190 into_types: (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize)
191 }
192}
193
194crate::macro_impl!(convert);