vexil_runtime/
bit_writer.rs1pub struct BitWriter {
11 buf: Vec<u8>,
12 current_byte: u8,
13 bit_offset: u8,
14}
15
16impl BitWriter {
17 pub fn new() -> Self {
19 Self {
20 buf: Vec::new(),
21 current_byte: 0,
22 bit_offset: 0,
23 }
24 }
25
26 fn align(&mut self) {
29 if self.bit_offset > 0 {
30 self.buf.push(self.current_byte);
31 self.current_byte = 0;
32 self.bit_offset = 0;
33 }
34 }
35
36 pub fn write_bits(&mut self, value: u64, count: u8) {
38 let mut v = value;
39 for _ in 0..count {
40 let bit = (v & 1) as u8;
41 self.current_byte |= bit << self.bit_offset;
42 self.bit_offset += 1;
43 if self.bit_offset == 8 {
44 self.buf.push(self.current_byte);
45 self.current_byte = 0;
46 self.bit_offset = 0;
47 }
48 v >>= 1;
49 }
50 }
51
52 pub fn write_bool(&mut self, v: bool) {
54 self.write_bits(v as u64, 1);
55 }
56
57 pub fn flush_to_byte_boundary(&mut self) {
63 if self.bit_offset == 0 {
64 if self.buf.is_empty() {
65 self.buf.push(0x00);
66 }
67 } else {
69 self.buf.push(self.current_byte);
70 self.current_byte = 0;
71 self.bit_offset = 0;
72 }
73 }
74
75 pub fn write_u8(&mut self, v: u8) {
77 self.align();
78 self.buf.push(v);
79 }
80
81 pub fn write_u16(&mut self, v: u16) {
83 self.align();
84 self.buf.extend_from_slice(&v.to_le_bytes());
85 }
86
87 pub fn write_u32(&mut self, v: u32) {
89 self.align();
90 self.buf.extend_from_slice(&v.to_le_bytes());
91 }
92
93 pub fn write_u64(&mut self, v: u64) {
95 self.align();
96 self.buf.extend_from_slice(&v.to_le_bytes());
97 }
98
99 pub fn write_i8(&mut self, v: i8) {
101 self.align();
102 self.buf.extend_from_slice(&v.to_le_bytes());
103 }
104
105 pub fn write_i16(&mut self, v: i16) {
107 self.align();
108 self.buf.extend_from_slice(&v.to_le_bytes());
109 }
110
111 pub fn write_i32(&mut self, v: i32) {
113 self.align();
114 self.buf.extend_from_slice(&v.to_le_bytes());
115 }
116
117 pub fn write_i64(&mut self, v: i64) {
119 self.align();
120 self.buf.extend_from_slice(&v.to_le_bytes());
121 }
122
123 pub fn write_f32(&mut self, v: f32) {
125 self.align();
126 let bits: u32 = if v.is_nan() {
127 0x7FC00000u32
128 } else {
129 v.to_bits()
130 };
131 self.buf.extend_from_slice(&bits.to_le_bytes());
132 }
133
134 pub fn write_f64(&mut self, v: f64) {
136 self.align();
137 let bits: u64 = if v.is_nan() {
138 0x7FF8000000000000u64
139 } else {
140 v.to_bits()
141 };
142 self.buf.extend_from_slice(&bits.to_le_bytes());
143 }
144
145 pub fn write_leb128(&mut self, v: u64) {
147 self.align();
148 crate::leb128::encode(&mut self.buf, v);
149 }
150
151 pub fn write_zigzag(&mut self, v: i64, type_bits: u8) {
153 let encoded = crate::zigzag::zigzag_encode(v, type_bits);
154 self.write_leb128(encoded);
155 }
156
157 pub fn write_string(&mut self, s: &str) {
159 self.align();
160 crate::leb128::encode(&mut self.buf, s.len() as u64);
161 self.buf.extend_from_slice(s.as_bytes());
162 }
163
164 pub fn write_bytes(&mut self, data: &[u8]) {
166 self.align();
167 crate::leb128::encode(&mut self.buf, data.len() as u64);
168 self.buf.extend_from_slice(data);
169 }
170
171 pub fn write_raw_bytes(&mut self, data: &[u8]) {
173 self.align();
174 self.buf.extend_from_slice(data);
175 }
176
177 pub fn finish(mut self) -> Vec<u8> {
179 self.flush_to_byte_boundary();
180 self.buf
181 }
182}
183
184impl Default for BitWriter {
185 fn default() -> Self {
186 Self::new()
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use super::*;
193
194 #[test]
195 fn write_single_bit_true() {
196 let mut w = BitWriter::new();
197 w.write_bool(true);
198 assert_eq!(w.finish(), [0x01]);
199 }
200
201 #[test]
202 fn write_single_bit_false() {
203 let mut w = BitWriter::new();
204 w.write_bool(false);
205 assert_eq!(w.finish(), [0x00]);
206 }
207
208 #[test]
209 fn write_bits_lsb_first() {
210 let mut w = BitWriter::new();
211 w.write_bits(5, 3); w.write_bits(19, 5); assert_eq!(w.finish(), [0x9D]);
215 }
216
217 #[test]
218 fn write_bits_cross_byte_boundary() {
219 let mut w = BitWriter::new();
220 w.write_bits(5, 3);
221 w.write_bits(19, 5);
222 w.write_bits(42, 6); assert_eq!(w.finish(), [0x9D, 0x2A]);
225 }
226
227 #[test]
228 fn flush_to_byte_boundary_pads_zeros() {
229 let mut w = BitWriter::new();
230 w.write_bits(0b101, 3);
231 w.flush_to_byte_boundary();
232 w.write_bits(0xFF, 8);
233 assert_eq!(w.finish(), [0x05, 0xFF]);
234 }
235
236 #[test]
237 fn write_u8_flushes_first() {
238 let mut w = BitWriter::new();
239 w.write_bool(true);
240 w.write_u8(0xAB);
241 assert_eq!(w.finish(), [0x01, 0xAB]);
242 }
243
244 #[test]
245 fn write_u16_le() {
246 let mut w = BitWriter::new();
247 w.write_u16(0x0102);
248 assert_eq!(w.finish(), [0x02, 0x01]);
249 }
250
251 #[test]
252 fn write_u32_le() {
253 let mut w = BitWriter::new();
254 w.write_u32(0x01020304);
255 assert_eq!(w.finish(), [0x04, 0x03, 0x02, 0x01]);
256 }
257
258 #[test]
259 fn write_i16_negative() {
260 let mut w = BitWriter::new();
261 w.write_i16(-1);
262 assert_eq!(w.finish(), [0xFF, 0xFF]);
263 }
264
265 #[test]
266 fn write_f32_nan_canonicalized() {
267 let mut w = BitWriter::new();
268 w.write_f32(f32::NAN);
269 assert_eq!(w.finish(), [0x00, 0x00, 0xC0, 0x7F]);
270 }
271
272 #[test]
273 fn write_f64_nan_canonicalized() {
274 let mut w = BitWriter::new();
275 w.write_f64(f64::NAN);
276 assert_eq!(w.finish(), 0x7FF8000000000000u64.to_le_bytes());
277 }
278
279 #[test]
280 fn write_f32_negative_zero_preserved() {
281 let mut w = BitWriter::new();
282 w.write_f32(-0.0f32);
283 let buf = w.finish();
284 assert_eq!(buf, (-0.0f32).to_le_bytes());
285 assert_ne!(buf, 0.0f32.to_le_bytes());
286 }
287
288 #[test]
289 fn write_leb128_test() {
290 let mut w = BitWriter::new();
291 w.write_leb128(300);
292 assert_eq!(w.finish(), [0xAC, 0x02]);
293 }
294
295 #[test]
296 fn write_zigzag_neg1() {
297 let mut w = BitWriter::new();
298 w.write_zigzag(-1, 64);
299 assert_eq!(w.finish(), [0x01]);
300 }
301
302 #[test]
303 fn write_string_test() {
304 let mut w = BitWriter::new();
305 w.write_string("hi");
306 assert_eq!(w.finish(), [0x02, 0x68, 0x69]);
307 }
308
309 #[test]
310 fn write_bytes_test() {
311 let mut w = BitWriter::new();
312 w.write_bytes(&[0xDE, 0xAD]);
313 assert_eq!(w.finish(), [0x02, 0xDE, 0xAD]);
314 }
315
316 #[test]
317 fn write_raw_bytes_test() {
318 let mut w = BitWriter::new();
319 w.write_raw_bytes(&[0xCA, 0xFE]);
320 assert_eq!(w.finish(), [0xCA, 0xFE]);
321 }
322
323 #[test]
324 fn empty_flush_produces_zero_byte() {
325 let mut w = BitWriter::new();
326 w.flush_to_byte_boundary();
327 assert_eq!(w.finish(), [0x00]);
328 }
329}