vexil_runtime/
bit_writer.rs1pub struct BitWriter {
11 buf: Vec<u8>,
12 current_byte: u8,
13 bit_offset: u8,
14 recursion_depth: u32,
15}
16
17impl BitWriter {
18 pub fn new() -> Self {
20 Self {
21 buf: Vec::new(),
22 current_byte: 0,
23 bit_offset: 0,
24 recursion_depth: 0,
25 }
26 }
27
28 fn align(&mut self) {
31 if self.bit_offset > 0 {
32 self.buf.push(self.current_byte);
33 self.current_byte = 0;
34 self.bit_offset = 0;
35 }
36 }
37
38 pub fn write_bits(&mut self, value: u64, count: u8) {
40 let mut v = value;
41 for _ in 0..count {
42 let bit = (v & 1) as u8;
43 self.current_byte |= bit << self.bit_offset;
44 self.bit_offset += 1;
45 if self.bit_offset == 8 {
46 self.buf.push(self.current_byte);
47 self.current_byte = 0;
48 self.bit_offset = 0;
49 }
50 v >>= 1;
51 }
52 }
53
54 pub fn write_bool(&mut self, v: bool) {
56 self.write_bits(v as u64, 1);
57 }
58
59 pub fn flush_to_byte_boundary(&mut self) {
65 if self.bit_offset == 0 {
66 if self.buf.is_empty() {
67 self.buf.push(0x00);
68 }
69 } else {
71 self.buf.push(self.current_byte);
72 self.current_byte = 0;
73 self.bit_offset = 0;
74 }
75 }
76
77 pub fn write_u8(&mut self, v: u8) {
79 self.align();
80 self.buf.push(v);
81 }
82
83 pub fn write_u16(&mut self, v: u16) {
85 self.align();
86 self.buf.extend_from_slice(&v.to_le_bytes());
87 }
88
89 pub fn write_u32(&mut self, v: u32) {
91 self.align();
92 self.buf.extend_from_slice(&v.to_le_bytes());
93 }
94
95 pub fn write_u64(&mut self, v: u64) {
97 self.align();
98 self.buf.extend_from_slice(&v.to_le_bytes());
99 }
100
101 pub fn write_i8(&mut self, v: i8) {
103 self.align();
104 self.buf.extend_from_slice(&v.to_le_bytes());
105 }
106
107 pub fn write_i16(&mut self, v: i16) {
109 self.align();
110 self.buf.extend_from_slice(&v.to_le_bytes());
111 }
112
113 pub fn write_i32(&mut self, v: i32) {
115 self.align();
116 self.buf.extend_from_slice(&v.to_le_bytes());
117 }
118
119 pub fn write_i64(&mut self, v: i64) {
121 self.align();
122 self.buf.extend_from_slice(&v.to_le_bytes());
123 }
124
125 pub fn write_f32(&mut self, v: f32) {
127 self.align();
128 let bits: u32 = if v.is_nan() {
129 0x7FC00000u32
130 } else {
131 v.to_bits()
132 };
133 self.buf.extend_from_slice(&bits.to_le_bytes());
134 }
135
136 pub fn write_f64(&mut self, v: f64) {
138 self.align();
139 let bits: u64 = if v.is_nan() {
140 0x7FF8000000000000u64
141 } else {
142 v.to_bits()
143 };
144 self.buf.extend_from_slice(&bits.to_le_bytes());
145 }
146
147 pub fn write_leb128(&mut self, v: u64) {
149 self.align();
150 crate::leb128::encode(&mut self.buf, v);
151 }
152
153 pub fn write_zigzag(&mut self, v: i64, type_bits: u8) {
155 let encoded = crate::zigzag::zigzag_encode(v, type_bits);
156 self.write_leb128(encoded);
157 }
158
159 pub fn write_string(&mut self, s: &str) {
161 self.align();
162 crate::leb128::encode(&mut self.buf, s.len() as u64);
163 self.buf.extend_from_slice(s.as_bytes());
164 }
165
166 pub fn write_bytes(&mut self, data: &[u8]) {
168 self.align();
169 crate::leb128::encode(&mut self.buf, data.len() as u64);
170 self.buf.extend_from_slice(data);
171 }
172
173 pub fn write_raw_bytes(&mut self, data: &[u8]) {
175 self.align();
176 self.buf.extend_from_slice(data);
177 }
178
179 pub fn enter_recursive(&mut self) -> Result<(), crate::error::EncodeError> {
181 self.recursion_depth += 1;
182 if self.recursion_depth > crate::MAX_RECURSION_DEPTH {
183 return Err(crate::error::EncodeError::RecursionLimitExceeded);
184 }
185 Ok(())
186 }
187
188 pub fn leave_recursive(&mut self) {
190 self.recursion_depth = self.recursion_depth.saturating_sub(1);
191 }
192
193 pub fn finish(mut self) -> Vec<u8> {
195 self.flush_to_byte_boundary();
196 self.buf
197 }
198}
199
200impl Default for BitWriter {
201 fn default() -> Self {
202 Self::new()
203 }
204}
205
206#[cfg(test)]
207mod tests {
208 use super::*;
209
210 #[test]
211 fn write_single_bit_true() {
212 let mut w = BitWriter::new();
213 w.write_bool(true);
214 assert_eq!(w.finish(), [0x01]);
215 }
216
217 #[test]
218 fn write_single_bit_false() {
219 let mut w = BitWriter::new();
220 w.write_bool(false);
221 assert_eq!(w.finish(), [0x00]);
222 }
223
224 #[test]
225 fn write_bits_lsb_first() {
226 let mut w = BitWriter::new();
227 w.write_bits(5, 3); w.write_bits(19, 5); assert_eq!(w.finish(), [0x9D]);
231 }
232
233 #[test]
234 fn write_bits_cross_byte_boundary() {
235 let mut w = BitWriter::new();
236 w.write_bits(5, 3);
237 w.write_bits(19, 5);
238 w.write_bits(42, 6); assert_eq!(w.finish(), [0x9D, 0x2A]);
241 }
242
243 #[test]
244 fn flush_to_byte_boundary_pads_zeros() {
245 let mut w = BitWriter::new();
246 w.write_bits(0b101, 3);
247 w.flush_to_byte_boundary();
248 w.write_bits(0xFF, 8);
249 assert_eq!(w.finish(), [0x05, 0xFF]);
250 }
251
252 #[test]
253 fn write_u8_flushes_first() {
254 let mut w = BitWriter::new();
255 w.write_bool(true);
256 w.write_u8(0xAB);
257 assert_eq!(w.finish(), [0x01, 0xAB]);
258 }
259
260 #[test]
261 fn write_u16_le() {
262 let mut w = BitWriter::new();
263 w.write_u16(0x0102);
264 assert_eq!(w.finish(), [0x02, 0x01]);
265 }
266
267 #[test]
268 fn write_u32_le() {
269 let mut w = BitWriter::new();
270 w.write_u32(0x01020304);
271 assert_eq!(w.finish(), [0x04, 0x03, 0x02, 0x01]);
272 }
273
274 #[test]
275 fn write_i16_negative() {
276 let mut w = BitWriter::new();
277 w.write_i16(-1);
278 assert_eq!(w.finish(), [0xFF, 0xFF]);
279 }
280
281 #[test]
282 fn write_f32_nan_canonicalized() {
283 let mut w = BitWriter::new();
284 w.write_f32(f32::NAN);
285 assert_eq!(w.finish(), [0x00, 0x00, 0xC0, 0x7F]);
286 }
287
288 #[test]
289 fn write_f64_nan_canonicalized() {
290 let mut w = BitWriter::new();
291 w.write_f64(f64::NAN);
292 assert_eq!(w.finish(), 0x7FF8000000000000u64.to_le_bytes());
293 }
294
295 #[test]
296 fn write_f32_negative_zero_preserved() {
297 let mut w = BitWriter::new();
298 w.write_f32(-0.0f32);
299 let buf = w.finish();
300 assert_eq!(buf, (-0.0f32).to_le_bytes());
301 assert_ne!(buf, 0.0f32.to_le_bytes());
302 }
303
304 #[test]
305 fn write_leb128_test() {
306 let mut w = BitWriter::new();
307 w.write_leb128(300);
308 assert_eq!(w.finish(), [0xAC, 0x02]);
309 }
310
311 #[test]
312 fn write_zigzag_neg1() {
313 let mut w = BitWriter::new();
314 w.write_zigzag(-1, 64);
315 assert_eq!(w.finish(), [0x01]);
316 }
317
318 #[test]
319 fn write_string_test() {
320 let mut w = BitWriter::new();
321 w.write_string("hi");
322 assert_eq!(w.finish(), [0x02, 0x68, 0x69]);
323 }
324
325 #[test]
326 fn write_bytes_test() {
327 let mut w = BitWriter::new();
328 w.write_bytes(&[0xDE, 0xAD]);
329 assert_eq!(w.finish(), [0x02, 0xDE, 0xAD]);
330 }
331
332 #[test]
333 fn write_raw_bytes_test() {
334 let mut w = BitWriter::new();
335 w.write_raw_bytes(&[0xCA, 0xFE]);
336 assert_eq!(w.finish(), [0xCA, 0xFE]);
337 }
338
339 #[test]
340 fn empty_flush_produces_zero_byte() {
341 let mut w = BitWriter::new();
342 w.flush_to_byte_boundary();
343 assert_eq!(w.finish(), [0x00]);
344 }
345
346 #[test]
347 fn recursion_depth_increment_decrement() {
348 let mut w = BitWriter::new();
349 w.enter_recursive().unwrap();
350 w.enter_recursive().unwrap();
351 w.leave_recursive();
352 w.leave_recursive();
353 }
354
355 #[test]
356 fn recursion_depth_max_64_succeeds() {
357 let mut w = BitWriter::new();
358 for _ in 0..64 {
359 w.enter_recursive().unwrap();
360 }
361 }
362
363 #[test]
364 fn recursion_depth_65_exceeds_limit() {
365 use crate::error::EncodeError;
366 let mut w = BitWriter::new();
367 for _ in 0..64 {
368 w.enter_recursive().unwrap();
369 }
370 assert_eq!(
371 w.enter_recursive().unwrap_err(),
372 EncodeError::RecursionLimitExceeded
373 );
374 }
375}