crypto_bigint/uint/
encoding.rs1#[cfg(all(feature = "der", feature = "generic-array"))]
4mod der;
5
6#[cfg(feature = "rlp")]
7mod rlp;
8
9use super::Uint;
10use crate::{Encoding, Limb, Word};
11
12impl<const LIMBS: usize> Uint<LIMBS> {
13 pub const fn from_be_slice(bytes: &[u8]) -> Self {
15 assert!(
16 bytes.len() == Limb::BYTES * LIMBS,
17 "bytes are not the expected size"
18 );
19
20 let mut res = [Limb::ZERO; LIMBS];
21 let mut buf = [0u8; Limb::BYTES];
22 let mut i = 0;
23
24 while i < LIMBS {
25 let mut j = 0;
26 while j < Limb::BYTES {
27 buf[j] = bytes[i * Limb::BYTES + j];
28 j += 1;
29 }
30 res[LIMBS - i - 1] = Limb(Word::from_be_bytes(buf));
31 i += 1;
32 }
33
34 Uint::new(res)
35 }
36
37 pub const fn from_be_hex(hex: &str) -> Self {
39 let bytes = hex.as_bytes();
40
41 assert!(
42 bytes.len() == Limb::BYTES * LIMBS * 2,
43 "hex string is not the expected size"
44 );
45
46 let mut res = [Limb::ZERO; LIMBS];
47 let mut buf = [0u8; Limb::BYTES];
48 let mut i = 0;
49 let mut err = 0;
50
51 while i < LIMBS {
52 let mut j = 0;
53 while j < Limb::BYTES {
54 let offset = (i * Limb::BYTES + j) * 2;
55 let (result, byte_err) = decode_hex_byte([bytes[offset], bytes[offset + 1]]);
56 err |= byte_err;
57 buf[j] = result;
58 j += 1;
59 }
60 res[LIMBS - i - 1] = Limb(Word::from_be_bytes(buf));
61 i += 1;
62 }
63
64 assert!(err == 0, "invalid hex byte");
65
66 Uint::new(res)
67 }
68
69 pub const fn from_le_slice(bytes: &[u8]) -> Self {
71 assert!(
72 bytes.len() == Limb::BYTES * LIMBS,
73 "bytes are not the expected size"
74 );
75
76 let mut res = [Limb::ZERO; LIMBS];
77 let mut buf = [0u8; Limb::BYTES];
78 let mut i = 0;
79
80 while i < LIMBS {
81 let mut j = 0;
82 while j < Limb::BYTES {
83 buf[j] = bytes[i * Limb::BYTES + j];
84 j += 1;
85 }
86 res[i] = Limb(Word::from_le_bytes(buf));
87 i += 1;
88 }
89
90 Uint::new(res)
91 }
92
93 pub const fn from_le_hex(hex: &str) -> Self {
95 let bytes = hex.as_bytes();
96
97 assert!(
98 bytes.len() == Limb::BYTES * LIMBS * 2,
99 "bytes are not the expected size"
100 );
101
102 let mut res = [Limb::ZERO; LIMBS];
103 let mut buf = [0u8; Limb::BYTES];
104 let mut i = 0;
105 let mut err = 0;
106
107 while i < LIMBS {
108 let mut j = 0;
109 while j < Limb::BYTES {
110 let offset = (i * Limb::BYTES + j) * 2;
111 let (result, byte_err) = decode_hex_byte([bytes[offset], bytes[offset + 1]]);
112 err |= byte_err;
113 buf[j] = result;
114 j += 1;
115 }
116 res[i] = Limb(Word::from_le_bytes(buf));
117 i += 1;
118 }
119
120 assert!(err == 0, "invalid hex byte");
121
122 Uint::new(res)
123 }
124
125 #[inline]
128 pub(crate) fn write_be_bytes(&self, out: &mut [u8]) {
129 debug_assert_eq!(out.len(), Limb::BYTES * LIMBS);
130
131 for (src, dst) in self
132 .limbs
133 .iter()
134 .rev()
135 .cloned()
136 .zip(out.chunks_exact_mut(Limb::BYTES))
137 {
138 dst.copy_from_slice(&src.to_be_bytes());
139 }
140 }
141
142 #[inline]
145 pub(crate) fn write_le_bytes(&self, out: &mut [u8]) {
146 debug_assert_eq!(out.len(), Limb::BYTES * LIMBS);
147
148 for (src, dst) in self
149 .limbs
150 .iter()
151 .cloned()
152 .zip(out.chunks_exact_mut(Limb::BYTES))
153 {
154 dst.copy_from_slice(&src.to_le_bytes());
155 }
156 }
157}
158
159#[inline(always)]
161const fn decode_nibble(src: u8) -> u16 {
162 let byte = src as i16;
163 let mut ret: i16 = -1;
164
165 ret += (((0x2fi16 - byte) & (byte - 0x3a)) >> 8) & (byte - 47);
168 ret += (((0x40i16 - byte) & (byte - 0x47)) >> 8) & (byte - 54);
171 ret += (((0x60i16 - byte) & (byte - 0x67)) >> 8) & (byte - 86);
174
175 ret as u16
176}
177
178#[inline(always)]
182const fn decode_hex_byte(bytes: [u8; 2]) -> (u8, u16) {
183 let hi = decode_nibble(bytes[0]);
184 let lo = decode_nibble(bytes[1]);
185 let byte = (hi << 4) | lo;
186 let err = byte >> 8;
187 let result = byte as u8;
188 (result, err)
189}
190
191#[cfg(test)]
192mod tests {
193 use crate::Limb;
194 use hex_literal::hex;
195
196 #[cfg(feature = "alloc")]
197 use {crate::U128, alloc::format};
198
199 #[cfg(target_pointer_width = "32")]
200 use crate::U64 as UintEx;
201
202 #[cfg(target_pointer_width = "64")]
203 use crate::U128 as UintEx;
204
205 #[test]
206 #[cfg(target_pointer_width = "32")]
207 fn from_be_slice() {
208 let bytes = hex!("0011223344556677");
209 let n = UintEx::from_be_slice(&bytes);
210 assert_eq!(n.as_limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
211 }
212
213 #[test]
214 #[cfg(target_pointer_width = "64")]
215 fn from_be_slice() {
216 let bytes = hex!("00112233445566778899aabbccddeeff");
217 let n = UintEx::from_be_slice(&bytes);
218 assert_eq!(
219 n.as_limbs(),
220 &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
221 );
222 }
223
224 #[test]
225 #[cfg(target_pointer_width = "32")]
226 fn from_le_slice() {
227 let bytes = hex!("7766554433221100");
228 let n = UintEx::from_le_slice(&bytes);
229 assert_eq!(n.as_limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
230 }
231
232 #[test]
233 #[cfg(target_pointer_width = "64")]
234 fn from_le_slice() {
235 let bytes = hex!("ffeeddccbbaa99887766554433221100");
236 let n = UintEx::from_le_slice(&bytes);
237 assert_eq!(
238 n.as_limbs(),
239 &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
240 );
241 }
242
243 #[test]
244 #[cfg(target_pointer_width = "32")]
245 fn from_be_hex() {
246 let n = UintEx::from_be_hex("0011223344556677");
247 assert_eq!(n.as_limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
248 }
249
250 #[test]
251 #[cfg(target_pointer_width = "64")]
252 fn from_be_hex() {
253 let n = UintEx::from_be_hex("00112233445566778899aabbccddeeff");
254 assert_eq!(
255 n.as_limbs(),
256 &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
257 );
258 }
259
260 #[test]
261 #[cfg(target_pointer_width = "32")]
262 fn from_le_hex() {
263 let n = UintEx::from_le_hex("7766554433221100");
264 assert_eq!(n.as_limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
265 }
266
267 #[test]
268 #[cfg(target_pointer_width = "64")]
269 fn from_le_hex() {
270 let n = UintEx::from_le_hex("ffeeddccbbaa99887766554433221100");
271 assert_eq!(
272 n.as_limbs(),
273 &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
274 );
275 }
276
277 #[cfg(feature = "alloc")]
278 #[test]
279 fn hex_upper() {
280 let hex = "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD";
281 let n = U128::from_be_hex(hex);
282 assert_eq!(hex, format!("{:X}", n));
283 }
284
285 #[cfg(feature = "alloc")]
286 #[test]
287 fn hex_lower() {
288 let hex = "aaaaaaaabbbbbbbbccccccccdddddddd";
289 let n = U128::from_be_hex(hex);
290 assert_eq!(hex, format!("{:x}", n));
291 }
292}