binary_codec/
fixed_int.rs

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