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