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
28pub 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
104pub 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}