crypto_bigint/uint/
array.rs

1//! `hybrid-array` integration with `Uint`.
2// TODO(tarcieri): completely phase out `hybrid-array` when const generics are powerful enough
3
4use crate::{ArrayDecoding, ArrayEncoding, ByteArray};
5use hybrid_array::{typenum, Array};
6
7macro_rules! impl_uint_array_encoding {
8    ($(($uint:ident, $bytes:path)),+) => {
9        $(
10            impl ArrayEncoding for super::$uint {
11                type ByteSize = $bytes;
12
13                #[inline]
14                fn from_be_byte_array(bytes: ByteArray<Self>) -> Self {
15                    Self::from_be_slice(&bytes)
16                }
17
18                #[inline]
19                fn from_le_byte_array(bytes: ByteArray<Self>) -> Self {
20                    Self::from_le_slice(&bytes)
21                }
22
23                #[inline]
24                fn to_be_byte_array(&self) -> ByteArray<Self> {
25                    let mut result = Array::default();
26                    self.write_be_bytes(&mut result);
27                    result
28                }
29
30                #[inline]
31                fn to_le_byte_array(&self) -> ByteArray<Self> {
32                    let mut result = Array::default();
33                    self.write_le_bytes(&mut result);
34                    result
35                }
36            }
37
38            impl ArrayDecoding for Array<u8, $bytes> {
39                type Output = super::$uint;
40
41                fn into_uint_be(self) -> Self::Output {
42                    Self::Output::from_be_byte_array(self)
43                }
44
45                fn into_uint_le(self) -> Self::Output {
46                    Self::Output::from_le_byte_array(self)
47                }
48            }
49        )+
50     };
51}
52
53// TODO(tarcieri): use `generic_const_exprs` when stable to make generic around bits.
54impl_uint_array_encoding! {
55    (U64, typenum::U8),
56    (U128, typenum::U16),
57    (U192, typenum::U24),
58    (U256, typenum::U32),
59    (U384, typenum::U48),
60    (U448, typenum::U56),
61    (U512, typenum::U64),
62    (U576, typenum::U72),
63    (U768, typenum::U96),
64    (U832, typenum::U104),
65    (U896, typenum::U112),
66    (U1024, typenum::U128),
67    (U1536, typenum::U192),
68    (U1792, typenum::U224),
69    (U2048, typenum::U256),
70    (U3072, typenum::U384),
71    (U3584, typenum::U448),
72    (U4096, typenum::U512),
73    (U6144, typenum::U768),
74    (U8192, typenum::U1024)
75}
76
77#[cfg(target_pointer_width = "32")]
78impl_uint_array_encoding! {
79    (U224, typenum::U28), // For NIST P-224
80    (U544, typenum::U68)  // For NIST P-521
81}
82
83#[cfg(test)]
84mod tests {
85    use crate::{ArrayDecoding, ArrayEncoding, Limb};
86    use hex_literal::hex;
87
88    #[cfg(target_pointer_width = "32")]
89    use crate::U64 as UintEx;
90
91    #[cfg(target_pointer_width = "64")]
92    use crate::U128 as UintEx;
93
94    /// Byte array that corresponds to `UintEx`
95    type ByteArray = crate::ByteArray<UintEx>;
96
97    #[test]
98    #[cfg(target_pointer_width = "32")]
99    fn from_be_byte_array() {
100        let n = UintEx::from_be_byte_array(hex!("0011223344556677").into());
101        assert_eq!(n.as_limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
102    }
103
104    #[test]
105    #[cfg(target_pointer_width = "64")]
106    fn from_be_byte_array() {
107        let n = UintEx::from_be_byte_array(hex!("00112233445566778899aabbccddeeff").into());
108        assert_eq!(
109            n.as_limbs(),
110            &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
111        );
112    }
113
114    #[test]
115    #[cfg(target_pointer_width = "32")]
116    fn from_le_byte_array() {
117        let n = UintEx::from_le_byte_array(hex!("7766554433221100").into());
118        assert_eq!(n.as_limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
119    }
120
121    #[test]
122    #[cfg(target_pointer_width = "64")]
123    fn from_le_byte_array() {
124        let n = UintEx::from_le_byte_array(hex!("ffeeddccbbaa99887766554433221100").into());
125        assert_eq!(
126            n.as_limbs(),
127            &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
128        );
129    }
130
131    #[test]
132    #[cfg(target_pointer_width = "32")]
133    fn to_be_byte_array() {
134        let expected_bytes = ByteArray::from(hex!("0011223344556677"));
135        let actual_bytes = UintEx::from_be_byte_array(expected_bytes).to_be_byte_array();
136        assert_eq!(expected_bytes, actual_bytes);
137    }
138
139    #[test]
140    #[cfg(target_pointer_width = "64")]
141    fn to_be_byte_array() {
142        let expected_bytes = ByteArray::from(hex!("00112233445566778899aabbccddeeff"));
143        let actual_bytes = UintEx::from_be_byte_array(expected_bytes).to_be_byte_array();
144        assert_eq!(expected_bytes, actual_bytes);
145    }
146
147    #[test]
148    #[cfg(target_pointer_width = "32")]
149    fn to_le_byte_array() {
150        let expected_bytes = ByteArray::from(hex!("7766554433221100"));
151        let actual_bytes = UintEx::from_le_byte_array(expected_bytes).to_le_byte_array();
152        assert_eq!(expected_bytes, actual_bytes);
153    }
154
155    #[test]
156    #[cfg(target_pointer_width = "64")]
157    fn to_le_byte_array() {
158        let expected_bytes = ByteArray::from(hex!("ffeeddccbbaa99887766554433221100"));
159        let actual_bytes = UintEx::from_le_byte_array(expected_bytes).to_le_byte_array();
160        assert_eq!(expected_bytes, actual_bytes);
161    }
162
163    #[test]
164    #[cfg(target_pointer_width = "32")]
165    fn into_uint_be() {
166        let expected_bytes = ByteArray::from(hex!("0011223344556677"));
167        let actual_bytes = expected_bytes.into_uint_be().to_be_byte_array();
168        assert_eq!(expected_bytes, actual_bytes);
169    }
170
171    #[test]
172    #[cfg(target_pointer_width = "64")]
173    fn into_uint_be() {
174        let expected_bytes = ByteArray::from(hex!("00112233445566778899aabbccddeeff"));
175        let actual_bytes = expected_bytes.into_uint_be().to_be_byte_array();
176        assert_eq!(expected_bytes, actual_bytes);
177    }
178
179    #[test]
180    #[cfg(target_pointer_width = "32")]
181    fn into_uint_le() {
182        let expected_bytes = ByteArray::from(hex!("7766554433221100"));
183        let actual_bytes = expected_bytes.into_uint_le().to_le_byte_array();
184        assert_eq!(expected_bytes, actual_bytes);
185    }
186
187    #[test]
188    #[cfg(target_pointer_width = "64")]
189    fn into_uint_le() {
190        let expected_bytes = ByteArray::from(hex!("ffeeddccbbaa99887766554433221100"));
191        let actual_bytes = expected_bytes.into_uint_le().to_le_byte_array();
192        assert_eq!(expected_bytes, actual_bytes);
193    }
194}