reweb3_num/buint/
convert.rs

1macro_rules! from_uint {
2    ($BUint: ident, $Digit: ident; $($uint: tt),*) => {
3        $(impl_const! {
4            impl<const N: usize> const 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        $(impl_const! {
27            impl<const N: usize> const 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        $(crate::nightly::impl_const! {
46            impl<const N: usize> const 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 { // Self::BITS - 1 as otherwise return value would be negative
139                        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>/*, u8, u16, u32, u64, u128, usize*/);
183        uint_try_from_int!(BTryFrom; $BUint; BInt<N>, BIntD32<N>, BIntD16<N>, BIntD8<N>/*, i8, i16, i32, i64, i128, isize*/);
184        int_try_from_uint!(BTryFrom; $BInt; BUint<N>, BUintD32<N>, BUintD16<N>, BUintD8<N>/*, u8, u16, u32, u64, u128, usize*/);
185        int_try_from_int!(BTryFrom; $BInt; BInt<N>, BIntD32<N>, BIntD16<N>, BIntD8<N>/*, i8, i16, i32, i64, i128, isize*/);
186    };
187}
188
189use crate::cast::CastFrom;
190use crate::errors::TryFromIntError;
191use crate::nightly::impl_const;
192
193macro_rules! convert {
194    ($BUint: ident, $BInt: ident, $Digit: ident) => {
195        impl_const! {
196            impl<const N: usize> const From<bool> for $BUint<N> {
197                #[inline]
198                fn from(small: bool) -> Self {
199                    Self::cast_from(small)
200                }
201            }
202        }
203
204        impl_const! {
205            impl<const N: usize> const From<char> for $BUint<N> {
206                #[inline]
207                fn from(c: char) -> Self {
208                    Self::cast_from(c)
209                }
210            }
211        }
212
213        from_uint!($BUint, $Digit; u8, u16, u32, u64, u128, usize);
214
215        try_from_iint!($BUint; i8 -> u8, i16 -> u16, i32 -> u32, isize -> usize, i64 -> u64, i128 -> u128);
216
217        try_from_buint!($BUint, $Digit; u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
218
219        mixed_try_from!($BUint, $BInt);
220
221        impl_const! {
222            impl<const N: usize> const From<[$Digit; N]> for $BUint<N> {
223                #[inline]
224                fn from(digits: [$Digit; N]) -> Self {
225                    Self::from_digits(digits)
226                }
227            }
228        }
229
230        impl_const! {
231            impl<const N: usize> const From<$BUint<N>> for [$Digit; N] {
232                #[inline]
233                fn from(uint: $BUint<N>) -> Self {
234                    uint.digits
235                }
236            }
237        }
238    };
239}
240
241crate::macro_impl!(convert);