crypto_bigint/uint/
array.rs

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