binary_codec/
encodings.rs

1use crate::{DeserializationError, SerializationError};
2
3pub fn write_zigzag<T, const S: usize>(
4    val: T,
5    bytes: &mut Vec<u8>,
6    pos: &mut usize,
7    bits: &mut u8,
8) -> Result<(), SerializationError>
9where
10    T: ZigZag,
11    T::Unsigned: FixedInt<S>,
12{
13    let encoded = val.to_unsigned();
14    encoded.write(bytes, pos, bits)
15}
16
17pub fn read_zigzag<T, const S: usize>(
18    bytes: &[u8],
19    pos: &mut usize,
20    bits: &mut u8,
21) -> Result<T, DeserializationError>
22where
23    T: ZigZag,
24    T::Unsigned: FixedInt<S>,
25{
26    let raw = T::Unsigned::read(bytes, pos, bits)?;
27    Ok(T::to_signed(raw))
28}
29
30// Fixed int implementations
31pub trait FixedInt<const S: usize> : Sized {    
32    fn serialize(self) -> [u8; S];
33    fn deserialize(bytes: &[u8]) -> Self;
34
35    fn write(
36        self,
37        bytes: &mut Vec<u8>,
38        pos: &mut usize,
39        bits: &mut u8,
40    ) -> Result<(), SerializationError> {
41        *bits = 0;
42        bytes.extend_from_slice(&self.serialize());
43        *pos += S;
44        Ok(())
45    }
46
47    fn read(
48        bytes: &[u8],
49        pos: &mut usize,
50        bits: &mut u8,
51    ) -> Result<Self, DeserializationError> {
52        *bits = 0;
53        if *pos + S > bytes.len() {
54            return Err(DeserializationError::NotEnoughBytes(*pos + S - bytes.len()));
55        }
56        let val = Self::deserialize(&bytes[*pos..*pos + S]);
57        *pos += S;
58        Ok(val)
59    }
60}
61
62impl FixedInt<1> for u8 {
63    fn serialize(self) -> [u8; 1] {
64        self.to_be_bytes()
65    }
66
67    fn deserialize(bytes: &[u8]) -> Self {
68        u8::from_be_bytes(bytes.try_into().unwrap()).try_into().unwrap()
69    }
70}
71
72impl FixedInt<2> for u16 {
73    fn serialize(self) -> [u8; 2] {
74        self.to_be_bytes()
75    }
76
77    fn deserialize(bytes: &[u8]) -> Self {
78        u16::from_be_bytes(bytes.try_into().unwrap()).try_into().unwrap()
79    }
80}
81
82impl FixedInt<4> for u32 {
83    fn serialize(self) -> [u8; 4] {
84        self.to_be_bytes()
85    }
86
87    fn deserialize(bytes: &[u8]) -> Self {
88        u32::from_be_bytes(bytes.try_into().unwrap()).try_into().unwrap()
89    }
90}
91
92impl FixedInt<8> for u64 {
93    fn serialize(self) -> [u8; 8] {
94        self.to_be_bytes()
95    }
96
97    fn deserialize(bytes: &[u8]) -> Self {
98        u64::from_be_bytes(bytes.try_into().unwrap()).try_into().unwrap()
99    }
100}
101
102impl FixedInt<16> for u128 {
103    fn serialize(self) -> [u8; 16] {
104        self.to_be_bytes()
105    }
106
107    fn deserialize(bytes: &[u8]) -> Self {
108        u128::from_be_bytes(bytes.try_into().unwrap()).try_into().unwrap()
109    }
110}
111
112// ZigZag implementations
113pub trait ZigZag {
114    type Unsigned;
115
116    fn to_unsigned(self) -> Self::Unsigned;
117    fn to_signed(n: Self::Unsigned) -> Self;
118}
119
120impl ZigZag for i8 {
121    type Unsigned = u8;
122    fn to_unsigned(self) -> u8 {
123        ((self << 1) ^ (self >> 7)) as u8
124    }
125    fn to_signed(n: u8) -> i8 {
126        ((n >> 1) as i8) ^ -((n & 1) as i8)
127    }
128}
129
130impl ZigZag for i16 {
131    type Unsigned = u16;
132    fn to_unsigned(self) -> u16 {
133        ((self << 1) ^ (self >> 15)) as u16
134    }
135    fn to_signed(n: u16) -> i16 {
136        ((n >> 1) as i16) ^ -((n & 1) as i16)
137    }
138}
139
140impl ZigZag for i32 {
141    type Unsigned = u32;
142    fn to_unsigned(self) -> u32 {
143        ((self << 1) ^ (self >> 31)) as u32
144    }
145    fn to_signed(n: u32) -> i32 {
146        ((n >> 1) as i32) ^ -((n & 1) as i32)
147    }
148}
149
150impl ZigZag for i64 {
151    type Unsigned = u64;
152    fn to_unsigned(self) -> u64 {
153        ((self << 1) ^ (self >> 63)) as u64
154    }
155    fn to_signed(n: u64) -> i64 {
156        ((n >> 1) as i64) ^ -((n & 1) as i64)
157    }
158}
159
160impl ZigZag for i128 {
161    type Unsigned = u128;
162    fn to_unsigned(self) -> u128 {
163        ((self << 1) ^ (self >> 127)) as u128
164    }
165    fn to_signed(n: u128) -> i128 {
166        ((n >> 1) as i128) ^ -((n & 1) as i128)
167    }
168}
169
170#[cfg(test)]
171mod tests {
172    use super::*;
173    macro_rules! zigzag_test {
174        ($name:ident, $ty:ty, $unsigned:ty, $val:expr, $expected:expr) => {
175            #[test]
176            fn $name() {
177                let val: $ty = $val;
178                let encoded: $unsigned = val.to_unsigned();
179                assert_eq!(encoded, $expected, "ZigZag encoding failed for {}", val);
180                let decoded: $ty = <$ty>::to_signed(encoded);
181                assert_eq!(decoded, val, "ZigZag decoding failed for {}", val);
182            }
183        };
184    }
185
186    zigzag_test!(zigzag_i16_pos, i16, u16, 0b0000_0000_0000_0010, 0b0000_0000_0000_0100);
187    zigzag_test!(zigzag_i16_neg, i16, u16, -0b0000_0000_0000_0010, 0b0000_0000_0000_0011);
188    zigzag_test!(zigzag_i32_pos, i32, u32, 0b0000_0000_0000_0000_0000_0000_0000_0010, 0b0000_0000_0000_0000_0000_0000_0000_0100);
189    zigzag_test!(zigzag_i32_neg, i32, u32, -0b0000_0000_0000_0000_0000_0000_0000_0010, 0b0000_0000_0000_0000_0000_0000_0000_0011);
190    zigzag_test!(zigzag_i64_pos, i64, u64, 0b10, 0b100);
191    zigzag_test!(zigzag_i64_neg, i64, u64, -0b10, 0b11);
192    zigzag_test!(zigzag_i128_pos, i128, u128, 0b10, 0b100);
193    zigzag_test!(zigzag_i128_neg, i128, u128, -0b10, 0b11);
194
195    macro_rules! fixedint_test {
196        ($name:ident, $ty:ty, $val:expr, $bytes:expr) => {
197            #[test]
198            fn $name() {
199                let val: $ty = $val;
200                let serialized = val.serialize();
201                assert_eq!(serialized, $bytes, "FixedInt serialize failed for {}", val);
202                let deserialized = <$ty>::deserialize(&serialized);
203                assert_eq!(deserialized, val, "FixedInt deserialize failed for {:?}", serialized);
204            }
205        };
206    }
207
208    fixedint_test!(fixedint_u16, u16, 0b1010_1010_1010_1010, [0b1010_1010; 2]);
209    fixedint_test!(fixedint_u32, u32, 0b1010_1010_1010_1010_1010_1010_1010_1010, [0b1010_1010; 4]);
210    fixedint_test!(fixedint_u64, u64, 0b1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010_1010, [0b1010_1010; 8]);
211    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]);
212
213    #[test]
214    fn test_write_read_zigzag_i32() {
215        let mut bytes = Vec::new();
216        let mut pos = 0;
217        let mut bits = 0;
218        let val: i32 = -123;
219        write_zigzag::<i32, 4>(val, &mut bytes, &mut pos, &mut bits).unwrap();
220        pos = 0;
221        bits = 0;
222        let decoded = read_zigzag::<i32, 4>(&bytes, &mut pos, &mut bits).unwrap();
223        assert_eq!(decoded, val);
224    }
225
226    #[test]
227    fn test_write_read_zigzag_i64() {
228        let mut bytes = Vec::new();
229        let mut pos = 0;
230        let mut bits = 0;
231        let val: i64 = 456789;
232        write_zigzag::<i64, 8>(val, &mut bytes, &mut pos, &mut bits).unwrap();
233        pos = 0;
234        bits = 0;
235        let decoded = read_zigzag::<i64, 8>(&bytes, &mut pos, &mut bits).unwrap();
236        assert_eq!(decoded, val);
237    }
238
239    #[test]
240    fn test_write_read_fixedint_u32() {
241        let mut bytes = Vec::new();
242        let mut pos = 0;
243        let mut bits = 0;
244        let val: u32 = 0b1010_1010_1010_1010_1010_1010_1010_1010;
245        val.write(&mut bytes, &mut pos, &mut bits).unwrap();
246        pos = 0;
247        bits = 0;
248        let decoded = u32::read(&bytes, &mut pos, &mut bits).unwrap();
249        assert_eq!(decoded, val);
250    }
251
252    #[test]
253    fn test_write_read_fixedint_u128() {
254        let mut bytes = Vec::new();
255        let mut pos = 0;
256        let mut bits = 0;
257        let val: 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;
258        val.write(&mut bytes, &mut pos, &mut bits).unwrap();
259        pos = 0;
260        bits = 0;
261        let decoded = u128::read(&bytes, &mut pos, &mut bits).unwrap();
262        assert_eq!(decoded, val);
263    }
264}