/rust/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-bigint-0.5.5/src/uint/encoding.rs
Line | Count | Source |
1 | | //! Const-friendly decoding operations for [`Uint`] |
2 | | |
3 | | #[cfg(all(feature = "der", feature = "generic-array"))] |
4 | | mod der; |
5 | | |
6 | | #[cfg(feature = "rlp")] |
7 | | mod rlp; |
8 | | |
9 | | use super::Uint; |
10 | | use crate::{Encoding, Limb, Word}; |
11 | | |
12 | | impl<const LIMBS: usize> Uint<LIMBS> { |
13 | | /// Create a new [`Uint`] from the provided big endian bytes. |
14 | 63.4k | pub const fn from_be_slice(bytes: &[u8]) -> Self { |
15 | 63.4k | assert!( |
16 | 63.4k | bytes.len() == Limb::BYTES * LIMBS, |
17 | 0 | "bytes are not the expected size" |
18 | | ); |
19 | | |
20 | 63.4k | let mut res = [Limb::ZERO; LIMBS]; |
21 | 63.4k | let mut buf = [0u8; Limb::BYTES]; |
22 | 63.4k | let mut i = 0; |
23 | | |
24 | 317k | while i < LIMBS { |
25 | 253k | let mut j = 0; |
26 | 2.28M | while j < Limb::BYTES { |
27 | 2.02M | buf[j] = bytes[i * Limb::BYTES + j]; |
28 | 2.02M | j += 1; |
29 | 2.02M | } |
30 | 253k | res[LIMBS - i - 1] = Limb(Word::from_be_bytes(buf)); |
31 | 253k | i += 1; |
32 | | } |
33 | | |
34 | 63.4k | Uint::new(res) |
35 | 63.4k | } Unexecuted instantiation: <crypto_bigint::uint::Uint<16>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<24>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<1>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<28>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<32>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<2>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<48>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<56>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<3>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<64>>::from_be_slice <crypto_bigint::uint::Uint<4>>::from_be_slice Line | Count | Source | 14 | 63.4k | pub const fn from_be_slice(bytes: &[u8]) -> Self { | 15 | 63.4k | assert!( | 16 | 63.4k | bytes.len() == Limb::BYTES * LIMBS, | 17 | 0 | "bytes are not the expected size" | 18 | | ); | 19 | | | 20 | 63.4k | let mut res = [Limb::ZERO; LIMBS]; | 21 | 63.4k | let mut buf = [0u8; Limb::BYTES]; | 22 | 63.4k | let mut i = 0; | 23 | | | 24 | 317k | while i < LIMBS { | 25 | 253k | let mut j = 0; | 26 | 2.28M | while j < Limb::BYTES { | 27 | 2.02M | buf[j] = bytes[i * Limb::BYTES + j]; | 28 | 2.02M | j += 1; | 29 | 2.02M | } | 30 | 253k | res[LIMBS - i - 1] = Limb(Word::from_be_bytes(buf)); | 31 | 253k | i += 1; | 32 | | } | 33 | | | 34 | 63.4k | Uint::new(res) | 35 | 63.4k | } |
Unexecuted instantiation: <crypto_bigint::uint::Uint<96>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<6>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<7>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<128>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<8>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<9>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<12>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<13>>::from_be_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<14>>::from_be_slice |
36 | | |
37 | | /// Create a new [`Uint`] from the provided big endian hex string. |
38 | 0 | pub const fn from_be_hex(hex: &str) -> Self { |
39 | 0 | let bytes = hex.as_bytes(); |
40 | | |
41 | 0 | assert!( |
42 | 0 | bytes.len() == Limb::BYTES * LIMBS * 2, |
43 | 0 | "hex string is not the expected size" |
44 | | ); |
45 | | |
46 | 0 | let mut res = [Limb::ZERO; LIMBS]; |
47 | 0 | let mut buf = [0u8; Limb::BYTES]; |
48 | 0 | let mut i = 0; |
49 | 0 | let mut err = 0; |
50 | | |
51 | 0 | while i < LIMBS { |
52 | 0 | let mut j = 0; |
53 | 0 | while j < Limb::BYTES { |
54 | 0 | let offset = (i * Limb::BYTES + j) * 2; |
55 | 0 | let (result, byte_err) = decode_hex_byte([bytes[offset], bytes[offset + 1]]); |
56 | 0 | err |= byte_err; |
57 | 0 | buf[j] = result; |
58 | 0 | j += 1; |
59 | 0 | } |
60 | 0 | res[LIMBS - i - 1] = Limb(Word::from_be_bytes(buf)); |
61 | 0 | i += 1; |
62 | | } |
63 | | |
64 | 0 | assert!(err == 0, "invalid hex byte"); |
65 | | |
66 | 0 | Uint::new(res) |
67 | 0 | } Unexecuted instantiation: <crypto_bigint::uint::Uint<4>>::from_be_hex Unexecuted instantiation: <crypto_bigint::uint::Uint<_>>::from_be_hex |
68 | | |
69 | | /// Create a new [`Uint`] from the provided little endian bytes. |
70 | 0 | pub const fn from_le_slice(bytes: &[u8]) -> Self { |
71 | 0 | assert!( |
72 | 0 | bytes.len() == Limb::BYTES * LIMBS, |
73 | 0 | "bytes are not the expected size" |
74 | | ); |
75 | | |
76 | 0 | let mut res = [Limb::ZERO; LIMBS]; |
77 | 0 | let mut buf = [0u8; Limb::BYTES]; |
78 | 0 | let mut i = 0; |
79 | | |
80 | 0 | while i < LIMBS { |
81 | 0 | let mut j = 0; |
82 | 0 | while j < Limb::BYTES { |
83 | 0 | buf[j] = bytes[i * Limb::BYTES + j]; |
84 | 0 | j += 1; |
85 | 0 | } |
86 | 0 | res[i] = Limb(Word::from_le_bytes(buf)); |
87 | 0 | i += 1; |
88 | | } |
89 | | |
90 | 0 | Uint::new(res) |
91 | 0 | } Unexecuted instantiation: <crypto_bigint::uint::Uint<16>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<24>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<1>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<28>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<32>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<2>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<48>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<56>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<3>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<64>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<4>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<96>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<6>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<7>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<128>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<8>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<9>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<12>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<13>>::from_le_slice Unexecuted instantiation: <crypto_bigint::uint::Uint<14>>::from_le_slice |
92 | | |
93 | | /// Create a new [`Uint`] from the provided little endian hex string. |
94 | 0 | pub const fn from_le_hex(hex: &str) -> Self { |
95 | 0 | let bytes = hex.as_bytes(); |
96 | | |
97 | 0 | assert!( |
98 | 0 | bytes.len() == Limb::BYTES * LIMBS * 2, |
99 | 0 | "bytes are not the expected size" |
100 | | ); |
101 | | |
102 | 0 | let mut res = [Limb::ZERO; LIMBS]; |
103 | 0 | let mut buf = [0u8; Limb::BYTES]; |
104 | 0 | let mut i = 0; |
105 | 0 | let mut err = 0; |
106 | | |
107 | 0 | while i < LIMBS { |
108 | 0 | let mut j = 0; |
109 | 0 | while j < Limb::BYTES { |
110 | 0 | let offset = (i * Limb::BYTES + j) * 2; |
111 | 0 | let (result, byte_err) = decode_hex_byte([bytes[offset], bytes[offset + 1]]); |
112 | 0 | err |= byte_err; |
113 | 0 | buf[j] = result; |
114 | 0 | j += 1; |
115 | 0 | } |
116 | 0 | res[i] = Limb(Word::from_le_bytes(buf)); |
117 | 0 | i += 1; |
118 | | } |
119 | | |
120 | 0 | assert!(err == 0, "invalid hex byte"); |
121 | | |
122 | 0 | Uint::new(res) |
123 | 0 | } |
124 | | |
125 | | /// Serialize this [`Uint`] as big-endian, writing it into the provided |
126 | | /// byte slice. |
127 | | #[inline] |
128 | 48.2k | pub(crate) fn write_be_bytes(&self, out: &mut [u8]) { |
129 | 48.2k | debug_assert_eq!(out.len(), Limb::BYTES * LIMBS); |
130 | | |
131 | 192k | for (src, dst) in self |
132 | 48.2k | .limbs |
133 | 48.2k | .iter() |
134 | 48.2k | .rev() |
135 | 48.2k | .cloned() |
136 | 48.2k | .zip(out.chunks_exact_mut(Limb::BYTES)) |
137 | 192k | { |
138 | 192k | dst.copy_from_slice(&src.to_be_bytes()); |
139 | 192k | } |
140 | 48.2k | } <crypto_bigint::uint::Uint<4>>::write_be_bytes Line | Count | Source | 128 | 48.2k | pub(crate) fn write_be_bytes(&self, out: &mut [u8]) { | 129 | 48.2k | debug_assert_eq!(out.len(), Limb::BYTES * LIMBS); | 130 | | | 131 | 192k | for (src, dst) in self | 132 | 48.2k | .limbs | 133 | 48.2k | .iter() | 134 | 48.2k | .rev() | 135 | 48.2k | .cloned() | 136 | 48.2k | .zip(out.chunks_exact_mut(Limb::BYTES)) | 137 | 192k | { | 138 | 192k | dst.copy_from_slice(&src.to_be_bytes()); | 139 | 192k | } | 140 | 48.2k | } |
Unexecuted instantiation: <crypto_bigint::uint::Uint<_>>::write_be_bytes |
141 | | |
142 | | /// Serialize this [`Uint`] as little-endian, writing it into the provided |
143 | | /// byte slice. |
144 | | #[inline] |
145 | 9.65k | pub(crate) fn write_le_bytes(&self, out: &mut [u8]) { |
146 | 9.65k | debug_assert_eq!(out.len(), Limb::BYTES * LIMBS); |
147 | | |
148 | 38.6k | for (src, dst) in self |
149 | 9.65k | .limbs |
150 | 9.65k | .iter() |
151 | 9.65k | .cloned() |
152 | 9.65k | .zip(out.chunks_exact_mut(Limb::BYTES)) |
153 | 38.6k | { |
154 | 38.6k | dst.copy_from_slice(&src.to_le_bytes()); |
155 | 38.6k | } |
156 | 9.65k | } <crypto_bigint::uint::Uint<4>>::write_le_bytes Line | Count | Source | 145 | 9.65k | pub(crate) fn write_le_bytes(&self, out: &mut [u8]) { | 146 | 9.65k | debug_assert_eq!(out.len(), Limb::BYTES * LIMBS); | 147 | | | 148 | 38.6k | for (src, dst) in self | 149 | 9.65k | .limbs | 150 | 9.65k | .iter() | 151 | 9.65k | .cloned() | 152 | 9.65k | .zip(out.chunks_exact_mut(Limb::BYTES)) | 153 | 38.6k | { | 154 | 38.6k | dst.copy_from_slice(&src.to_le_bytes()); | 155 | 38.6k | } | 156 | 9.65k | } |
Unexecuted instantiation: <crypto_bigint::uint::Uint<_>>::write_le_bytes |
157 | | } |
158 | | |
159 | | /// Decode a single nibble of upper or lower hex |
160 | | #[inline(always)] |
161 | 0 | const fn decode_nibble(src: u8) -> u16 { |
162 | 0 | let byte = src as i16; |
163 | 0 | let mut ret: i16 = -1; |
164 | | |
165 | | // 0-9 0x30-0x39 |
166 | | // if (byte > 0x2f && byte < 0x3a) ret += byte - 0x30 + 1; // -47 |
167 | 0 | ret += (((0x2fi16 - byte) & (byte - 0x3a)) >> 8) & (byte - 47); |
168 | | // A-F 0x41-0x46 |
169 | | // if (byte > 0x40 && byte < 0x47) ret += byte - 0x41 + 10 + 1; // -54 |
170 | 0 | ret += (((0x40i16 - byte) & (byte - 0x47)) >> 8) & (byte - 54); |
171 | | // a-f 0x61-0x66 |
172 | | // if (byte > 0x60 && byte < 0x67) ret += byte - 0x61 + 10 + 1; // -86 |
173 | 0 | ret += (((0x60i16 - byte) & (byte - 0x67)) >> 8) & (byte - 86); |
174 | | |
175 | 0 | ret as u16 |
176 | 0 | } |
177 | | |
178 | | /// Decode a single byte encoded as two hexadecimal characters. |
179 | | /// Second element of the tuple is non-zero if the `bytes` values are not in the valid range |
180 | | /// (0-9, a-z, A-Z). |
181 | | #[inline(always)] |
182 | 0 | const fn decode_hex_byte(bytes: [u8; 2]) -> (u8, u16) { |
183 | 0 | let hi = decode_nibble(bytes[0]); |
184 | 0 | let lo = decode_nibble(bytes[1]); |
185 | 0 | let byte = (hi << 4) | lo; |
186 | 0 | let err = byte >> 8; |
187 | 0 | let result = byte as u8; |
188 | 0 | (result, err) |
189 | 0 | } |
190 | | |
191 | | #[cfg(test)] |
192 | | mod 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 | | } |