]>
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 | ||
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 |
370 | pub 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)] | |
387 | mod 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 | } |