lc3_codec/decoder/
buffer_reader.rs1use byteorder::{BigEndian, ByteOrder};
2
3#[derive(Debug)]
4pub enum BufferReaderError {
5 ReadByteOutOfBounds(usize),
6 ReadU24OutOfBounds(usize),
7 BigEndianBitReaderReadUsizeNumBitsOutOfRange(usize, usize),
8 BigEndianBitReaderReadBoolOutOfRange(usize),
9}
10
11#[derive(Default)]
12pub struct BufferReader {
13 head_byte_cursor: usize,
14 tail_bit_cursor: usize,
15}
16
17impl BufferReader {
23 pub fn new() -> Self {
24 Self::default()
25 }
26
27 pub fn new_at(head_byte_cursor: usize, tail_bit_cursor: usize) -> Self {
28 Self {
29 head_byte_cursor,
30 tail_bit_cursor,
31 }
32 }
33
34 pub fn get_tail_bit_cursor(&self) -> usize {
35 self.tail_bit_cursor
36 }
37
38 pub fn get_head_byte_cursor(&self) -> usize {
39 self.head_byte_cursor
40 }
41
42 pub fn read_head_byte(&mut self, buf: &[u8]) -> Result<u8, BufferReaderError> {
43 match buf.get(self.head_byte_cursor) {
44 Some(byte) => {
45 self.head_byte_cursor += 1;
46 Ok(*byte)
47 }
48 None => Err(BufferReaderError::ReadByteOutOfBounds(self.head_byte_cursor)),
49 }
50 }
51
52 pub fn read_head_u24(&mut self, buf: &[u8]) -> Result<u32, BufferReaderError> {
53 if self.head_byte_cursor + 2 < buf.len() {
54 let value = BigEndian::read_u24(&buf[self.head_byte_cursor..]);
55 self.head_byte_cursor += 3;
56 Ok(value)
57 } else {
58 Err(BufferReaderError::ReadU24OutOfBounds(self.head_byte_cursor))
59 }
60 }
61
62 pub fn read_tail_usize(&mut self, buf: &[u8], num_bits: usize) -> Result<usize, BufferReaderError> {
64 let byte_index = self.tail_bit_cursor / 8;
65 let bit_index = self.tail_bit_cursor % 8;
66
67 let bits_left = 8 - bit_index;
68 let add_bytes = if num_bits > bits_left && num_bits < 8 { 2 } else { 1 };
69 let num_bytes = num_bits / 8 + add_bytes;
70
71 if (buf.len() as i32 - self.head_byte_cursor as i32 - byte_index as i32 - num_bytes as i32) < 0 {
72 return Err(BufferReaderError::BigEndianBitReaderReadUsizeNumBitsOutOfRange(
73 num_bits, bit_index,
74 ));
75 }
76
77 let from_index = buf.len() - byte_index - num_bytes;
78 let to_index = from_index + num_bytes;
79 let slice = &buf[from_index..to_index];
80
81 let mut value = match num_bytes {
82 1 => slice[0] as u32,
83 2 => BigEndian::read_u16(slice) as u32,
84 3 => BigEndian::read_u24(slice) as u32,
85 4 => BigEndian::read_u32(slice),
86 _ => 0_u32,
87 };
88
89 let shift_by = 32 - num_bits - bit_index;
91 value <<= shift_by;
92 value >>= shift_by + bit_index;
93
94 self.tail_bit_cursor += num_bits;
95 Ok(value as usize)
96 }
97
98 pub fn read_tail_bool(&mut self, buf: &[u8]) -> Result<bool, BufferReaderError> {
99 let byte_index = self.tail_bit_cursor / 8;
100 let bit_index = self.tail_bit_cursor % 8;
101
102 if (buf.len() as i32 - self.head_byte_cursor as i32 - byte_index as i32 + 2) < 0 {
104 return Err(BufferReaderError::BigEndianBitReaderReadBoolOutOfRange(bit_index));
105 }
106
107 let from_index = buf.len() - byte_index - 1;
108 let mut byte = buf[from_index];
109 byte <<= 7 - bit_index;
110 byte >>= 7;
111
112 self.tail_bit_cursor += 1;
113 Ok(byte == 1)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 extern crate std;
120 use super::*;
121
122 #[test]
123 fn read_5_bits_over_byte_boundary_unto_usize() {
124 let buf = [248, 52, 26, 166, 60];
125 let mut reader = BufferReader::new();
126 reader.tail_bit_cursor = 23;
127 let value1 = reader.read_tail_usize(&buf, 5).unwrap();
128 assert_eq!(8, value1);
129 }
130
131 #[test]
132 fn read_multiple_values_from_bigendian_bitstream() {
133 let buf: [u8; 2] = [0b0001_1011, 0b0000_1100];
135 let mut reader = BufferReader::new();
136
137 let value1 = reader.read_tail_usize(&buf, 3).unwrap();
139 let value2 = reader.read_tail_usize(&buf, 8).unwrap();
141
142 assert_eq!(4, value1);
143 assert_eq!(97, value2);
144 }
145
146 #[test]
147 fn read_bool_from_bigendian_bitstream() {
148 let byte = 0b0100_1000;
149 let buf: [u8; 1] = [byte];
150 let mut reader = BufferReader::new();
151
152 let value0 = reader.read_tail_bool(&buf).unwrap();
153 let value1 = reader.read_tail_bool(&buf).unwrap();
154 let value2 = reader.read_tail_bool(&buf).unwrap();
155 let value3 = reader.read_tail_bool(&buf).unwrap();
156 let value4 = reader.read_tail_bool(&buf).unwrap();
157 let value5 = reader.read_tail_bool(&buf).unwrap();
158 let value6 = reader.read_tail_bool(&buf).unwrap();
159 let value7 = reader.read_tail_bool(&buf).unwrap();
160
161 assert_eq!(false, value0);
162 assert_eq!(false, value1);
163 assert_eq!(false, value2);
164 assert_eq!(true, value3);
165 assert_eq!(false, value4);
166 assert_eq!(false, value5);
167 assert_eq!(true, value6);
168 assert_eq!(false, value7);
169 }
170}