Coverage Report

Created: 2026-07-10 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}