crypto_bigint/uint/
encoding.rs
1#[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::BYTE_SIZE * LIMBS,
17 "bytes are not the expected size"
18 );
19
20 let mut res = [Limb::ZERO; LIMBS];
21 let mut buf = [0u8; Limb::BYTE_SIZE];
22 let mut i = 0;
23
24 while i < LIMBS {
25 let mut j = 0;
26 while j < Limb::BYTE_SIZE {
27 buf[j] = bytes[i * Limb::BYTE_SIZE + 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::BYTE_SIZE * 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::BYTE_SIZE];
48 let mut i = 0;
49
50 while i < LIMBS {
51 let mut j = 0;
52 while j < Limb::BYTE_SIZE {
53 let offset = (i * Limb::BYTE_SIZE + j) * 2;
54 buf[j] = decode_hex_byte([bytes[offset], bytes[offset + 1]]);
55 j += 1;
56 }
57 res[LIMBS - i - 1] = Limb(Word::from_be_bytes(buf));
58 i += 1;
59 }
60
61 UInt::new(res)
62 }
63
64 pub const fn from_le_slice(bytes: &[u8]) -> Self {
66 assert!(
67 bytes.len() == Limb::BYTE_SIZE * LIMBS,
68 "bytes are not the expected size"
69 );
70
71 let mut res = [Limb::ZERO; LIMBS];
72 let mut buf = [0u8; Limb::BYTE_SIZE];
73 let mut i = 0;
74
75 while i < LIMBS {
76 let mut j = 0;
77 while j < Limb::BYTE_SIZE {
78 buf[j] = bytes[i * Limb::BYTE_SIZE + j];
79 j += 1;
80 }
81 res[i] = Limb(Word::from_le_bytes(buf));
82 i += 1;
83 }
84
85 UInt::new(res)
86 }
87
88 pub const fn from_le_hex(hex: &str) -> Self {
90 let bytes = hex.as_bytes();
91
92 assert!(
93 bytes.len() == Limb::BYTE_SIZE * LIMBS * 2,
94 "bytes are not the expected size"
95 );
96
97 let mut res = [Limb::ZERO; LIMBS];
98 let mut buf = [0u8; Limb::BYTE_SIZE];
99 let mut i = 0;
100
101 while i < LIMBS {
102 let mut j = 0;
103 while j < Limb::BYTE_SIZE {
104 let offset = (i * Limb::BYTE_SIZE + j) * 2;
105 buf[j] = decode_hex_byte([bytes[offset], bytes[offset + 1]]);
106 j += 1;
107 }
108 res[i] = Limb(Word::from_le_bytes(buf));
109 i += 1;
110 }
111
112 UInt::new(res)
113 }
114
115 #[inline]
118 #[cfg_attr(docsrs, doc(cfg(feature = "generic-array")))]
119 pub(crate) fn write_be_bytes(&self, out: &mut [u8]) {
120 debug_assert_eq!(out.len(), Limb::BYTE_SIZE * LIMBS);
121
122 for (src, dst) in self
123 .limbs
124 .iter()
125 .rev()
126 .cloned()
127 .zip(out.chunks_exact_mut(Limb::BYTE_SIZE))
128 {
129 dst.copy_from_slice(&src.to_be_bytes());
130 }
131 }
132
133 #[inline]
136 #[cfg_attr(docsrs, doc(cfg(feature = "generic-array")))]
137 pub(crate) fn write_le_bytes(&self, out: &mut [u8]) {
138 debug_assert_eq!(out.len(), Limb::BYTE_SIZE * LIMBS);
139
140 for (src, dst) in self
141 .limbs
142 .iter()
143 .cloned()
144 .zip(out.chunks_exact_mut(Limb::BYTE_SIZE))
145 {
146 dst.copy_from_slice(&src.to_le_bytes());
147 }
148 }
149}
150
151const fn decode_hex_byte(bytes: [u8; 2]) -> u8 {
153 let mut i = 0;
154 let mut result = 0u8;
155
156 while i < 2 {
157 result <<= 4;
158 result |= match bytes[i] {
159 b @ b'0'..=b'9' => b - b'0',
160 b @ b'a'..=b'f' => 10 + b - b'a',
161 b @ b'A'..=b'F' => 10 + b - b'A',
162 b => {
163 assert!(
164 matches!(b, b'0'..=b'9' | b'a' ..= b'f' | b'A'..=b'F'),
165 "invalid hex byte"
166 );
167 0
168 }
169 };
170
171 i += 1;
172 }
173
174 result
175}
176
177#[cfg(test)]
178mod tests {
179 use crate::Limb;
180 use hex_literal::hex;
181
182 #[cfg(feature = "alloc")]
183 use {crate::U128, alloc::format};
184
185 #[cfg(target_pointer_width = "32")]
186 use crate::U64 as UIntEx;
187
188 #[cfg(target_pointer_width = "64")]
189 use crate::U128 as UIntEx;
190
191 #[test]
192 #[cfg(target_pointer_width = "32")]
193 fn from_be_slice() {
194 let bytes = hex!("0011223344556677");
195 let n = UIntEx::from_be_slice(&bytes);
196 assert_eq!(n.limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
197 }
198
199 #[test]
200 #[cfg(target_pointer_width = "64")]
201 fn from_be_slice() {
202 let bytes = hex!("00112233445566778899aabbccddeeff");
203 let n = UIntEx::from_be_slice(&bytes);
204 assert_eq!(
205 n.limbs(),
206 &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
207 );
208 }
209
210 #[test]
211 #[cfg(target_pointer_width = "32")]
212 fn from_le_slice() {
213 let bytes = hex!("7766554433221100");
214 let n = UIntEx::from_le_slice(&bytes);
215 assert_eq!(n.limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
216 }
217
218 #[test]
219 #[cfg(target_pointer_width = "64")]
220 fn from_le_slice() {
221 let bytes = hex!("ffeeddccbbaa99887766554433221100");
222 let n = UIntEx::from_le_slice(&bytes);
223 assert_eq!(
224 n.limbs(),
225 &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
226 );
227 }
228
229 #[test]
230 #[cfg(target_pointer_width = "32")]
231 fn from_be_hex() {
232 let n = UIntEx::from_be_hex("0011223344556677");
233 assert_eq!(n.limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
234 }
235
236 #[test]
237 #[cfg(target_pointer_width = "64")]
238 fn from_be_hex() {
239 let n = UIntEx::from_be_hex("00112233445566778899aabbccddeeff");
240 assert_eq!(
241 n.limbs(),
242 &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
243 );
244 }
245
246 #[test]
247 #[cfg(target_pointer_width = "32")]
248 fn from_le_hex() {
249 let n = UIntEx::from_le_hex("7766554433221100");
250 assert_eq!(n.limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
251 }
252
253 #[test]
254 #[cfg(target_pointer_width = "64")]
255 fn from_le_hex() {
256 let n = UIntEx::from_le_hex("ffeeddccbbaa99887766554433221100");
257 assert_eq!(
258 n.limbs(),
259 &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
260 );
261 }
262
263 #[cfg(feature = "alloc")]
264 #[test]
265 fn hex_upper() {
266 let hex = "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD";
267 let n = U128::from_be_hex(hex);
268 assert_eq!(hex, format!("{:X}", n));
269 }
270
271 #[cfg(feature = "alloc")]
272 #[test]
273 fn hex_lower() {
274 let hex = "aaaaaaaabbbbbbbbccccccccdddddddd";
275 let n = U128::from_be_hex(hex);
276 assert_eq!(hex, format!("{:x}", n));
277 }
278}