Skip to main content

vsss_rs/
fixed_array.rs

1use super::*;
2
3/// A trait for converting a type to and from a fixed-size array.
4pub trait FixedArray<const LIMBS: usize> {
5    /// Convert the type to a fixed-size array.
6    fn to_fixed_array(&self) -> [u8; LIMBS];
7    /// Convert from a fixed-size array to the type.
8    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}