]>
Commit | Line | Data |
---|---|---|
1 | //! Bitstream reader functionality. | |
2 | //! | |
3 | //! Bitstream reader operates on `&[u8]` and allows to read bits from the slice in different modes. | |
4 | //! | |
5 | //! # Examples | |
6 | //! | |
7 | //! Reading 17 bits from a bitstream: | |
8 | //! ``` | |
9 | //! use nihav_core::io::bitreader::{BitReader,BitReaderMode}; | |
10 | //! | |
11 | //! # use nihav_core::io::bitreader::BitReaderResult; | |
12 | //! # fn foo() -> BitReaderResult<u32> { | |
13 | //! let bits: [u8; 4] = [ 42, 43, 44, 45 ]; | |
14 | //! let mut br = BitReader::new(&bits, BitReaderMode::BE); | |
15 | //! let value = br.read(17)?; | |
16 | //! # Ok(value) | |
17 | //! # } | |
18 | //! ``` | |
19 | //! | |
20 | //! Reading some amount of bits and checking how many bits are left: | |
21 | //! ``` | |
22 | //! use nihav_core::io::bitreader::{BitReader,BitReaderMode}; | |
23 | //! | |
24 | //! # use nihav_core::io::bitreader::BitReaderResult; | |
25 | //! # fn foo() -> BitReaderResult<()> { | |
26 | //! let bits: [u8; 4] = [ 42, 43, 44, 45 ]; | |
27 | //! let mut br = BitReader::new(&bits, BitReaderMode::BE); | |
28 | //! let num_skip_bits = br.read(3)?; | |
29 | //! br.skip(num_skip_bits)?; | |
30 | //! println!("Now there are {} bits left to read.", br.left()); | |
31 | //! # Ok(()) | |
32 | //! # } | |
33 | //! ``` | |
34 | ||
35 | ||
36 | ||
37 | /// Bitstream reading modes. | |
38 | #[derive(Debug,Clone,Copy)] | |
39 | pub enum BitReaderMode { | |
40 | /// The stream is big endian MSB first. | |
41 | BE, | |
42 | /// The stream is little endian LSB first. | |
43 | LE, | |
44 | /// The stream is packed into 16-bit little-endian words MSB first. | |
45 | LE16MSB, | |
46 | /// The stream is packed into 32-bit little-endian words MSB first. | |
47 | LE32MSB, | |
48 | } | |
49 | ||
50 | /// A list specifying general bitstream reading errors. | |
51 | #[derive(Debug,Clone,Copy)] | |
52 | pub enum BitReaderError { | |
53 | /// The reader is at the end of bitstream. | |
54 | BitstreamEnd, | |
55 | /// The caller tried to read too many bits at once (e.g. 128). | |
56 | TooManyBitsRequested, | |
57 | /// Some argument is invalid. | |
58 | InvalidValue, | |
59 | } | |
60 | ||
61 | use self::BitReaderError::*; | |
62 | ||
63 | /// A specialised `Result` type for bitstream operations. | |
64 | pub type BitReaderResult<T> = Result<T, BitReaderError>; | |
65 | ||
66 | /// Bitstream reader. | |
67 | #[derive(Debug,Clone)] | |
68 | pub struct BitReader<'a> { | |
69 | cache: u64, | |
70 | bits: u8, | |
71 | pos: usize, | |
72 | src: &'a [u8], | |
73 | mode: BitReaderMode, | |
74 | } | |
75 | ||
76 | #[allow(clippy::identity_op)] | |
77 | impl<'a> BitReader<'a> { | |
78 | ||
79 | /// Constructs a new instance of bitstream reader. | |
80 | /// | |
81 | /// # Examples | |
82 | /// | |
83 | /// ``` | |
84 | /// use nihav_core::io::bitreader::{BitReader,BitReaderMode}; | |
85 | /// | |
86 | /// let bits: [u8; 4] = [ 42, 43, 44, 45 ]; | |
87 | /// let mut br = BitReader::new(&bits, BitReaderMode::BE); | |
88 | /// ``` | |
89 | pub fn new(src: &'a [u8], mode: BitReaderMode) -> Self { | |
90 | BitReader{ cache: 0, pos: 0, bits: 0, src, mode } | |
91 | } | |
92 | ||
93 | /// Returns the data bitstream reader uses. | |
94 | pub fn get_data(&self) -> &'a [u8] { self.src } | |
95 | ||
96 | /// Reports the current bit position in the bitstream (usually simply the number of bits read so far). | |
97 | pub fn tell(&self) -> usize { | |
98 | self.pos * 8 - (self.bits as usize) | |
99 | } | |
100 | ||
101 | /// Reports the amount of bits left until the end of the bitstream. | |
102 | pub fn left(&self) -> isize { | |
103 | ((self.src.len() as isize) - (self.pos as isize)) * 8 + (self.bits as isize) | |
104 | } | |
105 | ||
106 | fn fill32be(&mut self, src: &[u8]) { | |
107 | let nw = (u32::from(src[0]) << 24) | | |
108 | (u32::from(src[1]) << 16) | | |
109 | (u32::from(src[2]) << 8) | | |
110 | (u32::from(src[3]) << 0); | |
111 | self.cache |= u64::from(nw) << (32 - self.bits); | |
112 | } | |
113 | ||
114 | fn fill32le16(&mut self, src: &[u8]) { | |
115 | let nw = (u32::from(src[1]) << 24) | | |
116 | (u32::from(src[0]) << 16) | | |
117 | (u32::from(src[3]) << 8) | | |
118 | (u32::from(src[2]) << 0); | |
119 | self.cache |= u64::from(nw) << (32 - self.bits); | |
120 | } | |
121 | ||
122 | fn fill32le32(&mut self, src: &[u8], lsb: bool) { | |
123 | let nw = (u32::from(src[3]) << 24) | | |
124 | (u32::from(src[2]) << 16) | | |
125 | (u32::from(src[1]) << 8) | | |
126 | (u32::from(src[0]) << 0); | |
127 | if lsb { | |
128 | self.cache |= u64::from(nw) << self.bits; | |
129 | } else { | |
130 | self.cache |= u64::from(nw) << (32 - self.bits); | |
131 | } | |
132 | } | |
133 | ||
134 | #[inline(always)] | |
135 | fn refill(&mut self) -> BitReaderResult<()> { | |
136 | if self.pos >= self.src.len() { return Err(BitstreamEnd) } | |
137 | while self.bits <= 32 { | |
138 | if self.pos + 4 <= self.src.len() { | |
139 | let buf = &self.src[self.pos..]; | |
140 | match self.mode { | |
141 | BitReaderMode::BE => self.fill32be (buf), | |
142 | BitReaderMode::LE16MSB => self.fill32le16(buf), | |
143 | BitReaderMode::LE => self.fill32le32(buf, true), | |
144 | BitReaderMode::LE32MSB => self.fill32le32(buf, false), | |
145 | } | |
146 | self.pos += 4; | |
147 | self.bits += 32; | |
148 | } else { | |
149 | let mut buf: [u8; 4] = [0, 0, 0, 0]; | |
150 | let mut newbits: u8 = 0; | |
151 | for out in buf.iter_mut().take(3) { | |
152 | if self.pos < self.src.len() { | |
153 | *out = self.src[self.pos]; | |
154 | self.pos += 1; | |
155 | newbits += 8; | |
156 | } | |
157 | } | |
158 | if newbits == 0 { break; } | |
159 | match self.mode { | |
160 | BitReaderMode::BE => self.fill32be (&buf), | |
161 | BitReaderMode::LE16MSB => self.fill32le16(&buf), | |
162 | BitReaderMode::LE => self.fill32le32(&buf, true), | |
163 | BitReaderMode::LE32MSB => self.fill32le32(&buf, false), | |
164 | } | |
165 | self.bits += newbits; | |
166 | } | |
167 | } | |
168 | Ok(()) | |
169 | } | |
170 | ||
171 | #[inline(always)] | |
172 | fn read_cache(&mut self, nbits: u8) -> u32 { | |
173 | let res = match self.mode { | |
174 | BitReaderMode::LE => ((1u64 << nbits) - 1) & self.cache, | |
175 | _ => self.cache >> (64 - nbits), | |
176 | }; | |
177 | res as u32 | |
178 | } | |
179 | ||
180 | fn read_cache_s(&mut self, nbits: u8) -> i32 { | |
181 | let res = match self.mode { | |
182 | BitReaderMode::LE => ((self.cache as i64) << (64 - nbits)) >> (64 - nbits), | |
183 | _ => (self.cache as i64) >> (64 - nbits), | |
184 | }; | |
185 | res as i32 | |
186 | } | |
187 | ||
188 | #[inline(always)] | |
189 | fn skip_cache(&mut self, nbits: u8) { | |
190 | match self.mode { | |
191 | BitReaderMode::LE => self.cache >>= nbits, | |
192 | _ => self.cache <<= nbits, | |
193 | }; | |
194 | self.bits -= nbits; | |
195 | } | |
196 | ||
197 | #[inline(always)] | |
198 | fn reset_cache(&mut self) { | |
199 | self.bits = 0; | |
200 | self.cache = 0; | |
201 | } | |
202 | ||
203 | /// Reads the specified amount of bits as an unsigned value. | |
204 | /// | |
205 | /// The amount should fit into 32 bits, if you need more then | |
206 | /// you should read it as several parts. If the amount of bits | |
207 | /// requested to read is larger than the amount of bits left the | |
208 | /// call will return [`BitstreamEnd`]. | |
209 | /// | |
210 | /// # Examples | |
211 | /// | |
212 | /// ``` | |
213 | /// use nihav_core::io::bitreader::{BitReader,BitReaderMode}; | |
214 | /// | |
215 | /// # use nihav_core::io::bitreader::BitReaderResult; | |
216 | /// # fn foo() -> BitReaderResult<u32> { | |
217 | /// let bits: [u8; 4] = [ 42, 43, 44, 45 ]; | |
218 | /// let mut br = BitReader::new(&bits, BitReaderMode::BE); | |
219 | /// let value = br.read(17)?; | |
220 | /// # Ok(value) | |
221 | /// # } | |
222 | /// ``` | |
223 | /// | |
224 | /// [`BitstreamEnd`]: ./enum.BitReaderError.html#variant.BitstreamEnd | |
225 | #[inline(always)] | |
226 | pub fn read(&mut self, nbits: u8) -> BitReaderResult<u32> { | |
227 | if nbits == 0 { return Ok(0) } | |
228 | if nbits > 32 { return Err(TooManyBitsRequested) } | |
229 | if self.bits < nbits { | |
230 | if let Err(err) = self.refill() { return Err(err) } | |
231 | if self.bits < nbits { return Err(BitstreamEnd) } | |
232 | } | |
233 | let res = self.read_cache(nbits); | |
234 | self.skip_cache(nbits); | |
235 | Ok(res) | |
236 | } | |
237 | ||
238 | /// Reads the specified amount of bits as a signed value. | |
239 | /// | |
240 | /// Beside signedness it behaves the same as [`read`]. | |
241 | /// | |
242 | /// [`read`]: #method.read | |
243 | pub fn read_s(&mut self, nbits: u8) -> BitReaderResult<i32> { | |
244 | if nbits == 0 || nbits > 32 { return Err(TooManyBitsRequested) } | |
245 | if self.bits < nbits { | |
246 | if let Err(err) = self.refill() { return Err(err) } | |
247 | if self.bits < nbits { return Err(BitstreamEnd) } | |
248 | } | |
249 | let res = self.read_cache_s(nbits); | |
250 | self.skip_cache(nbits); | |
251 | Ok(res) | |
252 | } | |
253 | ||
254 | /// Reads single bit from the stream and interprets it as a boolean value. | |
255 | #[inline(always)] | |
256 | pub fn read_bool(&mut self) -> BitReaderResult<bool> { | |
257 | if self.bits < 1 { | |
258 | if let Err(err) = self.refill() { return Err(err) } | |
259 | if self.bits < 1 { return Err(BitstreamEnd) } | |
260 | } | |
261 | let res = self.read_cache(1); | |
262 | self.skip_cache(1); | |
263 | Ok(res == 1) | |
264 | } | |
265 | ||
266 | /// Retrieves the next bits from the stream without advancing. | |
267 | /// | |
268 | /// If the bitstream is shorter than the amount of bits requested the result is padded with zeroes. | |
269 | /// | |
270 | /// # Examples | |
271 | /// | |
272 | /// ``` | |
273 | /// use nihav_core::io::bitreader::{BitReader,BitReaderMode}; | |
274 | /// | |
275 | /// # use nihav_core::io::bitreader::BitReaderResult; | |
276 | /// # fn foo() -> BitReaderResult<u32> { | |
277 | /// let bits: [u8; 4] = [ 42, 43, 44, 45 ]; | |
278 | /// let mut br = BitReader::new(&bits, BitReaderMode::BE); | |
279 | /// let peek_value = br.peek(8); // this should return 42 | |
280 | /// let value = br.read(8)?; // also 42 | |
281 | /// # Ok(value) | |
282 | /// # } | |
283 | /// ``` | |
284 | #[inline(always)] | |
285 | pub fn peek(&mut self, nbits: u8) -> u32 { | |
286 | if nbits > 32 { return 0 } | |
287 | if self.bits < nbits { let _ = self.refill(); } | |
288 | self.read_cache(nbits) | |
289 | } | |
290 | ||
291 | /// Skips the requested amount of bits. | |
292 | /// | |
293 | /// The amount of bits to skip can be arbitrary large. | |
294 | /// If it skips more bits than there are actually in the stream the call will return [`BitstreamEnd`] | |
295 | /// | |
296 | /// [`read`]: #method.read | |
297 | /// [`BitstreamEnd`]: ./enum.BitReaderError.html#variant.BitstreamEnd | |
298 | #[inline(always)] | |
299 | pub fn skip(&mut self, nbits: u32) -> BitReaderResult<()> { | |
300 | if u32::from(self.bits) >= nbits { | |
301 | self.skip_cache(nbits as u8); | |
302 | return Ok(()); | |
303 | } | |
304 | let mut skip_bits = nbits - u32::from(self.bits); | |
305 | self.reset_cache(); | |
306 | self.pos += ((skip_bits / 32) * 4) as usize; | |
307 | skip_bits &= 0x1F; | |
308 | if skip_bits > 0 { | |
309 | self.refill()?; | |
310 | if u32::from(self.bits) < skip_bits { | |
311 | return Err(BitstreamEnd); | |
312 | } | |
313 | self.skip_cache(skip_bits as u8); | |
314 | } | |
315 | Ok(()) | |
316 | } | |
317 | ||
318 | /// Seeks to the absolute bit position in the stream. | |
319 | /// If the requested position lies after the bitstream end the function returns [`TooManyBitsRequested`]. | |
320 | /// | |
321 | /// # Examples | |
322 | /// | |
323 | /// ``` | |
324 | /// use nihav_core::io::bitreader::{BitReader,BitReaderMode}; | |
325 | /// | |
326 | /// # use nihav_core::io::bitreader::BitReaderResult; | |
327 | /// # fn foo() -> BitReaderResult<u32> { | |
328 | /// let bits: [u8; 4] = [ 42, 43, 44, 45 ]; | |
329 | /// let mut br = BitReader::new(&bits, BitReaderMode::BE); | |
330 | /// br.seek(16)?; | |
331 | /// let value = br.read(8)?; // this should return 44 | |
332 | /// # Ok(value) | |
333 | /// # } | |
334 | /// ``` | |
335 | /// | |
336 | /// [`TooManyBitsRequested`]: ./enum.BitReaderError.html#variant.TooManyBitsRequested | |
337 | pub fn seek(&mut self, nbits: u32) -> BitReaderResult<()> { | |
338 | if ((nbits + 7) >> 3) as usize > self.src.len() { return Err(TooManyBitsRequested); } | |
339 | self.reset_cache(); | |
340 | self.pos = ((nbits / 32) * 4) as usize; | |
341 | self.skip(nbits & 0x1F) | |
342 | } | |
343 | ||
344 | /// Aligns the bit position to the next byte boundary. If already at byte boundary the function does nothing. | |
345 | /// | |
346 | /// # Examples | |
347 | /// | |
348 | /// ``` | |
349 | /// use nihav_core::io::bitreader::{BitReader,BitReaderMode}; | |
350 | /// | |
351 | /// # use nihav_core::io::bitreader::BitReaderResult; | |
352 | /// # fn foo() -> BitReaderResult<()> { | |
353 | /// let bits: [u8; 4] = [ 42, 43, 44, 45 ]; | |
354 | /// let mut br = BitReader::new(&bits, BitReaderMode::BE); | |
355 | /// br.skip(17)?; // now reader is at bit position 17 | |
356 | /// br.align(); // now reader is at bit position 24 | |
357 | /// br.align(); // now reader is still at bit position 24 | |
358 | /// # Ok(()) | |
359 | /// # } | |
360 | /// ``` | |
361 | pub fn align(&mut self) { | |
362 | let pos = self.bits & 7; | |
363 | if pos != 0 { | |
364 | self.skip_cache(pos); | |
365 | } | |
366 | } | |
367 | } | |
368 | ||
369 | /// Returns a variable with `len` amount of low bits in reverse order. | |
370 | /// | |
371 | /// # Examples | |
372 | /// ``` | |
373 | /// use nihav_core::io::bitreader::reverse_bits; | |
374 | /// reverse_bits(0b010101, 6); // the result should be 0b101010 | |
375 | /// ``` | |
376 | pub fn reverse_bits(inval: u32, len: u8) -> u32 { | |
377 | if len == 0 { return 0; } | |
378 | const REV_TAB: [u8; 16] = [ | |
379 | 0b0000, 0b1000, 0b0100, 0b1100, 0b0010, 0b1010, 0b0110, 0b1110, | |
380 | 0b0001, 0b1001, 0b0101, 0b1101, 0b0011, 0b1011, 0b0111, 0b1111, | |
381 | ]; | |
382 | ||
383 | let mut ret = 0; | |
384 | let mut val = inval; | |
385 | for _ in 0..8 { | |
386 | ret = (ret << 4) | u32::from(REV_TAB[(val & 0xF) as usize]); | |
387 | val >>= 4; | |
388 | } | |
389 | ret >> (32 - len) | |
390 | } | |
391 | ||
392 | #[cfg(test)] | |
393 | mod test { | |
394 | use super::*; | |
395 | ||
396 | #[test] | |
397 | fn br_works() { | |
398 | const DATA: [u8; 18] = [0b00011011; 18]; | |
399 | let src = &DATA; | |
400 | let mut br = BitReader::new(src, BitReaderMode::LE16MSB); | |
401 | ||
402 | for _ in 0..8 { | |
403 | assert_eq!(br.read(16).unwrap(), 0x1B1B); | |
404 | } | |
405 | const DATA2: [u8; 1] = [ 0b00011011 ]; | |
406 | let src = &DATA2; | |
407 | let mut br = BitReader::new(src, BitReaderMode::LE); | |
408 | assert_eq!(br.read_s(5).unwrap(), -5); | |
409 | } | |
410 | } |