1//! `BitStreamReader` API
2//!
3//! This module provides an interface to read and write bits (and bytes) for
4//! huffman
5
6pub struct BitStreamReader<'src>
7{
8 // buffer from which we are pulling in bits from
9 // used in decompression.
10 pub src: &'src [u8],
11 // position in our buffer,
12 pub position: usize,
13 pub bits_left: u8,
14 pub buffer: u64,
15 pub over_read: usize
16}
17
18impl<'src> BitStreamReader<'src>
19{
20 /// Create a new `BitStreamReader` instance
21 ///
22 /// # Expectations
23 /// The buffer must be padded with fill bytes in the end,
24 /// if not, this becomes UB in the refill phase.
25 pub fn new(in_buffer: &'src [u8]) -> BitStreamReader<'src>
26 {
27 BitStreamReader {
28 bits_left: 0,
29 buffer: 0,
30 src: in_buffer,
31 position: 0,
32 over_read: 0
33 }
34 }
35 /// Refill the bitstream ensuring the buffer has bits between
36 /// 56 and 63.
37 ///
38 #[inline(always)]
39 pub fn refill(&mut self)
40 {
41 /*
42 * The refill always guarantees refills between 56-63
43 *
44 * Bits stored will never go above 63 and if bits are in the range 56-63 no refills occur.
45 */
46 let mut buf = [0; 8];
47
48 match self.src.get(self.position..self.position + 8)
49 {
50 Some(bytes) =>
51 {
52 buf.copy_from_slice(bytes);
53 // create a u64 from an array of u8's
54 let new_buffer = u64::from_le_bytes(buf);
55 // num indicates how many bytes we actually consumed.
56 let num = 63 ^ self.bits_left;
57 // offset position
58 self.position += (num >> 3) as usize;
59 // shift number of bits
60 self.buffer |= new_buffer << self.bits_left;
61 // update bits left
62 // bits left are now between 56-63
63 self.bits_left |= 56;
64 }
65 None => self.refill_slow()
66 }
67 }
68 #[inline(always)]
69 pub fn refill_inner_loop(&mut self)
70 {
71 /*
72 * The refill always guarantees refills between 56-63
73 *
74 * Bits stored will never go above 63 and if bits are in the range 56-63 no refills occur.
75 */
76 let mut buf = [0; 8];
77
78 if let Some(bytes) = self.src.get(self.position..self.position + 8)
79 {
80 {
81 buf.copy_from_slice(bytes);
82 // create a u64 from an array of u8's
83 let new_buffer = u64::from_le_bytes(buf);
84 // num indicates how many bytes we actually consumed.
85 let num = 63 ^ self.bits_left;
86 // offset position
87 self.position += (num >> 3) as usize;
88 // shift number of bits
89 self.buffer |= new_buffer << self.bits_left;
90 // update bits left
91 // bits left are now between 56-63
92 self.bits_left |= 56;
93 }
94 }
95 }
96 #[inline(never)]
97 fn refill_slow(&mut self)
98 {
99 let bytes = &self.src[self.position..];
100
101 for byte in bytes
102 {
103 if self.bits_left >= 56
104 {
105 break;
106 }
107
108 self.buffer |= u64::from(*byte) << self.bits_left;
109 self.bits_left += 8;
110 self.position += 1;
111 }
112 while self.bits_left < 56
113 {
114 self.bits_left += 8;
115 self.over_read += 1;
116 }
117 }
118
119 #[inline(always)]
120 pub fn peek_bits<const LOOKAHEAD: usize>(&self) -> usize
121 {
122 debug_assert!(self.bits_left >= LOOKAHEAD as u8);
123 (self.buffer & ((1 << LOOKAHEAD) - 1)) as usize
124 }
125 #[inline(always)]
126 pub fn peek_var_bits(&self, lookahead: usize) -> usize
127 {
128 debug_assert!(self.bits_left >= lookahead as u8);
129 (self.buffer & ((1 << lookahead) - 1)) as usize
130 }
131
132 #[inline(always)]
133 pub fn get_bits(&mut self, num_bits: u8) -> u64
134 {
135 debug_assert!(self.bits_left >= num_bits);
136
137 let mask = (1_u64 << num_bits) - 1;
138
139 let value = self.buffer & mask;
140
141 self.buffer >>= num_bits;
142
143 self.bits_left -= num_bits;
144
145 value
146 }
147 /// Get number of bits left in the bit buffer.
148 pub const fn get_bits_left(&self) -> u8
149 {
150 self.bits_left
151 }
152 /// Get position the stream is in this buffer
153 /// Or alternatively, number of bits read.
154 pub fn get_position(&self) -> usize
155 {
156 self.position
157 .saturating_sub(usize::from(self.bits_left >> 3))
158 }
159
160 /// Reset buffer and bits left to zero.
161 pub fn reset(&mut self)
162 {
163 self.buffer = 0;
164 self.bits_left = 0;
165 }
166 /// Return true if the bit buffer can satisfy
167 /// `bits` read without refilling,
168 pub const fn has(&self, bits: u8) -> bool
169 {
170 self.bits_left >= bits
171 }
172
173 #[inline(always)]
174 pub fn drop_bits(&mut self, bits: u8)
175 {
176 debug_assert!(self.bits_left >= bits);
177 self.bits_left -= bits;
178 self.buffer >>= bits;
179 }
180 /// Return the remaining bytes in this stream.
181 ///
182 /// This does not consider bits in the bit-buffer hence
183 /// may not be accurate
184 pub const fn remaining_bytes(&self) -> usize
185 {
186 self.src.len().saturating_sub(self.position)
187 }
188}
189