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::with_capacity(64)
21 }
22
23 pub fn with_capacity(bytes: usize) -> Self {
28 Self {
29 buf: Vec::with_capacity(bytes),
30 current_byte: 0,
31 bit_offset: 0,
32 recursion_depth: 0,
33 }
34 }
35
36 pub fn reset(&mut self) {
40 self.buf.clear();
41 self.current_byte = 0;
42 self.bit_offset = 0;
43 self.recursion_depth = 0;
44 }
45
46 fn align(&mut self) {
49 if self.bit_offset > 0 {
50 self.buf.push(self.current_byte);
51 self.current_byte = 0;
52 self.bit_offset = 0;
53 }
54 }
55
56 pub fn write_bits(&mut self, value: u64, count: u8) {
61 debug_assert!(count <= 64, "write_bits: count must be <= 64");
62 if count == 0 {
63 return;
64 }
65
66 let remaining = 8 - self.bit_offset;
67
68 if count <= remaining {
72 let masked = if count >= 8 {
73 value as u8
74 } else {
75 (value as u8) & ((1u8 << count) - 1)
76 };
77 self.current_byte |= masked << self.bit_offset;
78 self.bit_offset += count;
79 if self.bit_offset == 8 {
80 self.buf.push(self.current_byte);
81 self.current_byte = 0;
82 self.bit_offset = 0;
83 }
84 return;
85 }
86
87 let mut v = value;
89 for _ in 0..count {
90 let bit = (v & 1) as u8;
91 self.current_byte |= bit << self.bit_offset;
92 self.bit_offset += 1;
93 if self.bit_offset == 8 {
94 self.buf.push(self.current_byte);
95 self.current_byte = 0;
96 self.bit_offset = 0;
97 }
98 v >>= 1;
99 }
100 }
101
102 pub fn write_bool(&mut self, v: bool) {
104 self.write_bits(v as u64, 1);
105 }
106
107 pub fn flush_to_byte_boundary(&mut self) {
113 if self.bit_offset == 0 {
114 if self.buf.is_empty() {
115 self.buf.push(0x00);
116 }
117 } else {
119 self.buf.push(self.current_byte);
120 self.current_byte = 0;
121 self.bit_offset = 0;
122 }
123 }
124
125 pub fn write_u8(&mut self, v: u8) {
127 self.align();
128 self.buf.push(v);
129 }
130
131 pub fn write_u16(&mut self, v: u16) {
133 self.align();
134 self.buf.extend_from_slice(&v.to_le_bytes());
135 }
136
137 pub fn write_u32(&mut self, v: u32) {
139 self.align();
140 self.buf.extend_from_slice(&v.to_le_bytes());
141 }
142
143 pub fn write_u64(&mut self, v: u64) {
145 self.align();
146 self.buf.extend_from_slice(&v.to_le_bytes());
147 }
148
149 pub fn write_i8(&mut self, v: i8) {
151 self.align();
152 self.buf.extend_from_slice(&v.to_le_bytes());
153 }
154
155 pub fn write_i16(&mut self, v: i16) {
157 self.align();
158 self.buf.extend_from_slice(&v.to_le_bytes());
159 }
160
161 pub fn write_i32(&mut self, v: i32) {
163 self.align();
164 self.buf.extend_from_slice(&v.to_le_bytes());
165 }
166
167 pub fn write_i64(&mut self, v: i64) {
169 self.align();
170 self.buf.extend_from_slice(&v.to_le_bytes());
171 }
172
173 pub fn write_f32(&mut self, v: f32) {
175 self.align();
176 let bits: u32 = if v.is_nan() {
177 0x7FC00000u32
178 } else {
179 v.to_bits()
180 };
181 self.buf.extend_from_slice(&bits.to_le_bytes());
182 }
183
184 pub fn write_f64(&mut self, v: f64) {
186 self.align();
187 let bits: u64 = if v.is_nan() {
188 0x7FF8000000000000u64
189 } else {
190 v.to_bits()
191 };
192 self.buf.extend_from_slice(&bits.to_le_bytes());
193 }
194
195 pub fn write_leb128(&mut self, v: u64) {
197 self.align();
198 crate::leb128::encode(&mut self.buf, v);
199 }
200
201 pub fn write_zigzag(&mut self, v: i64, type_bits: u8) {
203 let encoded = crate::zigzag::zigzag_encode(v, type_bits);
204 self.write_leb128(encoded);
205 }
206
207 pub fn write_string(&mut self, s: &str) {
209 self.align();
210 crate::leb128::encode(&mut self.buf, s.len() as u64);
211 self.buf.extend_from_slice(s.as_bytes());
212 }
213
214 pub fn write_bytes(&mut self, data: &[u8]) {
216 self.align();
217 crate::leb128::encode(&mut self.buf, data.len() as u64);
218 self.buf.extend_from_slice(data);
219 }
220
221 pub fn write_raw_bytes(&mut self, data: &[u8]) {
223 self.align();
224 self.buf.extend_from_slice(data);
225 }
226
227 pub fn enter_recursive(&mut self) -> Result<(), crate::error::EncodeError> {
229 self.recursion_depth += 1;
230 if self.recursion_depth > crate::MAX_RECURSION_DEPTH {
231 return Err(crate::error::EncodeError::RecursionLimitExceeded);
232 }
233 Ok(())
234 }
235
236 pub fn leave_recursive(&mut self) {
238 self.recursion_depth = self.recursion_depth.saturating_sub(1);
239 }
240
241 pub fn finish(mut self) -> Vec<u8> {
243 self.flush_to_byte_boundary();
244 self.buf
245 }
246}
247
248impl Default for BitWriter {
249 fn default() -> Self {
250 Self::new()
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257
258 #[test]
259 fn write_single_bit_true() {
260 let mut w = BitWriter::new();
261 w.write_bool(true);
262 assert_eq!(w.finish(), [0x01]);
263 }
264
265 #[test]
266 fn write_single_bit_false() {
267 let mut w = BitWriter::new();
268 w.write_bool(false);
269 assert_eq!(w.finish(), [0x00]);
270 }
271
272 #[test]
273 fn write_bits_lsb_first() {
274 let mut w = BitWriter::new();
275 w.write_bits(5, 3); w.write_bits(19, 5); assert_eq!(w.finish(), [0x9D]);
279 }
280
281 #[test]
282 fn write_bits_cross_byte_boundary() {
283 let mut w = BitWriter::new();
284 w.write_bits(5, 3);
285 w.write_bits(19, 5);
286 w.write_bits(42, 6); assert_eq!(w.finish(), [0x9D, 0x2A]);
289 }
290
291 #[test]
292 fn flush_to_byte_boundary_pads_zeros() {
293 let mut w = BitWriter::new();
294 w.write_bits(0b101, 3);
295 w.flush_to_byte_boundary();
296 w.write_bits(0xFF, 8);
297 assert_eq!(w.finish(), [0x05, 0xFF]);
298 }
299
300 #[test]
301 fn write_u8_flushes_first() {
302 let mut w = BitWriter::new();
303 w.write_bool(true);
304 w.write_u8(0xAB);
305 assert_eq!(w.finish(), [0x01, 0xAB]);
306 }
307
308 #[test]
309 fn write_u16_le() {
310 let mut w = BitWriter::new();
311 w.write_u16(0x0102);
312 assert_eq!(w.finish(), [0x02, 0x01]);
313 }
314
315 #[test]
316 fn write_u32_le() {
317 let mut w = BitWriter::new();
318 w.write_u32(0x01020304);
319 assert_eq!(w.finish(), [0x04, 0x03, 0x02, 0x01]);
320 }
321
322 #[test]
323 fn write_i16_negative() {
324 let mut w = BitWriter::new();
325 w.write_i16(-1);
326 assert_eq!(w.finish(), [0xFF, 0xFF]);
327 }
328
329 #[test]
330 fn write_f32_nan_canonicalized() {
331 let mut w = BitWriter::new();
332 w.write_f32(f32::NAN);
333 assert_eq!(w.finish(), [0x00, 0x00, 0xC0, 0x7F]);
334 }
335
336 #[test]
337 fn write_f64_nan_canonicalized() {
338 let mut w = BitWriter::new();
339 w.write_f64(f64::NAN);
340 assert_eq!(w.finish(), 0x7FF8000000000000u64.to_le_bytes());
341 }
342
343 #[test]
344 fn write_f32_negative_zero_preserved() {
345 let mut w = BitWriter::new();
346 w.write_f32(-0.0f32);
347 let buf = w.finish();
348 assert_eq!(buf, (-0.0f32).to_le_bytes());
349 assert_ne!(buf, 0.0f32.to_le_bytes());
350 }
351
352 #[test]
353 fn write_leb128_test() {
354 let mut w = BitWriter::new();
355 w.write_leb128(300);
356 assert_eq!(w.finish(), [0xAC, 0x02]);
357 }
358
359 #[test]
360 fn write_zigzag_neg1() {
361 let mut w = BitWriter::new();
362 w.write_zigzag(-1, 64);
363 assert_eq!(w.finish(), [0x01]);
364 }
365
366 #[test]
367 fn write_string_test() {
368 let mut w = BitWriter::new();
369 w.write_string("hi");
370 assert_eq!(w.finish(), [0x02, 0x68, 0x69]);
371 }
372
373 #[test]
374 fn write_bytes_test() {
375 let mut w = BitWriter::new();
376 w.write_bytes(&[0xDE, 0xAD]);
377 assert_eq!(w.finish(), [0x02, 0xDE, 0xAD]);
378 }
379
380 #[test]
381 fn write_raw_bytes_test() {
382 let mut w = BitWriter::new();
383 w.write_raw_bytes(&[0xCA, 0xFE]);
384 assert_eq!(w.finish(), [0xCA, 0xFE]);
385 }
386
387 #[test]
388 fn empty_flush_produces_zero_byte() {
389 let mut w = BitWriter::new();
390 w.flush_to_byte_boundary();
391 assert_eq!(w.finish(), [0x00]);
392 }
393
394 #[test]
395 fn recursion_depth_increment_decrement() {
396 let mut w = BitWriter::new();
397 w.enter_recursive().unwrap();
398 w.enter_recursive().unwrap();
399 w.leave_recursive();
400 w.leave_recursive();
401 }
402
403 #[test]
404 fn recursion_depth_max_64_succeeds() {
405 let mut w = BitWriter::new();
406 for _ in 0..64 {
407 w.enter_recursive().unwrap();
408 }
409 }
410
411 #[test]
412 fn recursion_depth_65_exceeds_limit() {
413 use crate::error::EncodeError;
414 let mut w = BitWriter::new();
415 for _ in 0..64 {
416 w.enter_recursive().unwrap();
417 }
418 assert_eq!(
419 w.enter_recursive().unwrap_err(),
420 EncodeError::RecursionLimitExceeded
421 );
422 }
423}