reweb3_num/bint/
convert.rs

1macro_rules! from_int {
2    ($BInt: ident, $Digit: ident; $($int: tt),*) => {
3        $(impl_const! {
4            impl<const N: usize> const 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        $(impl_const! {
28            impl<const N: usize> const 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        $(crate::nightly::impl_const! {
42            impl<const N: usize> const 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        $(crate::nightly::impl_const! {
104            impl<const N: usize> const 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 crate::nightly::impl_const;
124use core::str::FromStr;
125
126macro_rules! convert {
127    ($BUint: ident, $BInt: ident, $Digit: ident) => {
128        impl<const N: usize> FromStr for $BInt<N> {
129            type Err = ParseIntError;
130
131            #[inline]
132            fn from_str(src: &str) -> Result<Self, Self::Err> {
133                Self::from_str_radix(src, 10)
134            }
135        }
136
137        from_int!($BInt, $Digit; i8, i16, i32, i64, i128, isize);
138
139        from_uint!($BInt, $BUint; u8, u16, u32, u64, u128, usize);
140
141        impl_const! {
142            impl<const N: usize> const From<bool> for $BInt<N> {
143                #[inline]
144                fn from(small: bool) -> Self {
145                    Self::cast_from(small)
146                }
147            }
148        }
149
150        int_try_from_bint!($BInt, $Digit; i8, i16, i32, i64, i128, isize);
151        uint_try_from_bint!($BInt; u8, u16, u32, u64, u128, usize);
152
153        // impl_const! {
154        //     impl<const N: usize> const TryFrom<$BUint<N>> for $BInt<N> {
155        //         type Error = TryFromIntError;
156
157        //         #[inline]
158        //         fn try_from(u: $BUint<N>) -> Result<Self, Self::Error> {
159        //             if u.leading_ones() != 0 {
160        //                 Err(TryFromIntError(()))
161        //             } else {
162        //                 Ok(Self::from_bits(u))
163        //             }
164        //         }
165        //     }
166        // }
167
168    };
169}
170
171crate::macro_impl!(convert);