binary_codec/
fixed_int.rs

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