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
30pub 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
112pub 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}