reweb3_num/bint/
endian.rs1use crate::digit;
2use crate::doc;
3macro_rules! endian {
6 ($BUint: ident, $BInt: ident, $Digit: ident) => {
7 macro_rules! set_digit {
8 ($out_digits: ident, $i: expr, $digit: expr, $is_negative: expr, $sign_bits: expr) => {
9 if $i == Self::N_MINUS_1 {
10 if ($digit as digit::$Digit::SignedDigit).is_negative() == $is_negative {
11 $out_digits[$i] = $digit;
12 } else {
13 return None;
14 }
15 } else if $i < N {
16 $out_digits[$i] = $digit;
17 } else if $digit != $sign_bits {
18 return None;
19 };
20 };
21 }
22
23 #[doc = doc::endian::impl_desc!($BInt)]
24 impl<const N: usize> $BInt<N> {
25 #[doc = doc::endian::from_be!(I 256)]
26 #[must_use = doc::must_use_op!()]
27 #[inline]
28 pub const fn from_be(x: Self) -> Self {
29 Self::from_bits($BUint::from_be(x.bits))
30 }
31
32 #[doc = doc::endian::from_le!(I 256)]
33 #[must_use = doc::must_use_op!()]
34 #[inline]
35 pub const fn from_le(x: Self) -> Self {
36 Self::from_bits($BUint::from_le(x.bits))
37 }
38
39 #[doc = doc::endian::to_be!(I 256)]
40 #[must_use = doc::must_use_op!()]
41 #[inline]
42 pub const fn to_be(self) -> Self {
43 Self::from_be(self)
44 }
45
46 #[doc = doc::endian::to_le!(I 256)]
47 #[must_use = doc::must_use_op!()]
48 #[inline]
49 pub const fn to_le(self) -> Self {
50 Self::from_le(self)
51 }
52
53 #[doc = concat!("[`from_be_slice`](crate::", stringify!($BUint), "::from_be_slice)")]
61 #[doc = concat!("[`", stringify!($BUint), "`](crate::", stringify!($BUint), ").")]
63 #[must_use = doc::must_use_op!()]
64 pub const fn from_be_slice(slice: &[u8]) -> Option<Self> {
65 let len = slice.len();
66 if len == 0 {
67 return Some(Self::ZERO);
68 }
69 let is_negative = (slice[0] as i8).is_negative();
70 let sign_bits = if is_negative {
71 $Digit::MAX
72 } else {
73 $Digit::MIN
74 };
75 let mut out_digits = if is_negative {
76 [$Digit::MAX; N]
77 } else {
78 [0; N]
79 };
80 let mut i = 0;
81 let exact = len >> digit::$Digit::BYTE_SHIFT;
82 while i < exact {
83 let mut digit_bytes = [0u8; digit::$Digit::BYTES as usize];
84 let init_index = len - digit::$Digit::BYTES as usize;
85 let mut j = init_index;
86 while j < slice.len() {
87 digit_bytes[j - init_index] = slice[j - (i << digit::$Digit::BYTE_SHIFT)];
88 j += 1;
89 }
90 let digit = $Digit::from_be_bytes(digit_bytes);
91 set_digit!(out_digits, i, digit, is_negative, sign_bits);
92 i += 1;
93 }
94 let rem = len & (digit::$Digit::BYTES as usize - 1);
95 if rem == 0 {
96 Some(Self::from_bits($BUint::from_digits(out_digits)))
97 } else {
98 let pad_byte = if is_negative { u8::MAX } else { 0 };
99 let mut last_digit_bytes = [pad_byte; digit::$Digit::BYTES as usize];
100 let mut j = 0;
101 while j < rem {
102 last_digit_bytes[digit::$Digit::BYTES as usize - rem + j] = slice[j];
103 j += 1;
104 }
105 let digit = $Digit::from_be_bytes(last_digit_bytes);
106 set_digit!(out_digits, i, digit, is_negative, sign_bits);
107 Some(Self::from_bits($BUint::from_digits(out_digits)))
108 }
109 }
110
111 #[doc = concat!("[`from_le_slice`](crate::", stringify!($BUint), "::from_le_slice)")]
119 #[doc = concat!("[`", stringify!($BUint), "`](crate::", stringify!($BUint), ").")]
121 #[must_use = doc::must_use_op!()]
122 pub const fn from_le_slice(slice: &[u8]) -> Option<Self> {
123 let len = slice.len();
124 if len == 0 {
125 return Some(Self::ZERO);
126 }
127 let is_negative = (slice[len - 1] as i8).is_negative();
128 let sign_bits = if is_negative {
129 $Digit::MAX
130 } else {
131 $Digit::MIN
132 };
133 let mut out_digits = [sign_bits; N];
134 let mut i = 0;
136 let exact = len >> digit::$Digit::BYTE_SHIFT;
137 while i < exact {
138 let mut digit_bytes = [0u8; digit::$Digit::BYTES as usize];
139 let init_index = i << digit::$Digit::BYTE_SHIFT;
140 let mut j = init_index;
141 while j < init_index + digit::$Digit::BYTES as usize {
142 digit_bytes[j - init_index] = slice[j];
143 j += 1;
144 }
145
146 let digit = $Digit::from_le_bytes(digit_bytes);
147 set_digit!(out_digits, i, digit, is_negative, sign_bits);
148 i += 1;
149 }
150 if len & (digit::$Digit::BYTES as usize - 1) == 0 {
151 Some(Self::from_bits($BUint::from_digits(out_digits)))
152 } else {
153 let pad_byte = if is_negative { u8::MAX } else { 0 };
154 let mut last_digit_bytes = [pad_byte; digit::$Digit::BYTES as usize];
155 let addition = exact << digit::$Digit::BYTE_SHIFT;
156 let mut j = 0;
157 while j + addition < len {
158 last_digit_bytes[j] = slice[j + addition];
159 j += 1;
160 }
161 let digit = $Digit::from_le_bytes(last_digit_bytes);
162 set_digit!(out_digits, i, digit, is_negative, sign_bits);
163 Some(Self::from_bits($BUint::from_digits(out_digits)))
164 }
165 }
166 }
167 };
168}
169
170crate::macro_impl!(endian);