1use crate::error::{Error, Result};
11
12pub const MAX_BIT_WIDTH: u32 = 64;
14
15#[derive(Debug, Clone)]
28pub struct BitReader<'a> {
29 bytes: &'a [u8],
30 bit_pos: usize,
31}
32
33impl<'a> BitReader<'a> {
34 #[inline]
36 pub const fn new(bytes: &'a [u8]) -> Self {
37 Self { bytes, bit_pos: 0 }
38 }
39
40 #[inline]
42 pub const fn bits_consumed(&self) -> usize {
43 self.bit_pos
44 }
45
46 #[inline]
48 pub const fn bits_remaining(&self) -> usize {
49 bit_capacity(self.bytes.len()) - self.bit_pos
50 }
51
52 #[inline]
57 pub fn align_to_byte(&mut self) {
58 self.bit_pos = (self.bit_pos + 7) & !7;
62 }
63
64 pub fn read_bits(&mut self, n: u32) -> Result<u64> {
71 if n == 0 || n > MAX_BIT_WIDTH {
72 return Err(Error::BitOverflow);
73 }
74 if (n as usize) > self.bits_remaining() {
75 return Err(Error::UnexpectedEof);
76 }
77 let mut value: u64 = 0;
78 let mut bits_left = n;
79 while bits_left > 0 {
80 let byte_idx = self.bit_pos / 8;
81 let bit_off = (self.bit_pos % 8) as u32;
82 let avail = 8 - bit_off;
83 let take = if bits_left < avail { bits_left } else { avail };
84 let shift = avail - take;
85 let mask: u32 = (1u32 << take) - 1;
86 let chunk = (u32::from(self.bytes[byte_idx]) >> shift) & mask;
87 value = (value << take) | u64::from(chunk);
88 self.bit_pos += take as usize;
89 bits_left -= take;
90 }
91 Ok(value)
92 }
93
94 #[inline]
110 pub fn read_bool(&mut self) -> Result<bool> {
111 self.read_bits(1).map(|bit| bit != 0)
112 }
113
114 #[inline]
131 pub fn read_signed_bits(&mut self, n: u32) -> Result<i64> {
132 self.read_bits(n).map(|raw| sign_extend(raw, n))
133 }
134}
135
136#[inline]
138pub(crate) const fn sign_extend(raw: u64, n: u32) -> i64 {
139 let shift = 64 - n;
140 ((raw << shift) as i64) >> shift
141}
142
143#[inline]
146pub(crate) fn signed_to_bits(value: i64, n: u32) -> Option<u64> {
147 if n == 0 || n > MAX_BIT_WIDTH {
148 return None;
149 }
150 let shift = 64 - n;
151 let raw = (value as u64) & (u64::MAX >> shift);
154 (sign_extend(raw, n) == value).then_some(raw)
155}
156
157#[derive(Debug)]
178pub struct BitWriter<'a> {
179 bytes: &'a mut [u8],
180 bit_pos: usize,
181}
182
183impl<'a> BitWriter<'a> {
184 #[inline]
187 pub fn new(bytes: &'a mut [u8]) -> Self {
188 Self { bytes, bit_pos: 0 }
189 }
190
191 #[inline]
193 pub fn bits_written(&self) -> usize {
194 self.bit_pos
195 }
196
197 pub fn align_to_byte(&mut self) -> Result<()> {
207 self.zero_trailing_bits();
208 self.bit_pos = (self.bit_pos + 7) & !7;
212 Ok(())
213 }
214
215 #[inline]
217 fn zero_trailing_bits(&mut self) {
218 let bit_off = self.bit_pos % 8;
219 if bit_off != 0 {
220 let keep = 0xFFu8 << (8 - bit_off);
221 self.bytes[self.bit_pos / 8] &= keep;
222 }
223 }
224
225 pub fn write_bits(&mut self, value: u64, n: u32) -> Result<()> {
233 if n == 0 || n > MAX_BIT_WIDTH {
234 return Err(Error::BitOverflow);
235 }
236 if n < 64 && (value >> n) != 0 {
237 return Err(Error::BitOverflow);
238 }
239 if (n as usize) > bit_capacity(self.bytes.len()) - self.bit_pos {
240 return Err(Error::BufferFull);
241 }
242 let mut bits_left = n;
243 while bits_left > 0 {
244 let byte_idx = self.bit_pos / 8;
245 let bit_off = (self.bit_pos % 8) as u32;
246 let avail = 8 - bit_off;
247 let take = if bits_left < avail { bits_left } else { avail };
248 let shift = avail - take;
249 let chunk = ((value >> (bits_left - take)) & ((1u64 << take) - 1)) as u8;
250 let mask = (((1u32 << take) - 1) as u8) << shift;
254 self.bytes[byte_idx] = (self.bytes[byte_idx] & !mask) | (chunk << shift);
255 self.bit_pos += take as usize;
256 bits_left -= take;
257 }
258 Ok(())
259 }
260
261 #[inline]
281 pub fn write_bool(&mut self, value: bool) -> Result<()> {
282 self.write_bits(u64::from(value), 1)
283 }
284
285 #[inline]
306 pub fn write_signed_bits(&mut self, value: i64, n: u32) -> Result<()> {
307 let raw = signed_to_bits(value, n).ok_or(Error::BitOverflow)?;
308 self.write_bits(raw, n)
309 }
310
311 #[inline]
316 pub fn finish(mut self) -> usize {
317 self.zero_trailing_bits();
318 self.bit_pos.div_ceil(8)
319 }
320}
321
322#[inline]
329const fn bit_capacity(len: usize) -> usize {
330 let max_bytes = usize::MAX / 8;
331 let bytes = if len < max_bytes { len } else { max_bytes };
332 bytes * 8
333}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338
339 #[test]
340 fn pack_unpack_round_trip() {
341 let mut storage = [0u8; 4];
342 let mut w = BitWriter::new(&mut storage);
343 w.write_bits(0b1011, 4).unwrap();
344 w.write_bits(0b1100_1010, 8).unwrap();
345 w.write_bits(0b1111_0000, 8).unwrap();
346 let n = w.finish();
347 assert_eq!(n, 3);
348
349 let mut r = BitReader::new(&storage[..n]);
350 assert_eq!(r.read_bits(4).unwrap(), 0b1011);
351 assert_eq!(r.read_bits(8).unwrap(), 0b1100_1010);
352 assert_eq!(r.read_bits(8).unwrap(), 0b1111_0000);
353 }
354
355 #[test]
356 fn write_rejects_value_overflow() {
357 let mut storage = [0u8; 1];
358 let mut w = BitWriter::new(&mut storage);
359 assert_eq!(w.write_bits(0b1_0000, 4), Err(Error::BitOverflow));
361 }
362
363 #[test]
364 fn padding_bits_are_zeroed_on_reused_buffer() {
365 let mut storage = [0xFFu8; 2];
367 let mut w = BitWriter::new(&mut storage);
368 w.write_bits(0b1, 1).unwrap();
369 w.align_to_byte().unwrap();
370 w.write_bits(0b0, 1).unwrap();
371 assert_eq!(w.finish(), 2);
372 assert_eq!(storage, [0b1000_0000, 0b0000_0000]);
373 }
374
375 #[test]
376 fn finish_leaves_bytes_past_the_prefix_untouched() {
377 let mut storage = [0xAAu8; 3];
378 let mut w = BitWriter::new(&mut storage);
379 w.write_bits(0b11, 2).unwrap();
380 assert_eq!(w.finish(), 1);
381 assert_eq!(storage, [0b1100_0000, 0xAA, 0xAA]);
382 }
383
384 #[test]
385 fn align_when_already_aligned_is_a_no_op() {
386 let mut storage = [0xFFu8; 1];
387 let mut w = BitWriter::new(&mut storage);
388 w.align_to_byte().unwrap();
389 assert_eq!(w.bits_written(), 0);
390 w.write_bits(0xA5, 8).unwrap();
391 w.align_to_byte().unwrap();
392 assert_eq!(w.bits_written(), 8);
393 assert_eq!(w.finish(), 1);
394 assert_eq!(storage, [0xA5]);
395 }
396
397 #[test]
398 fn reader_align_to_byte() {
399 let mut r = BitReader::new(&[0b1010_0000, 0xCD]);
400 r.align_to_byte();
401 assert_eq!(r.bits_consumed(), 0, "aligned cursor does not move");
402 assert_eq!(r.read_bits(3).unwrap(), 0b101);
403 r.align_to_byte();
404 assert_eq!(r.bits_consumed(), 8);
405 assert_eq!(r.bits_remaining(), 8);
406 assert_eq!(r.read_bits(8).unwrap(), 0xCD);
407 r.align_to_byte();
408 assert_eq!(r.bits_consumed(), 16, "align at end of input stays put");
409 assert_eq!(r.read_bits(1), Err(Error::UnexpectedEof));
410 }
411
412 #[test]
413 fn width_validation() {
414 let mut r = BitReader::new(&[0xFF; 16]);
415 assert_eq!(r.read_bits(0), Err(Error::BitOverflow));
416 assert_eq!(r.read_bits(65), Err(Error::BitOverflow));
417 assert_eq!(r.read_signed_bits(0), Err(Error::BitOverflow));
418 assert_eq!(r.bits_consumed(), 0);
419
420 let mut storage = [0u8; 16];
421 let mut w = BitWriter::new(&mut storage);
422 assert_eq!(w.write_bits(0, 0), Err(Error::BitOverflow));
423 assert_eq!(w.write_bits(0, 65), Err(Error::BitOverflow));
424 assert_eq!(w.write_signed_bits(0, 0), Err(Error::BitOverflow));
425 assert_eq!(w.write_signed_bits(0, 65), Err(Error::BitOverflow));
426 assert_eq!(w.bits_written(), 0);
427 }
428
429 #[test]
430 fn full_width_fields_at_unaligned_offsets() {
431 for offset in 0..8u32 {
432 let mut storage = [0u8; 10];
433 let mut w = BitWriter::new(&mut storage);
434 if offset > 0 {
435 w.write_bits(0, offset).unwrap();
436 }
437 w.write_bits(0xDEAD_BEEF_0123_4567, 64).unwrap();
438 assert_eq!(w.write_bits(u64::MAX, 64), Err(Error::BufferFull));
439 let n = w.finish();
440 let mut r = BitReader::new(&storage[..n]);
441 if offset > 0 {
442 assert_eq!(r.read_bits(offset).unwrap(), 0);
443 }
444 assert_eq!(r.read_bits(64).unwrap(), 0xDEAD_BEEF_0123_4567);
445 }
446 }
447
448 #[test]
449 fn reads_and_writes_spanning_several_bytes() {
450 let mut storage = [0u8; 4];
451 let mut w = BitWriter::new(&mut storage);
452 w.write_bits(0b1, 1).unwrap();
453 w.write_bits(0x1_2345, 17).unwrap();
454 w.write_bits(0x3FFF, 14).unwrap();
455 assert_eq!(w.bits_written(), 32);
456 assert_eq!(w.write_bool(true), Err(Error::BufferFull));
457 assert_eq!(w.finish(), 4);
458 let mut r = BitReader::new(&storage);
459 assert_eq!(r.read_bits(1).unwrap(), 1);
460 assert_eq!(r.read_bits(17).unwrap(), 0x1_2345);
461 assert_eq!(r.read_bits(14).unwrap(), 0x3FFF);
462 assert_eq!(r.read_bool(), Err(Error::UnexpectedEof));
463 }
464
465 #[test]
466 fn signed_fields() {
467 for n in [1u32, 2, 7, 8, 13, 63, 64] {
468 let min = if n == 64 {
469 i64::MIN
470 } else {
471 -(1i64 << (n - 1))
472 };
473 let max = if n == 64 {
474 i64::MAX
475 } else {
476 (1i64 << (n - 1)) - 1
477 };
478 for v in [min, max, 0, -1] {
479 let mut storage = [0u8; 8];
480 let mut w = BitWriter::new(&mut storage);
481 w.write_signed_bits(v, n).unwrap();
482 let bytes = w.finish();
483 let mut r = BitReader::new(&storage[..bytes]);
484 assert_eq!(r.read_signed_bits(n).unwrap(), v, "n={n} v={v}");
485 }
486 if n < 64 {
487 let mut storage = [0u8; 8];
488 let mut w = BitWriter::new(&mut storage);
489 assert_eq!(w.write_signed_bits(max + 1, n), Err(Error::BitOverflow));
490 assert_eq!(w.write_signed_bits(min - 1, n), Err(Error::BitOverflow));
491 }
492 }
493 assert_eq!(sign_extend(0b1, 1), -1);
494 assert_eq!(signed_to_bits(-1, 1), Some(1));
495 assert_eq!(signed_to_bits(1, 1), None);
496 }
497
498 #[test]
499 fn bit_capacity_saturates() {
500 assert_eq!(bit_capacity(0), 0);
501 assert_eq!(bit_capacity(3), 24);
502 assert_eq!(bit_capacity(usize::MAX), (usize::MAX / 8) * 8);
503 assert_eq!(bit_capacity(usize::MAX) % 8, 0);
504 }
505
506 #[test]
507 fn align_rounds_up_to_byte() {
508 let mut storage = [0u8; 2];
509 let mut w = BitWriter::new(&mut storage);
510 w.write_bits(0b101, 3).unwrap();
511 w.align_to_byte().unwrap();
512 w.write_bits(0xFF, 8).unwrap();
513 assert_eq!(w.finish(), 2);
514 assert_eq!(storage, [0b1010_0000, 0xFF]);
515 }
516}