1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use super::BUint;
use crate::digit::{self, Digit};
use crate::errors::{TryFromErrorReason::*, TryFromIntError};
use crate::nightly::impl_const;
use crate::cast::CastFrom;

impl_const! {
    impl<const N: usize> const From<bool> for BUint<N> {
        #[inline]
        fn from(small: bool) -> Self {
            Self::cast_from(small)
        }
    }
}

impl_const! {
    impl<const N: usize> const From<char> for BUint<N> {
        #[inline]
        fn from(c: char) -> Self {
            Self::cast_from(c)
        }
    }
}

macro_rules! from_uint {
    ($($uint: tt),*) => {
        $(impl_const! {
            impl<const N: usize> const From<$uint> for BUint<N> {
                #[inline]
                fn from(int: $uint) -> Self {
                    const UINT_BITS: usize = $uint::BITS as usize;
                    let mut out = Self::ZERO;
                    let mut i = 0;
                    while i << digit::BIT_SHIFT < UINT_BITS {
                        let d = (int >> (i << digit::BIT_SHIFT)) as Digit;
                        if d != 0 {
                            out.digits[i] = d;
                        }
                        i += 1;
                    }
                    out
                }
            }
		})*
    }
}

from_uint!(u8, u16, u32, usize, u64, u128);

macro_rules! try_from_iint {
    ($($int: tt -> $uint: tt),*) => {
        $(impl_const! {
			impl<const N: usize> const TryFrom<$int> for BUint<N> {
				type Error = TryFromIntError;

				#[inline]
				fn try_from(int: $int) -> Result<Self, Self::Error> {
					if int.is_negative() {
						return Err(TryFromIntError {
							from: stringify!($int),
							to: "BUint",
							reason: Negative,
						});
					}
					let bits = int as $uint;
					Ok(Self::from(bits))
				}
			}
		})*
    }
}

try_from_iint!(i8 -> u8, i16 -> u16, i32 -> u32, isize -> usize, i64 -> u64, i128 -> u128);

crate::int::convert::all_try_int_impls!(BUint);

impl_const! {
    impl<const N: usize> const From<[Digit; N]> for BUint<N> {
        #[inline]
        fn from(digits: [Digit; N]) -> Self {
            Self::from_digits(digits)
        }
    }
}

impl_const! {
    impl<const N: usize> const From<BUint<N>> for [Digit; N] {
        #[inline]
        fn from(uint: BUint<N>) -> Self {
            uint.digits
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::test;

    test::test_from! {
        function: <u128 as From>::from,
        from_types: (u8, u16, u32, u64, u128, bool, char)
    }

    test::test_from! {
        function: <u128 as TryFrom>::try_from,
        from_types: (i8, i16, i32, i64, i128, isize, usize)
    }

    test::test_into! {
        function: <u128 as TryInto>::try_into,
        into_types: (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize)
    }
}