1use super::*;
2
3pub trait FixedArray<const LIMBS: usize> {
5 fn to_fixed_array(&self) -> [u8; LIMBS];
7 fn from_fixed_array(array: &[u8; LIMBS]) -> Self;
9}
10
11macro_rules! impl_fixed_array {
12 ($($inner:ident => $size:expr),+$(,)*) => {
13 $(
14 impl FixedArray<$size> for $inner {
15 fn to_fixed_array(&self) -> [u8; $size] {
16 self.to_be_bytes()
17 }
18
19 fn from_fixed_array(array: &[u8; $size]) -> Self {
20 $inner::from_be_bytes(*array)
21 }
22 }
23 )+
24 };
25}
26
27impl_fixed_array!(
28 u8 => 1,
29 u16 => 2,
30 u32 => 4,
31 u64 => 8,
32 u128 => 16,
33 usize => USIZE_BYTES,
34 i8 => 1,
35 i16 => 2,
36 i32 => 4,
37 i64 => 8,
38 i128 => 16,
39 isize => ISIZE_BYTES,
40);
41
42#[cfg(test)]
43mod tests {
44 use super::FixedArray;
45 use core::mem::size_of;
46
47 fn assert_round_trip<T, const LIMBS: usize>(value: T)
48 where
49 T: FixedArray<LIMBS> + Copy + Eq + core::fmt::Debug,
50 {
51 let bytes = value.to_fixed_array();
52 assert_eq!(T::from_fixed_array(&bytes), value);
53 }
54
55 #[test]
56 fn unsigned_primitives_round_trip_as_fixed_arrays() {
57 assert_round_trip::<u8, 1>(0xab);
58 assert_round_trip::<u16, 2>(0xabcd);
59 assert_round_trip::<u32, 4>(0xabcdef12);
60 assert_round_trip::<u64, 8>(0xabcdef1234567890);
61 assert_round_trip::<u128, 16>(0xabcdef1234567890fedcba0987654321);
62 assert_round_trip::<usize, { size_of::<usize>() }>(usize::MAX - 7);
63 }
64
65 #[test]
66 fn signed_primitives_round_trip_as_fixed_arrays() {
67 assert_round_trip::<i8, 1>(-5);
68 assert_round_trip::<i16, 2>(-1234);
69 assert_round_trip::<i32, 4>(-12345678);
70 assert_round_trip::<i64, 8>(-123456789012345);
71 assert_round_trip::<i128, 16>(-123456789012345678901234567890);
72 assert_round_trip::<isize, { size_of::<isize>() }>(isize::MIN + 7);
73 }
74}