]>
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 | /// Reports the current bit position in the bitstream (usually simply the number of bits read so far). | |
94 | pub fn tell(&self) -> usize { | |
95 | self.pos * 8 - (self.bits as usize) | |
96 | } | |
97 | ||
98 | /// Reports the amount of bits left until the end of the bitstream. | |
99 | pub fn left(&self) -> isize { | |
100 | ((self.src.len() as isize) - (self.pos as isize)) * 8 + (self.bits as isize) | |
101 | } | |
102 | ||
103 | fn fill32be(&mut self, src: &[u8]) { | |
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); | |
109 | } | |
110 | ||
111 | fn fill32le16(&mut self, src: &[u8]) { | |
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); | |
117 | } | |
118 | ||
119 | fn fill32le32(&mut self, src: &[u8], lsb: bool) { | |
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); | |
124 | if lsb { | |
125 | self.cache |= u64::from(nw) << self.bits; | |
126 | } else { | |
127 | self.cache |= u64::from(nw) << (32 - self.bits); | |
128 | } | |
129 | } | |
130 | ||
131 | #[inline(always)] | |
132 | fn refill(&mut self) -> BitReaderResult<()> { | |
133 | if self.pos >= self.src.len() { return Err(BitstreamEnd) } | |
134 | while self.bits <= 32 { | |
135 | if self.pos + 4 <= self.src.len() { | |
136 | let buf = &self.src[self.pos..]; | |
137 | match self.mode { | |
138 | BitReaderMode::BE => self.fill32be (buf), | |
139 | BitReaderMode::LE16MSB => self.fill32le16(buf), | |
140 | BitReaderMode::LE => self.fill32le32(buf, true), | |
141 | BitReaderMode::LE32MSB => self.fill32le32(buf, false), | |
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; | |
148 | for out in buf.iter_mut().take(3) { | |
149 | if self.pos < self.src.len() { | |
150 | *out = self.src[self.pos]; | |
151 | self.pos += 1; | |
152 | newbits += 8; | |
153 | } | |
154 | } | |
155 | if newbits == 0 { break; } | |
156 | match self.mode { | |
157 | BitReaderMode::BE => self.fill32be (&buf), | |
158 | BitReaderMode::LE16MSB => self.fill32le16(&buf), | |
159 | BitReaderMode::LE => self.fill32le32(&buf, true), | |
160 | BitReaderMode::LE32MSB => self.fill32le32(&buf, false), | |
161 | } | |
162 | self.bits += newbits; | |
163 | } | |
164 | } | |
165 | Ok(()) | |
166 | } | |
167 | ||
168 | #[inline(always)] | |
169 | fn read_cache(&mut self, nbits: u8) -> u32 { | |
170 | let res = match self.mode { | |
171 | BitReaderMode::LE => ((1u64 << nbits) - 1) & self.cache, | |
172 | _ => self.cache >> (64 - nbits), | |
173 | }; | |
174 | res as u32 | |
175 | } | |
176 | ||
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 | ||
185 | #[inline(always)] | |
186 | fn skip_cache(&mut self, nbits: u8) { | |
187 | match self.mode { | |
188 | BitReaderMode::LE => self.cache >>= nbits, | |
189 | _ => self.cache <<= nbits, | |
190 | }; | |
191 | self.bits -= nbits; | |
192 | } | |
193 | ||
194 | #[inline(always)] | |
195 | fn reset_cache(&mut self) { | |
196 | self.bits = 0; | |
197 | self.cache = 0; | |
198 | } | |
199 | ||
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; | |
213 | /// # fn foo() -> BitReaderResult<u32> { | |
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 | |
222 | #[inline(always)] | |
223 | pub fn read(&mut self, nbits: u8) -> BitReaderResult<u32> { | |
224 | if nbits == 0 { return Ok(0) } | |
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); | |
232 | Ok(res) | |
233 | } | |
234 | ||
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 | |
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) | |
249 | } | |
250 | ||
251 | /// Reads single bit from the stream and interprets it as a boolean value. | |
252 | #[inline(always)] | |
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 | ||
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; | |
273 | /// # fn foo() -> BitReaderResult<u32> { | |
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 | /// ``` | |
281 | #[inline(always)] | |
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 | ||
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 | |
295 | #[inline(always)] | |
296 | pub fn skip(&mut self, nbits: u32) -> BitReaderResult<()> { | |
297 | if u32::from(self.bits) >= nbits { | |
298 | self.skip_cache(nbits as u8); | |
299 | return Ok(()); | |
300 | } | |
301 | let mut skip_bits = nbits - u32::from(self.bits); | |
302 | self.reset_cache(); | |
303 | self.pos += ((skip_bits / 32) * 4) as usize; | |
304 | skip_bits &= 0x1F; | |
305 | self.refill()?; | |
306 | if skip_bits > 0 { | |
307 | self.skip_cache(skip_bits as u8); | |
308 | } | |
309 | Ok(()) | |
310 | } | |
311 | ||
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; | |
321 | /// # fn foo() -> BitReaderResult<u32> { | |
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 | |
331 | pub fn seek(&mut self, nbits: u32) -> BitReaderResult<()> { | |
332 | if ((nbits + 7) >> 3) as usize > self.src.len() { return Err(TooManyBitsRequested); } | |
333 | self.reset_cache(); | |
334 | self.pos = ((nbits / 32) * 4) as usize; | |
335 | self.skip(nbits & 0x1F) | |
336 | } | |
337 | ||
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; | |
346 | /// # fn foo() -> BitReaderResult<()> { | |
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 | /// ``` | |
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 | ||
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 | /// ``` | |
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 { | |
380 | ret = (ret << 4) | u32::from(REV_TAB[(val & 0xF) as usize]); | |
381 | val >>= 4; | |
382 | } | |
383 | ret >> (32 - len) | |
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; | |
394 | let mut br = BitReader::new(src, BitReaderMode::LE16MSB); | |
395 | ||
396 | for _ in 0..8 { | |
397 | assert_eq!(br.read(16).unwrap(), 0x1B1B); | |
398 | } | |
399 | const DATA2: [u8; 1] = [ 0b00011011 ]; | |
400 | let src = &DATA2; | |
401 | let mut br = BitReader::new(src, BitReaderMode::LE); | |
402 | assert_eq!(br.read_s(5).unwrap(), -5); | |
403 | } | |
404 | } |