binary_codec/encoding/
fixed_int.rs

1use crate::encoding::zigzag::ZigZag;
2
3/// FixedInt
4pub trait FixedInt<const S: usize>: Sized {
5    /// Serialize self to fixed-size big-endian u8 array
6    fn serialize(self) -> [u8; S];
7
8    /// Deserialize from big-endian slice
9    fn deserialize(bytes: &[u8]) -> Self;
10}
11
12impl FixedInt<1> for u8 {
13    fn serialize(self) -> [u8; 1] {
14        self.to_be_bytes()
15    }
16
17    fn deserialize(bytes: &[u8]) -> Self {
18        u8::from_be_bytes(bytes.try_into().unwrap())
19            .try_into()
20            .unwrap()
21    }
22}
23
24impl FixedInt<1> for i8 {
25    fn serialize(self) -> [u8; 1] {
26        FixedInt::serialize(self.to_unsigned())
27    }
28
29    fn deserialize(bytes: &[u8]) -> Self {
30        ZigZag::to_signed(FixedInt::deserialize(bytes))
31    }
32}
33
34impl FixedInt<2> for u16 {
35    fn serialize(self) -> [u8; 2] {
36        self.to_be_bytes()
37    }
38
39    fn deserialize(bytes: &[u8]) -> Self {
40        u16::from_be_bytes(bytes.try_into().unwrap())
41            .try_into()
42            .unwrap()
43    }
44}
45
46impl FixedInt<2> for i16 {
47    fn serialize(self) -> [u8; 2] {
48        FixedInt::serialize(self.to_unsigned())
49    }
50
51    fn deserialize(bytes: &[u8]) -> Self {
52        ZigZag::to_signed(FixedInt::deserialize(bytes))
53    }
54}
55
56impl FixedInt<4> for u32 {
57    fn serialize(self) -> [u8; 4] {
58        self.to_be_bytes()
59    }
60
61    fn deserialize(bytes: &[u8]) -> Self {
62        u32::from_be_bytes(bytes.try_into().unwrap())
63            .try_into()
64            .unwrap()
65    }
66}
67
68impl FixedInt<4> for i32 {
69    fn serialize(self) -> [u8; 4] {
70        FixedInt::serialize(self.to_unsigned())
71    }
72
73    fn deserialize(bytes: &[u8]) -> Self {
74        ZigZag::to_signed(FixedInt::deserialize(bytes))
75    }
76}
77
78impl FixedInt<8> for u64 {
79    fn serialize(self) -> [u8; 8] {
80        self.to_be_bytes()
81    }
82
83    fn deserialize(bytes: &[u8]) -> Self {
84        u64::from_be_bytes(bytes.try_into().unwrap())
85            .try_into()
86            .unwrap()
87    }
88}
89
90impl FixedInt<8> for i64 {
91    fn serialize(self) -> [u8; 8] {
92        FixedInt::serialize(self.to_unsigned())
93    }
94
95    fn deserialize(bytes: &[u8]) -> Self {
96        ZigZag::to_signed(FixedInt::deserialize(bytes))
97    }
98}
99
100impl FixedInt<16> for u128 {
101    fn serialize(self) -> [u8; 16] {
102        self.to_be_bytes()
103    }
104
105    fn deserialize(bytes: &[u8]) -> Self {
106        u128::from_be_bytes(bytes.try_into().unwrap())
107            .try_into()
108            .unwrap()
109    }
110}
111
112impl FixedInt<16> for i128 {
113    fn serialize(self) -> [u8; 16] {
114        FixedInt::serialize(self.to_unsigned())
115    }
116
117    fn deserialize(bytes: &[u8]) -> Self {
118        ZigZag::to_signed(FixedInt::deserialize(bytes))
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use crate::encoding::fixed_int::FixedInt;
125
126    macro_rules! fixedint_test {
127        ($name:ident, $ty:ty, $val:expr, $bytes:expr) => {
128            #[test]
129            fn $name() {
130                let val: $ty = $val;
131                let serialized = val.serialize();
132                assert_eq!(serialized, $bytes, "FixedInt serialize failed for {}", val);
133                let deserialized = <$ty>::deserialize(&serialized);
134                assert_eq!(
135                    deserialized, val,
136                    "FixedInt deserialize failed for {:?}",
137                    serialized
138                );
139            }
140        };
141    }
142
143    fixedint_test!(fixedint_u16, u16, 0b1010_1010_1010_1010, [0b1010_1010; 2]);
144    fixedint_test!(
145        fixedint_u32,
146        u32,
147        0b1010_1010_1010_1010_1010_1010_1010_1010,
148        [0b1010_1010; 4]
149    );
150    fixedint_test!(
151        fixedint_u64,
152        u64,
153        0b1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010,
154        [0b1010_1010; 8]
155    );
156    fixedint_test!(fixedint_u128, u128, 0b1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010, [0b1010_1010; 16]);
157}