radix_common/math/bnum_integer/
convert.rs

1use super::*;
2use bnum::cast::CastFrom;
3
4macro_rules! impl_from_primitive {
5    ($t:ident, $wrapped:ty, ($($type:ident),*)) => {
6        paste! {
7            impl FromPrimitive for $t {
8                $(
9                    fn [< from_$type >](n: [<$type>]) -> Option<Self> {
10                        <$wrapped>::try_from(n)
11                            .map(|val| Self(val))
12                            .ok()
13                    }
14                )*
15            }
16        }
17    }
18}
19macro_rules! impl_to_primitive {
20    ($t:ident, $wrapped:ty, ($($type:ident),*)) => {
21        paste! {
22            impl ToPrimitive for $t {
23                $(
24                    fn [< to_$type >](&self) -> Option<[<$type>]> {
25                        [<$type>]::try_from(self.0).ok()
26                    }
27                )*
28            }
29        }
30    }
31}
32impl_from_primitive! { I192, BInt::<3>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
33impl_from_primitive! { I256, BInt::<4>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
34impl_from_primitive! { I320, BInt::<5>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
35impl_from_primitive! { I384, BInt::<6>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
36impl_from_primitive! { I448, BInt::<7>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
37impl_from_primitive! { I512, BInt::<8>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
38impl_from_primitive! { I768, BInt::<12>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
39impl_from_primitive! { U192, BUint::<3>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
40impl_from_primitive! { U256, BUint::<4>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
41impl_from_primitive! { U320, BUint::<5>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
42impl_from_primitive! { U384, BUint::<6>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
43impl_from_primitive! { U448, BUint::<7>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
44impl_from_primitive! { U512, BUint::<8>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
45impl_from_primitive! { U768, BUint::<12>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
46impl_to_primitive! { I192, BInt::<3>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
47impl_to_primitive! { I256, BInt::<4>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
48impl_to_primitive! { I320, BInt::<5>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
49impl_to_primitive! { I384, BInt::<6>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
50impl_to_primitive! { I448, BInt::<7>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
51impl_to_primitive! { I512, BInt::<8>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
52impl_to_primitive! { I768, BInt::<12>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
53impl_to_primitive! { U192, BUint::<3>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
54impl_to_primitive! { U256, BUint::<4>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
55impl_to_primitive! { U320, BUint::<5>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
56impl_to_primitive! { U384, BUint::<6>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
57impl_to_primitive! { U448, BUint::<7>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
58impl_to_primitive! { U512, BUint::<8>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
59impl_to_primitive! { U768, BUint::<12>, (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize) }
60
61macro_rules! impl_from_builtin {
62    ($t:ident, $wrapped:ty, ($($o:ident),*)) => {
63        paste! {
64            $(
65                impl From<$o> for $t {
66                    fn from(val: $o) -> Self {
67                        Self::[<from_$o>](val).unwrap()
68
69                    }
70                }
71            )*
72        }
73    };
74}
75
76macro_rules! impl_try_from_builtin {
77    ($t:ident, $wrapped:ty, ($($o:ident),*)) => {
78        paste! {
79            $(
80                impl TryFrom<$o> for $t {
81                    type Error = [<Parse $t Error>];
82
83                    fn try_from(val: $o) -> Result<Self, Self::Error> {
84                        match Self::[<from_$o>](val) {
85                            Some(val) => Ok(val),
86                            None => Err([<Parse $t Error>]::Overflow),
87                        }
88                    }
89                }
90            )*
91        }
92    };
93}
94
95macro_rules! impl_to_builtin {
96    ($t:ident, $wrapped:ty, ($($o:ident),*)) => {
97        paste! {
98            $(
99                impl TryFrom<$t> for $o {
100                    type Error = [<Parse $t Error>];
101
102                    fn try_from(val: $t) -> Result<Self, Self::Error> {
103                        $o::try_from(val.0)
104                            .map_err(|_| [<Parse $t Error>]::Overflow)
105                    }
106                }
107            )*
108        }
109    };
110}
111
112impl_from_builtin! { I192, BInt::<3>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
113impl_from_builtin! { I256, BInt::<4>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
114impl_from_builtin! { I320, BInt::<5>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
115impl_from_builtin! { I384, BInt::<6>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
116impl_from_builtin! { I448, BInt::<7>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
117impl_from_builtin! { I512, BInt::<8>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
118impl_from_builtin! { I768, BInt::<12>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
119impl_from_builtin! { U192, BUint::<3>, (u8, u16, u32, u64, u128, usize)}
120impl_from_builtin! { U256, BUint::<4>, (u8, u16, u32, u64, u128, usize)}
121impl_from_builtin! { U320, BUint::<5>, (u8, u16, u32, u64, u128, usize)}
122impl_from_builtin! { U384, BUint::<6>, (u8, u16, u32, u64, u128, usize)}
123impl_from_builtin! { U448, BUint::<7>, (u8, u16, u32, u64, u128, usize)}
124impl_from_builtin! { U512, BUint::<8>, (u8, u16, u32, u64, u128, usize)}
125impl_from_builtin! { U768, BUint::<12>, (u8, u16, u32, u64, u128, usize)}
126
127impl_try_from_builtin! { U192, BUint::<3>, (i8, i16, i32, i64, i128, isize)}
128impl_try_from_builtin! { U256, BUint::<4>, (i8, i16, i32, i64, i128, isize)}
129impl_try_from_builtin! { U320, BUint::<5>, (i8, i16, i32, i64, i128, isize)}
130impl_try_from_builtin! { U384, BUint::<6>, (i8, i16, i32, i64, i128, isize)}
131impl_try_from_builtin! { U448, BUint::<7>, (i8, i16, i32, i64, i128, isize)}
132impl_try_from_builtin! { U512, BUint::<8>, (i8, i16, i32, i64, i128, isize)}
133impl_try_from_builtin! { U768, BUint::<12>, (i8, i16, i32, i64, i128, isize)}
134
135impl_to_builtin! { I192, BInt::<3>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
136impl_to_builtin! { I256, BInt::<4>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
137impl_to_builtin! { I320, BInt::<5>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
138impl_to_builtin! { I384, BInt::<6>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
139impl_to_builtin! { I448, BInt::<7>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
140impl_to_builtin! { I512, BInt::<8>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
141impl_to_builtin! { I768, BInt::<12>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
142impl_to_builtin! { U192, BUint::<3>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
143impl_to_builtin! { U256, BUint::<4>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
144impl_to_builtin! { U320, BUint::<5>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
145impl_to_builtin! { U384, BUint::<6>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
146impl_to_builtin! { U448, BUint::<7>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
147impl_to_builtin! { U512, BUint::<8>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
148impl_to_builtin! { U768, BUint::<12>, (i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize)}
149
150macro_rules! impl_try_from_bigint {
151    ($($t:ident, $wrapped:ty),*) => {
152        paste! {
153            $(
154                impl TryFrom<BigInt> for $t {
155                    type Error = [<Parse $t Error>];
156
157                    fn try_from(val: BigInt) -> Result<Self, Self::Error> {
158                        let bytes = val.to_signed_bytes_le();
159                        match <$wrapped>::from_le_slice(&bytes) {
160                            Some(val) => Ok(Self(val)),
161                            None => Err([<Parse $t Error>]::Overflow),
162                        }
163                    }
164                }
165            )*
166        }
167    };
168}
169
170macro_rules! impl_to_bigint {
171    ($($t:ident, $wrapped:ty),*) => {
172        paste! {
173            $(
174                impl From<$t> for BigInt {
175                    fn from(val: $t) -> BigInt {
176                        // TODO: switch from str to bytes
177                        BigInt::from_str(&val.to_string()).unwrap()
178                    }
179                }
180            )*
181        }
182    };
183}
184impl_try_from_bigint! { I192, BInt::<3>  }
185impl_try_from_bigint! { I256, BInt::<4>  }
186impl_try_from_bigint! { I320, BInt::<5>  }
187impl_try_from_bigint! { I384, BInt::<6>  }
188impl_try_from_bigint! { I448, BInt::<7>  }
189impl_try_from_bigint! { I512, BInt::<8>  }
190impl_try_from_bigint! { I768, BInt::<12> }
191impl_try_from_bigint! { U192, BUint::<3> }
192impl_try_from_bigint! { U256, BUint::<4> }
193impl_try_from_bigint! { U320, BUint::<5> }
194impl_try_from_bigint! { U384, BUint::<6> }
195impl_try_from_bigint! { U448, BUint::<7> }
196impl_try_from_bigint! { U512, BUint::<8> }
197impl_try_from_bigint! { U768, BUint::<12> }
198impl_to_bigint! { I192, BInt::<3> }
199impl_to_bigint! { I256, BInt::<4> }
200impl_to_bigint! { I320, BInt::<5> }
201impl_to_bigint! { I384, BInt::<6> }
202impl_to_bigint! { I448, BInt::<7> }
203impl_to_bigint! { I512, BInt::<8> }
204impl_to_bigint! { I768, BInt::<12> }
205impl_to_bigint! { U192, BUint::<3> }
206impl_to_bigint! { U256, BUint::<4> }
207impl_to_bigint! { U320, BUint::<5> }
208impl_to_bigint! { U384, BUint::<6> }
209impl_to_bigint! { U448, BUint::<7> }
210impl_to_bigint! { U512, BUint::<8> }
211impl_to_bigint! { U768, BUint::<12> }
212
213macro_rules! impl_from_string {
214    ($($t:ident, $wrapped:ty),*) => {
215        $(
216            paste! {
217                impl FromStr for $t {
218                    type Err = [<Parse $t Error>];
219                    fn from_str(val: &str) -> Result<Self, Self::Err> {
220                        match <$wrapped>::from_str(val) {
221                            Ok(val) => Ok(Self(val)),
222                            Err(err) => Err(match err.kind() {
223                                core::num::IntErrorKind::Empty => [<Parse $t Error>]::Empty,
224                                core::num::IntErrorKind::InvalidDigit => [<Parse $t Error>]::InvalidDigit,
225                                core::num::IntErrorKind::PosOverflow => [<Parse $t Error>]::Overflow,
226                                core::num::IntErrorKind::NegOverflow => [<Parse $t Error>]::Overflow,
227                                core::num::IntErrorKind::Zero => unreachable!("Zero is only issued for non-zero type"),
228                                _ => [<Parse $t Error>]::InvalidDigit, // Enum is non-exhaustive, sensible fallback is InvalidDigit
229                            })
230                        }
231                    }
232                }
233            }
234        )*
235    };
236}
237
238impl_from_string! { I192, BInt::<3> }
239impl_from_string! { I256, BInt::<4> }
240impl_from_string! { I320, BInt::<5> }
241impl_from_string! { I384, BInt::<6> }
242impl_from_string! { I448, BInt::<7> }
243impl_from_string! { I512, BInt::<8> }
244impl_from_string! { I768, BInt::<12> }
245impl_from_string! { U192, BUint::<3> }
246impl_from_string! { U256, BUint::<4> }
247impl_from_string! { U320, BUint::<5> }
248impl_from_string! { U384, BUint::<6> }
249impl_from_string! { U448, BUint::<7> }
250impl_from_string! { U512, BUint::<8> }
251impl_from_string! { U768, BUint::<12> }
252
253macro_rules! impl_try_from_bnum {
254    ($t:ident, $wrapped:ty, ($($into:ident, $into_wrap:ty),*)) => {
255        $(
256            paste! {
257                impl TryFrom<$t> for $into {
258                    type Error = [<Parse $into Error>];
259
260                    fn try_from(val: $t) -> Result<Self, Self::Error> {
261                        let mut sign = Self::ONE;
262                        let mut other = val;
263
264                        if other < <$t>::ZERO {
265                            if Self::MIN == Self::ZERO {
266                                return Err(Self::Error::NegativeToUnsigned);
267                            } else {
268                                // This is basically abs() function (which is not available for
269                                // unsigned types).
270                                // Do not perform below for MIN value to avoid overflow
271                                if other != <$t>::MIN {
272                                    other = <$t>::ZERO - other;
273                                    sign = Self::ZERO - sign;
274                                }
275                            }
276                        }
277                        if (other.leading_zeros() as i32) <= <$t>::BITS as i32 - Self::BITS as i32 {
278                            return Err(Self::Error::Overflow);
279                        }
280                        Ok(
281                         Self(<$into_wrap>::cast_from(other.0)) * sign)
282                    }
283                }
284
285            }
286        )*
287    };
288}
289macro_rules! impl_from_bnum {
290    ($t:ident, $wrapped:ty, ($($into:ident, $into_wrap:ty),*)) => {
291        $(
292            paste! {
293                impl From<$t> for $into {
294                    fn from(val: $t) -> $into {
295                        let mut sign = <$into>::ONE;
296                        let mut other = val;
297
298                        if other < <$t>::ZERO {
299                            if <$into>::MIN == <$into>::ZERO {
300                                panic!("NegativeToUnsigned");
301                            } else {
302                                // This is basically abs() function (which is not available for
303                                // unsigned types).
304                                // Do not perform below for MIN value to avoid overflow
305                                if other != <$t>::MIN {
306                                    other = <$t>::ZERO - other;
307                                    sign = <$into>::ZERO - sign;
308                                }
309                            }
310                        }
311                        if (other.leading_zeros() as i32) <= <$t>::BITS as i32 - <$into>::BITS as i32 {
312                            panic!("Overflow");
313                        }
314                        Self(<$into_wrap>::cast_from(other.0)) * sign
315                    }
316                }
317
318            }
319        )*
320    };
321}
322
323impl_try_from_bnum! {
324    I192, BInt::<3>, (
325        U192, BUint::<3>,
326        U256, BUint::<4>,
327        U320, BUint::<5>,
328        U384, BUint::<6>,
329        U448, BUint::<7>,
330        U512, BUint::<8>,
331        U768, BUint::<12>
332    )
333}
334impl_from_bnum! {
335    I192, BInt::<3>, (
336        I256, BInt::<4>,
337        I320, BInt::<5>,
338        I384, BInt::<6>,
339        I448, BInt::<7>,
340        I512, BInt::<8>,
341        I768, BInt::<12>
342    )
343}
344
345impl_try_from_bnum! {
346    I256, BInt::<4>, (
347        I192, BInt::<3>,
348        U192, BUint::<3>,
349        U256, BUint::<4>,
350        U320, BUint::<5>,
351        U384, BUint::<6>,
352        U448, BUint::<7>,
353        U512, BUint::<8>,
354        U768, BUint::<12>
355    )
356}
357impl_from_bnum! {
358    I256, BInt::<4>, (
359        I320, BInt::<5>,
360        I384, BInt::<6>,
361        I448, BInt::<7>,
362        I512, BInt::<8>,
363        I768, BInt::<12>
364    )
365}
366
367impl_try_from_bnum! {
368    I320, BInt::<5>, (
369        I192, BInt::<3>,
370        I256, BInt::<4>,
371        U192, BUint::<3>,
372        U256, BUint::<4>,
373        U320, BUint::<5>,
374        U384, BUint::<6>,
375        U448, BUint::<7>,
376        U512, BUint::<8>,
377        U768, BUint::<12>
378    )
379}
380impl_from_bnum! {
381    I320, BInt::<5>, (
382        I384, BInt::<6>,
383        I448, BInt::<7>,
384        I512, BInt::<8>,
385        I768, BInt::<12>
386    )
387}
388
389impl_try_from_bnum! {
390    I384, BInt::<6>, (
391        I192, BInt::<3>,
392        I256, BInt::<4>,
393        I320, BInt::<5>,
394        U192, BUint::<3>,
395        U256, BUint::<4>,
396        U320, BUint::<5>,
397        U384, BUint::<6>,
398        U448, BUint::<7>,
399        U512, BUint::<8>,
400        U768, BUint::<12>
401    )
402}
403impl_from_bnum! {
404    I384, BInt::<6>, (
405        I448, BInt::<7>,
406        I512, BInt::<8>,
407        I768, BInt::<12>
408    )
409}
410
411impl_try_from_bnum! {
412    I448, BInt::<7>, (
413        I192, BInt::<3>,
414        I256, BInt::<4>,
415        I320, BInt::<5>,
416        I384, BInt::<6>,
417        U192, BUint::<3>,
418        U256, BUint::<4>,
419        U320, BUint::<5>,
420        U384, BUint::<6>,
421        U448, BUint::<7>,
422        U512, BUint::<8>,
423        U768, BUint::<12>
424    )
425}
426impl_from_bnum! {
427    I448, BInt::<7>, (
428        I512, BInt::<8>,
429        I768, BInt::<12>
430    )
431}
432
433impl_try_from_bnum! {
434    I512, BInt::<8>, (
435        I192, BInt::<3>,
436        I256, BInt::<4>,
437        I320, BInt::<5>,
438        I384, BInt::<6>,
439        I448, BInt::<7>,
440        U192, BUint::<3>,
441        U256, BUint::<4>,
442        U320, BUint::<5>,
443        U384, BUint::<6>,
444        U448, BUint::<7>,
445        U512, BUint::<8>,
446        U768, BUint::<12>
447    )
448}
449impl_from_bnum! {
450    I512, BInt::<8>, (
451        I768, BInt::<12>
452    )
453}
454
455impl_try_from_bnum! {
456    I768, BInt::<12>, (
457        I192, BInt::<3>,
458        I256, BInt::<4>,
459        I320, BInt::<5>,
460        I384, BInt::<6>,
461        I448, BInt::<7>,
462        I512, BInt::<8>,
463        U192, BUint::<3>,
464        U256, BUint::<4>,
465        U320, BUint::<5>,
466        U384, BUint::<6>,
467        U448, BUint::<7>,
468        U512, BUint::<8>,
469        U768, BUint::<12>
470    )
471}
472
473// must fit 0 - MAX
474impl_try_from_bnum! {
475    U192, BUint::<3>, (
476        I192, BInt::<3>
477    )
478}
479impl_from_bnum! {
480    U192, BUint::<3>, (
481        I256, BInt::<4>,
482        I320, BInt::<5>,
483        I384, BInt::<6>,
484        I448, BInt::<7>,
485        I512, BInt::<8>,
486        I768, BInt::<12>,
487        U256, BUint::<4>,
488        U320, BUint::<5>,
489        U384, BUint::<6>,
490        U448, BUint::<7>,
491        U512, BUint::<8>,
492        U768, BUint::<12>
493    )
494}
495
496impl_try_from_bnum! {
497    U256, BUint::<4>, (
498        I192, BInt::<3>,
499        U192, BUint::<3>,
500        I256, BInt::<4>
501    )
502}
503impl_from_bnum! {
504    U256, BUint::<4>, (
505        I320, BInt::<5>,
506        I384, BInt::<6>,
507        I448, BInt::<7>,
508        I512, BInt::<8>,
509        I768, BInt::<12>,
510        U320, BUint::<5>,
511        U384, BUint::<6>,
512        U448, BUint::<7>,
513        U512, BUint::<8>,
514        U768, BUint::<12>
515    )
516}
517
518impl_try_from_bnum! {
519    U320, BUint::<5>, (
520        I192, BInt::<3>,
521        I256, BInt::<4>,
522        I320, BInt::<5>,
523        U192, BUint::<3>,
524        U256, BUint::<4>
525    )
526}
527impl_from_bnum! {
528    U320, BUint::<5>, (
529        I384, BInt::<6>,
530        I448, BInt::<7>,
531        I512, BInt::<8>,
532        I768, BInt::<12>,
533        U384, BUint::<6>,
534        U448, BUint::<7>,
535        U512, BUint::<8>,
536        U768, BUint::<12>
537    )
538}
539
540impl_try_from_bnum! {
541    U384, BUint::<6>, (
542        I192, BInt::<3>,
543        I256, BInt::<4>,
544        I320, BInt::<5>,
545        I384, BInt::<6>,
546        U192, BUint::<3>,
547        U256, BUint::<4>,
548        U320, BUint::<5>
549    )
550}
551impl_from_bnum! {
552    U384, BUint::<6>, (
553        I448, BInt::<7>,
554        I512, BInt::<8>,
555        I768, BInt::<12>,
556        U448, BUint::<7>,
557        U512, BUint::<8>,
558        U768, BUint::<12>
559    )
560}
561
562impl_try_from_bnum! {
563    U448, BUint::<7>, (
564        I192, BInt::<3>,
565        I256, BInt::<4>,
566        I320, BInt::<5>,
567        I384, BInt::<6>,
568        I448, BInt::<7>,
569        U192, BUint::<3>,
570        U256, BUint::<4>,
571        U320, BUint::<5>,
572        U384, BUint::<6>
573    )
574}
575impl_from_bnum! {
576    U448, BUint::<7>, (
577        I512, BInt::<8>,
578        I768, BInt::<12>,
579        U512, BUint::<8>,
580        U768, BUint::<12>
581    )
582}
583
584impl_try_from_bnum! {
585    U512, BUint::<8>, (
586        I192, BInt::<3>,
587        I256, BInt::<4>,
588        I320, BInt::<5>,
589        I384, BInt::<6>,
590        I448, BInt::<7>,
591        I512, BInt::<8>,
592        U192, BUint::<3>,
593        U256, BUint::<4>,
594        U320, BUint::<5>,
595        U384, BUint::<6>,
596        U448, BUint::<7>
597    )
598}
599impl_from_bnum! {
600    U512, BUint::<8>, (
601        I768, BInt::<12>,
602        U768, BUint::<12>
603    )
604}
605
606impl_try_from_bnum! {
607    U768, BUint::<12>, (
608        I192, BInt::<3>,
609        I256, BInt::<4>,
610        I320, BInt::<5>,
611        I384, BInt::<6>,
612        I448, BInt::<7>,
613        I512, BInt::<8>,
614        I768, BInt::<12>,
615        U192, BUint::<3>,
616        U256, BUint::<4>,
617        U320, BUint::<5>,
618        U384, BUint::<6>,
619        U448, BUint::<7>,
620        U512, BUint::<8>
621    )
622}
623
624macro_rules! impl_from_bytes {
625    ($($t:ident, $wrapped:ty),*) => {
626        paste! {
627            $(
628                impl TryFrom<&[u8]> for $t {
629                    type Error = [<Parse $t Error>];
630                    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
631                        if bytes.len() > <$t>::BYTES as usize {
632                            Err([<Parse $t Error>]::InvalidLength)
633                        } else {
634                            Ok(Self(<$wrapped>::from_le_slice(&bytes).unwrap()))
635                        }
636                    }
637                }
638
639                impl TryFrom<Vec<u8>> for $t {
640                    type Error = [<Parse $t Error>];
641                    fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
642                        if bytes.len() > <$t>::BYTES as usize {
643                            Err([<Parse $t Error>]::InvalidLength)
644                        } else {
645                            Ok(Self(<$wrapped>::from_le_slice(&bytes).unwrap()))
646                        }
647                    }
648                }
649
650                impl $t {
651                    pub fn from_le_bytes(bytes: &[u8]) -> Self {
652                        Self::try_from(bytes).unwrap()
653                    }
654                }
655            )*
656        }
657    };
658}
659
660macro_rules! impl_to_bytes {
661    ($($t:ident, $wrapped:ty),*) => {
662        paste! {
663            $(
664                impl $t {
665                    pub fn to_le_bytes(&self) -> [u8; <$wrapped>::BYTES as usize] {
666                        let mut shift = 0;
667                        let mut bytes = [0_u8; <$wrapped>::BYTES as usize];
668
669                        let ffs = <$t>::from(0xffff_ffff_ffff_ffff_u64);
670                        for i in 0..<$wrapped>::BYTES/8 {
671                            let idx: usize = (i * 8) as usize;
672                            let mut masked  = self.0 >> shift;
673                            masked &= ffs.0;
674                            let u: u64 = u64::try_from(masked).unwrap();
675                            let _ = &bytes[idx..idx+8].copy_from_slice(&u.to_le_bytes());
676                            shift += 64;
677                        }
678                        bytes
679                    }
680                }
681            )*
682        }
683    };
684}
685
686impl_from_bytes! { I192, BInt::<3> }
687impl_from_bytes! { I256, BInt::<4> }
688impl_from_bytes! { I320, BInt::<5> }
689impl_from_bytes! { I384, BInt::<6> }
690impl_from_bytes! { I448, BInt::<7> }
691impl_from_bytes! { I512, BInt::<8> }
692impl_from_bytes! { I768, BInt::<12> }
693impl_from_bytes! { U192, BUint::<3> }
694impl_from_bytes! { U256, BUint::<4> }
695impl_from_bytes! { U320, BUint::<5> }
696impl_from_bytes! { U384, BUint::<6> }
697impl_from_bytes! { U448, BUint::<7> }
698impl_from_bytes! { U512, BUint::<8> }
699impl_from_bytes! { U768, BUint::<12> }
700impl_to_bytes! { I192, BInt::<3> }
701impl_to_bytes! { I256, BInt::<4> }
702impl_to_bytes! { I320, BInt::<5> }
703impl_to_bytes! { I384, BInt::<6> }
704impl_to_bytes! { I448, BInt::<7> }
705impl_to_bytes! { I512, BInt::<8> }
706impl_to_bytes! { I768, BInt::<12> }
707impl_to_bytes! { U192, BUint::<3> }
708impl_to_bytes! { U256, BUint::<4> }
709impl_to_bytes! { U320, BUint::<5> }
710impl_to_bytes! { U384, BUint::<6> }
711impl_to_bytes! { U448, BUint::<7> }
712impl_to_bytes! { U512, BUint::<8> }
713impl_to_bytes! { U768, BUint::<12> }
714
715macro_rules! from_and_to_u64_arr_signed {
716    ($($t:ident, $wrapped:ty),*) => {
717        $(
718            paste! {
719                impl $t {
720
721                    pub const fn from_digits(digits: [u64; <$t>::N]) -> Self {
722                        let u = BUint::<{$t::N}>::from_digits(digits);
723                        Self(<$wrapped>::from_bits(u))
724                    }
725
726                    pub const fn to_digits(&self) -> [u64; <$t>::N] {
727                        let u: BUint::<{$t::N}> = self.0.to_bits();
728                        *u.digits()
729                    }
730                }
731            }
732        )*
733    };
734}
735
736macro_rules! from_and_to_u64_arr_unsigned {
737    ($($t:ident, $wrapped:ty),*) => {
738        $(
739            paste! {
740                impl $t {
741
742                    pub const fn from_digits(digits: [u64; <$t>::N]) -> Self {
743                        Self(<$wrapped>::from_digits(digits))
744                    }
745
746                    pub const fn to_digits(&self) -> [u64; <$t>::N] {
747                        *self.0.digits()
748                    }
749                }
750            }
751        )*
752    };
753}
754
755from_and_to_u64_arr_signed! { I192, BInt::<3> }
756from_and_to_u64_arr_signed! { I256, BInt::<4> }
757from_and_to_u64_arr_signed! { I320, BInt::<5> }
758from_and_to_u64_arr_signed! { I384, BInt::<6> }
759from_and_to_u64_arr_signed! { I448, BInt::<7> }
760from_and_to_u64_arr_signed! { I512, BInt::<8> }
761from_and_to_u64_arr_signed! { I768, BInt::<12> }
762
763from_and_to_u64_arr_unsigned! { U192, BUint::<3> }
764from_and_to_u64_arr_unsigned! { U256, BUint::<4> }
765from_and_to_u64_arr_unsigned! { U320, BUint::<5> }
766from_and_to_u64_arr_unsigned! { U384, BUint::<6> }
767from_and_to_u64_arr_unsigned! { U448, BUint::<7> }
768from_and_to_u64_arr_unsigned! { U512, BUint::<8> }
769from_and_to_u64_arr_unsigned! { U768, BUint::<12> }