lc3_codec/encoder/
buffer_writer.rs1#[allow(unused_imports)]
2use num_traits::real::Real;
3
4#[derive(Default)]
5pub struct BufferWriter {
6 pub bp: usize,
7 bp_side: u16,
8 mask_side: u8,
9}
10
11impl BufferWriter {
12 pub fn new(buf_len: usize) -> Self {
13 Self {
14 bp: 0,
15 bp_side: buf_len as u16 - 1,
16 mask_side: 1,
17 }
18 }
19 pub fn write_uint_backward(&mut self, buf: &mut [u8], mut val: usize, num_bits: usize) {
20 for _ in 0..num_bits {
21 let bit = (val as u16 & 1) as u8;
22 self.write_bool_backward(buf, bit != 0);
23 val >>= 1;
24 }
25 }
26
27 pub fn write_bool_backward(&mut self, buf: &mut [u8], bit: bool) {
28 if !bit {
29 buf[self.bp_side as usize] &= !self.mask_side;
30 } else {
31 buf[self.bp_side as usize] |= self.mask_side;
32 }
33
34 if self.mask_side == 0x80 {
35 self.mask_side = 1;
36 self.bp_side -= 1
37 } else {
38 self.mask_side <<= 1;
39 }
40 }
41
42 pub fn write_uint_forward(&mut self, buf: &mut [u8], val: u16, num_bits: usize) {
43 let mut mask: u8 = 0x80;
44 for _ in 0..num_bits {
45 let bit = val as u8 & mask; if bit == 0 {
47 buf[self.bp] &= !mask;
48 } else {
49 buf[self.bp] |= mask;
50 }
51 mask >>= 1;
52 }
53 }
54
55 pub fn write_byte_forward(&mut self, buf: &mut [u8], val: u8) {
56 buf[self.bp] = val;
57 self.bp += 1;
58 }
59
60 pub fn nbits_side_written(&self, nbits: usize) -> usize {
61 let value = nbits as i32 - (8 * self.bp_side as i32 + 8 - (self.mask_side as f64).log2() as i32);
62 if value < 0 {
63 panic!("nbits_side_written is negative: {}", value);
64 }
65 value as usize
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 extern crate std;
72 use super::*;
73
74 #[test]
75 fn buffer_writer_forward_and_backwards() {
76 let mut writer = BufferWriter::new(10);
77 let mut buf = [0; 10];
78
79 writer.write_bool_backward(&mut buf, true);
80 writer.write_byte_forward(&mut buf, 123);
81 writer.write_uint_backward(&mut buf, 22, 6);
82 writer.write_bool_backward(&mut buf, false);
83 assert_eq!(buf, [123, 0, 0, 0, 0, 0, 0, 0, 0, 45]);
87 }
88
89 #[test]
90 fn nbits_written_calc() {
91 let mut writer = BufferWriter::new(150);
92 writer.bp_side = 140;
93 writer.mask_side = 4;
94
95 let nbits_side_written = writer.nbits_side_written(1200);
96
97 assert_eq!(nbits_side_written, 74);
98 }
99}