]>
Commit | Line | Data |
---|---|---|
26aa3dd3 KS |
1 | //! Bitstream reader functionality. |
2 | //! | |
155c91e4 | 3 | //! Bitstream reader operates on `&[u8]` and allows to read bits from the slice in different modes. |
26aa3dd3 KS |
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; | |
155c91e4 | 12 | //! # fn foo() -> BitReaderResult<u32> { |
26aa3dd3 KS |
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; | |
155c91e4 | 25 | //! # fn foo() -> BitReaderResult<()> { |
26aa3dd3 KS |
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. | |
91f5ad84 | 38 | #[derive(Debug,Clone,Copy)] |
90aa4e6b | 39 | pub enum BitReaderMode { |
26aa3dd3 | 40 | /// The stream is big endian MSB first. |
90aa4e6b | 41 | BE, |
26aa3dd3 | 42 | /// The stream is little endian LSB first. |
a961f92b | 43 | LE, |
26aa3dd3 | 44 | /// The stream is packed into 16-bit little-endian words MSB first. |
a961f92b | 45 | LE16MSB, |
26aa3dd3 | 46 | /// The stream is packed into 32-bit little-endian words MSB first. |
a961f92b | 47 | LE32MSB, |
90aa4e6b KS |
48 | } |
49 | ||
26aa3dd3 | 50 | /// A list specifying general bitstream reading errors. |
91f5ad84 | 51 | #[derive(Debug,Clone,Copy)] |
90aa4e6b | 52 | pub enum BitReaderError { |
26aa3dd3 | 53 | /// The reader is at the end of bitstream. |
90aa4e6b | 54 | BitstreamEnd, |
26aa3dd3 | 55 | /// The caller tried to read too many bits at once (e.g. 128). |
90aa4e6b | 56 | TooManyBitsRequested, |
26aa3dd3 | 57 | /// Some argument is invalid. |
a961f92b | 58 | InvalidValue, |
90aa4e6b KS |
59 | } |
60 | ||
61 | use self::BitReaderError::*; | |
62 | ||
26aa3dd3 | 63 | /// A specialised `Result` type for bitstream operations. |
a961f92b | 64 | pub type BitReaderResult<T> = Result<T, BitReaderError>; |
90aa4e6b | 65 | |
26aa3dd3 | 66 | /// Bitstream reader. |
91f5ad84 | 67 | #[derive(Debug,Clone)] |
90aa4e6b KS |
68 | pub struct BitReader<'a> { |
69 | cache: u64, | |
70 | bits: u8, | |
71 | pos: usize, | |
90aa4e6b KS |
72 | src: &'a [u8], |
73 | mode: BitReaderMode, | |
74 | } | |
75 | ||
e243ceb4 | 76 | #[allow(clippy::identity_op)] |
90aa4e6b KS |
77 | impl<'a> BitReader<'a> { |
78 | ||
26aa3dd3 | 79 | /// Constructs a new instance of bitstream reader. |
155c91e4 | 80 | /// |
26aa3dd3 KS |
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 | /// ``` | |
fa90ccfb KS |
89 | pub fn new(src: &'a [u8], mode: BitReaderMode) -> Self { |
90 | BitReader{ cache: 0, pos: 0, bits: 0, src, mode } | |
90aa4e6b KS |
91 | } |
92 | ||
bebc390b KS |
93 | /// Returns the data bitstream reader uses. |
94 | pub fn get_data(&self) -> &'a [u8] { self.src } | |
95 | ||
26aa3dd3 | 96 | /// Reports the current bit position in the bitstream (usually simply the number of bits read so far). |
90aa4e6b KS |
97 | pub fn tell(&self) -> usize { |
98 | self.pos * 8 - (self.bits as usize) | |
99 | } | |
100 | ||
26aa3dd3 | 101 | /// Reports the amount of bits left until the end of the bitstream. |
90aa4e6b | 102 | pub fn left(&self) -> isize { |
fa90ccfb | 103 | ((self.src.len() as isize) - (self.pos as isize)) * 8 + (self.bits as isize) |
90aa4e6b KS |
104 | } |
105 | ||
106 | fn fill32be(&mut self, src: &[u8]) { | |
e243ceb4 KS |
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); | |
90aa4e6b KS |
112 | } |
113 | ||
8ab3904c | 114 | fn fill32le16(&mut self, src: &[u8]) { |
e243ceb4 KS |
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); | |
90aa4e6b KS |
120 | } |
121 | ||
8ab3904c | 122 | fn fill32le32(&mut self, src: &[u8], lsb: bool) { |
e243ceb4 KS |
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); | |
8ab3904c | 127 | if lsb { |
e243ceb4 | 128 | self.cache |= u64::from(nw) << self.bits; |
8ab3904c | 129 | } else { |
e243ceb4 | 130 | self.cache |= u64::from(nw) << (32 - self.bits); |
8ab3904c | 131 | } |
90aa4e6b KS |
132 | } |
133 | ||
83b49341 | 134 | #[inline(always)] |
90aa4e6b | 135 | fn refill(&mut self) -> BitReaderResult<()> { |
fa90ccfb | 136 | if self.pos >= self.src.len() { return Err(BitstreamEnd) } |
90aa4e6b | 137 | while self.bits <= 32 { |
fa90ccfb | 138 | if self.pos + 4 <= self.src.len() { |
90aa4e6b KS |
139 | let buf = &self.src[self.pos..]; |
140 | match self.mode { | |
a961f92b | 141 | BitReaderMode::BE => self.fill32be (buf), |
8ab3904c KS |
142 | BitReaderMode::LE16MSB => self.fill32le16(buf), |
143 | BitReaderMode::LE => self.fill32le32(buf, true), | |
144 | BitReaderMode::LE32MSB => self.fill32le32(buf, false), | |
90aa4e6b KS |
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; | |
e243ceb4 | 151 | for out in buf.iter_mut().take(3) { |
fa90ccfb | 152 | if self.pos < self.src.len() { |
e243ceb4 KS |
153 | *out = self.src[self.pos]; |
154 | self.pos += 1; | |
90aa4e6b KS |
155 | newbits += 8; |
156 | } | |
157 | } | |
158 | if newbits == 0 { break; } | |
159 | match self.mode { | |
a961f92b | 160 | BitReaderMode::BE => self.fill32be (&buf), |
8ab3904c KS |
161 | BitReaderMode::LE16MSB => self.fill32le16(&buf), |
162 | BitReaderMode::LE => self.fill32le32(&buf, true), | |
163 | BitReaderMode::LE32MSB => self.fill32le32(&buf, false), | |
90aa4e6b KS |
164 | } |
165 | self.bits += newbits; | |
166 | } | |
167 | } | |
168 | Ok(()) | |
169 | } | |
170 | ||
83b49341 | 171 | #[inline(always)] |
90aa4e6b KS |
172 | fn read_cache(&mut self, nbits: u8) -> u32 { |
173 | let res = match self.mode { | |
a961f92b | 174 | BitReaderMode::LE => ((1u64 << nbits) - 1) & self.cache, |
e243ceb4 | 175 | _ => self.cache >> (64 - nbits), |
90aa4e6b KS |
176 | }; |
177 | res as u32 | |
178 | } | |
179 | ||
a961f92b KS |
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 | ||
83b49341 | 188 | #[inline(always)] |
90aa4e6b KS |
189 | fn skip_cache(&mut self, nbits: u8) { |
190 | match self.mode { | |
a961f92b KS |
191 | BitReaderMode::LE => self.cache >>= nbits, |
192 | _ => self.cache <<= nbits, | |
90aa4e6b KS |
193 | }; |
194 | self.bits -= nbits; | |
195 | } | |
196 | ||
83b49341 | 197 | #[inline(always)] |
90aa4e6b KS |
198 | fn reset_cache(&mut self) { |
199 | self.bits = 0; | |
200 | self.cache = 0; | |
201 | } | |
202 | ||
26aa3dd3 KS |
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; | |
155c91e4 | 216 | /// # fn foo() -> BitReaderResult<u32> { |
26aa3dd3 KS |
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 | |
83b49341 | 225 | #[inline(always)] |
90aa4e6b | 226 | pub fn read(&mut self, nbits: u8) -> BitReaderResult<u32> { |
a961f92b | 227 | if nbits == 0 { return Ok(0) } |
90aa4e6b KS |
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); | |
a961f92b KS |
235 | Ok(res) |
236 | } | |
237 | ||
26aa3dd3 KS |
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 | |
a961f92b KS |
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) | |
90aa4e6b KS |
252 | } |
253 | ||
26aa3dd3 | 254 | /// Reads single bit from the stream and interprets it as a boolean value. |
83b49341 | 255 | #[inline(always)] |
0a1d94d9 KS |
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 | ||
26aa3dd3 KS |
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; | |
155c91e4 | 276 | /// # fn foo() -> BitReaderResult<u32> { |
26aa3dd3 KS |
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 | /// ``` | |
83b49341 | 284 | #[inline(always)] |
90aa4e6b KS |
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 | ||
26aa3dd3 KS |
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 | |
83b49341 | 298 | #[inline(always)] |
90aa4e6b | 299 | pub fn skip(&mut self, nbits: u32) -> BitReaderResult<()> { |
e243ceb4 | 300 | if u32::from(self.bits) >= nbits { |
90aa4e6b KS |
301 | self.skip_cache(nbits as u8); |
302 | return Ok(()); | |
303 | } | |
e243ceb4 | 304 | let mut skip_bits = nbits - u32::from(self.bits); |
90aa4e6b KS |
305 | self.reset_cache(); |
306 | self.pos += ((skip_bits / 32) * 4) as usize; | |
e243ceb4 | 307 | skip_bits &= 0x1F; |
90aa4e6b KS |
308 | self.refill()?; |
309 | if skip_bits > 0 { | |
310 | self.skip_cache(skip_bits as u8); | |
311 | } | |
312 | Ok(()) | |
313 | } | |
314 | ||
26aa3dd3 KS |
315 | /// Seeks to the absolute bit position in the stream. |
316 | /// If the requested position lies after the bitstream end the function returns [`TooManyBitsRequested`]. | |
317 | /// | |
318 | /// # Examples | |
319 | /// | |
320 | /// ``` | |
321 | /// use nihav_core::io::bitreader::{BitReader,BitReaderMode}; | |
322 | /// | |
323 | /// # use nihav_core::io::bitreader::BitReaderResult; | |
155c91e4 | 324 | /// # fn foo() -> BitReaderResult<u32> { |
26aa3dd3 KS |
325 | /// let bits: [u8; 4] = [ 42, 43, 44, 45 ]; |
326 | /// let mut br = BitReader::new(&bits, BitReaderMode::BE); | |
327 | /// br.seek(16)?; | |
328 | /// let value = br.read(8)?; // this should return 44 | |
329 | /// # Ok(value) | |
330 | /// # } | |
331 | /// ``` | |
332 | /// | |
333 | /// [`TooManyBitsRequested`]: ./enum.BitReaderError.html#variant.TooManyBitsRequested | |
90aa4e6b | 334 | pub fn seek(&mut self, nbits: u32) -> BitReaderResult<()> { |
fa90ccfb | 335 | if ((nbits + 7) >> 3) as usize > self.src.len() { return Err(TooManyBitsRequested); } |
90aa4e6b KS |
336 | self.reset_cache(); |
337 | self.pos = ((nbits / 32) * 4) as usize; | |
338 | self.skip(nbits & 0x1F) | |
339 | } | |
06fd8c88 | 340 | |
26aa3dd3 KS |
341 | /// Aligns the bit position to the next byte boundary. If already at byte boundary the function does nothing. |
342 | /// | |
343 | /// # Examples | |
344 | /// | |
345 | /// ``` | |
346 | /// use nihav_core::io::bitreader::{BitReader,BitReaderMode}; | |
347 | /// | |
348 | /// # use nihav_core::io::bitreader::BitReaderResult; | |
155c91e4 | 349 | /// # fn foo() -> BitReaderResult<()> { |
26aa3dd3 KS |
350 | /// let bits: [u8; 4] = [ 42, 43, 44, 45 ]; |
351 | /// let mut br = BitReader::new(&bits, BitReaderMode::BE); | |
352 | /// br.skip(17)?; // now reader is at bit position 17 | |
353 | /// br.align(); // now reader is at bit position 24 | |
354 | /// br.align(); // now reader is still at bit position 24 | |
355 | /// # Ok(()) | |
356 | /// # } | |
357 | /// ``` | |
06fd8c88 KS |
358 | pub fn align(&mut self) { |
359 | let pos = self.bits & 7; | |
360 | if pos != 0 { | |
361 | self.skip_cache(pos); | |
362 | } | |
363 | } | |
364 | } | |
365 | ||
26aa3dd3 KS |
366 | /// Returns a variable with `len` amount of low bits in reverse order. |
367 | /// | |
368 | /// # Examples | |
369 | /// ``` | |
370 | /// use nihav_core::io::bitreader::reverse_bits; | |
371 | /// reverse_bits(0b010101, 6); // the result should be 0b101010 | |
372 | /// ``` | |
06fd8c88 KS |
373 | pub fn reverse_bits(inval: u32, len: u8) -> u32 { |
374 | if len == 0 { return 0; } | |
375 | const REV_TAB: [u8; 16] = [ | |
376 | 0b0000, 0b1000, 0b0100, 0b1100, 0b0010, 0b1010, 0b0110, 0b1110, | |
377 | 0b0001, 0b1001, 0b0101, 0b1101, 0b0011, 0b1011, 0b0111, 0b1111, | |
378 | ]; | |
379 | ||
380 | let mut ret = 0; | |
381 | let mut val = inval; | |
382 | for _ in 0..8 { | |
e243ceb4 KS |
383 | ret = (ret << 4) | u32::from(REV_TAB[(val & 0xF) as usize]); |
384 | val >>= 4; | |
06fd8c88 KS |
385 | } |
386 | ret >> (32 - len) | |
90aa4e6b KS |
387 | } |
388 | ||
389 | #[cfg(test)] | |
390 | mod test { | |
391 | use super::*; | |
392 | ||
393 | #[test] | |
394 | fn br_works() { | |
395 | const DATA: [u8; 18] = [0b00011011; 18]; | |
396 | let src = &DATA; | |
fa90ccfb | 397 | let mut br = BitReader::new(src, BitReaderMode::LE16MSB); |
90aa4e6b KS |
398 | |
399 | for _ in 0..8 { | |
400 | assert_eq!(br.read(16).unwrap(), 0x1B1B); | |
401 | } | |
a961f92b KS |
402 | const DATA2: [u8; 1] = [ 0b00011011 ]; |
403 | let src = &DATA2; | |
fa90ccfb | 404 | let mut br = BitReader::new(src, BitReaderMode::LE); |
a961f92b | 405 | assert_eq!(br.read_s(5).unwrap(), -5); |
90aa4e6b KS |
406 | } |
407 | } |