/rust/registry/src/index.crates.io-6f17d22bba15001f/bitstream-io-2.6.0/src/lib.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2017 Brian Langenberger |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
4 | | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
5 | | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
6 | | // option. This file may not be copied, modified, or distributed |
7 | | // except according to those terms. |
8 | | |
9 | | //! Traits and helpers for bitstream handling functionality |
10 | | //! |
11 | | //! Bitstream readers are for reading signed and unsigned integer |
12 | | //! values from a stream whose sizes may not be whole bytes. |
13 | | //! Bitstream writers are for writing signed and unsigned integer |
14 | | //! values to a stream, also potentially un-aligned at a whole byte. |
15 | | //! |
16 | | //! Both big-endian and little-endian streams are supported. |
17 | | //! |
18 | | //! The only requirement for wrapped reader streams is that they must |
19 | | //! implement the `Read` trait, and the only requirement |
20 | | //! for writer streams is that they must implement the `Write` trait. |
21 | | //! |
22 | | //! In addition, reader streams do not consume any more bytes |
23 | | //! from the underlying reader than necessary, buffering only a |
24 | | //! single partial byte as needed. |
25 | | //! Writer streams also write out all whole bytes as they are accumulated. |
26 | | //! |
27 | | //! Readers and writers are also designed to work with integer |
28 | | //! types of any possible size. |
29 | | //! Many of Rust's built-in integer types are supported by default. |
30 | | |
31 | | //! # Minimum Compiler Version |
32 | | //! |
33 | | //! Beginning with version 2.4, the minimum compiler version has been |
34 | | //! updated to Rust 1.79. |
35 | | //! |
36 | | //! The issue is that reading an excessive number of |
37 | | //! bits to a type which is too small to hold them, |
38 | | //! or writing an excessive number of bits from too small of a type, |
39 | | //! are always errors: |
40 | | //! ``` |
41 | | //! use std::io::{Read, Cursor}; |
42 | | //! use bitstream_io::{BigEndian, BitReader, BitRead}; |
43 | | //! let data = [0; 10]; |
44 | | //! let mut r = BitReader::endian(Cursor::new(&data), BigEndian); |
45 | | //! let x: Result<u32, _> = r.read(64); // reading 64 bits to u32 always fails at runtime |
46 | | //! assert!(x.is_err()); |
47 | | //! ``` |
48 | | //! but those errors will not be caught until the program runs, |
49 | | //! which is less than ideal for the common case in which |
50 | | //! the number of bits is already known at compile-time. |
51 | | //! |
52 | | //! But starting with Rust 1.79, we can now have read and write methods |
53 | | //! which take a constant number of bits and can validate the number of bits |
54 | | //! are small enough for the type being read/written at compile-time: |
55 | | //! ```rust,ignore |
56 | | //! use std::io::{Read, Cursor}; |
57 | | //! use bitstream_io::{BigEndian, BitReader, BitRead}; |
58 | | //! let data = [0; 10]; |
59 | | //! let mut r = BitReader::endian(Cursor::new(&data), BigEndian); |
60 | | //! let x: Result<u32, _> = r.read_in::<64, _>(); // doesn't compile at all |
61 | | //! ``` |
62 | | //! Since catching potential bugs at compile-time is preferable |
63 | | //! to encountering errors at runtime, this will hopefully be |
64 | | //! an improvement in the long run. |
65 | | |
66 | | //! # Migrating From Pre 1.0.0 |
67 | | //! |
68 | | //! There are now `BitRead` and `BitWrite` traits for bitstream |
69 | | //! reading and writing (analogous to the standard library's |
70 | | //! `Read` and `Write` traits) which you will also need to import. |
71 | | //! The upside to this approach is that library consumers |
72 | | //! can now make functions and methods generic over any sort |
73 | | //! of bit reader or bit writer, regardless of the underlying |
74 | | //! stream byte source or endianness. |
75 | | |
76 | | #![warn(missing_docs)] |
77 | | #![forbid(unsafe_code)] |
78 | | #![cfg_attr(feature = "alloc", no_std)] |
79 | | |
80 | | #[cfg(feature = "alloc")] |
81 | | extern crate alloc; |
82 | | use core::fmt::Debug; |
83 | | use core::marker::PhantomData; |
84 | | use core::mem; |
85 | | use core::ops::{BitOrAssign, BitXor, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub}; |
86 | | #[cfg(feature = "alloc")] |
87 | | use core2::io; |
88 | | #[cfg(not(feature = "alloc"))] |
89 | | use std::io; |
90 | | |
91 | | pub mod huffman; |
92 | | pub mod read; |
93 | | pub mod write; |
94 | | pub use read::{ |
95 | | BitRead, BitReader, ByteRead, ByteReader, FromBitStream, FromBitStreamWith, FromByteStream, |
96 | | FromByteStreamWith, HuffmanRead, |
97 | | }; |
98 | | pub use write::{ |
99 | | BitCounter, BitRecorder, BitWrite, BitWriter, ByteWrite, ByteWriter, HuffmanWrite, ToBitStream, |
100 | | ToBitStreamWith, ToByteStream, ToByteStreamWith, |
101 | | }; |
102 | | |
103 | | /// A trait intended for simple fixed-length primitives (such as ints and floats) |
104 | | /// which allows them to be read and written to streams of |
105 | | /// different endiannesses verbatim. |
106 | | pub trait Primitive { |
107 | | /// The raw byte representation of this numeric type |
108 | | type Bytes: AsRef<[u8]> + AsMut<[u8]>; |
109 | | |
110 | | /// An empty buffer of this type's size |
111 | | fn buffer() -> Self::Bytes; |
112 | | |
113 | | /// Our value in big-endian bytes |
114 | | fn to_be_bytes(self) -> Self::Bytes; |
115 | | |
116 | | /// Our value in little-endian bytes |
117 | | fn to_le_bytes(self) -> Self::Bytes; |
118 | | |
119 | | /// Convert big-endian bytes to our value |
120 | | fn from_be_bytes(bytes: Self::Bytes) -> Self; |
121 | | |
122 | | /// Convert little-endian bytes to our value |
123 | | fn from_le_bytes(bytes: Self::Bytes) -> Self; |
124 | | } |
125 | | |
126 | | macro_rules! define_primitive_numeric { |
127 | | ($t:ty) => { |
128 | | impl Primitive for $t { |
129 | | type Bytes = [u8; mem::size_of::<$t>()]; |
130 | | |
131 | | #[inline(always)] |
132 | 0 | fn buffer() -> Self::Bytes { |
133 | 0 | [0; mem::size_of::<$t>()] |
134 | 0 | } Unexecuted instantiation: <u8 as bitstream_io::Primitive>::buffer Unexecuted instantiation: <i8 as bitstream_io::Primitive>::buffer Unexecuted instantiation: <u16 as bitstream_io::Primitive>::buffer Unexecuted instantiation: <i16 as bitstream_io::Primitive>::buffer Unexecuted instantiation: <u32 as bitstream_io::Primitive>::buffer Unexecuted instantiation: <i32 as bitstream_io::Primitive>::buffer Unexecuted instantiation: <u64 as bitstream_io::Primitive>::buffer |
135 | | #[inline(always)] |
136 | 0 | fn to_be_bytes(self) -> Self::Bytes { |
137 | 0 | self.to_be_bytes() |
138 | 0 | } Unexecuted instantiation: <i8 as bitstream_io::Primitive>::to_be_bytes Unexecuted instantiation: <i16 as bitstream_io::Primitive>::to_be_bytes |
139 | | #[inline(always)] |
140 | | fn to_le_bytes(self) -> Self::Bytes { |
141 | | self.to_le_bytes() |
142 | | } |
143 | | #[inline(always)] |
144 | | fn from_be_bytes(bytes: Self::Bytes) -> Self { |
145 | | <$t>::from_be_bytes(bytes) |
146 | | } |
147 | | #[inline(always)] |
148 | | fn from_le_bytes(bytes: Self::Bytes) -> Self { |
149 | | <$t>::from_le_bytes(bytes) |
150 | | } |
151 | | } |
152 | | }; |
153 | | } |
154 | | |
155 | | impl<const N: usize> Primitive for [u8; N] { |
156 | | type Bytes = [u8; N]; |
157 | | |
158 | | #[inline(always)] |
159 | | fn buffer() -> Self::Bytes { |
160 | | [0; N] |
161 | | } |
162 | | |
163 | | #[inline(always)] |
164 | | fn to_be_bytes(self) -> Self::Bytes { |
165 | | self |
166 | | } |
167 | | |
168 | | #[inline(always)] |
169 | | fn to_le_bytes(self) -> Self::Bytes { |
170 | | self |
171 | | } |
172 | | |
173 | | #[inline(always)] |
174 | | fn from_be_bytes(bytes: Self::Bytes) -> Self { |
175 | | bytes |
176 | | } |
177 | | |
178 | | #[inline(always)] |
179 | | fn from_le_bytes(bytes: Self::Bytes) -> Self { |
180 | | bytes |
181 | | } |
182 | | } |
183 | | |
184 | | /// This trait extends many common integer types (both unsigned and signed) |
185 | | /// with a few trivial methods so that they can be used |
186 | | /// with the bitstream handling traits. |
187 | | pub trait Numeric: |
188 | | Primitive |
189 | | + Sized |
190 | | + Copy |
191 | | + Default |
192 | | + Debug |
193 | | + PartialOrd |
194 | | + Shl<u32, Output = Self> |
195 | | + ShlAssign<u32> |
196 | | + Shr<u32, Output = Self> |
197 | | + ShrAssign<u32> |
198 | | + Rem<Self, Output = Self> |
199 | | + RemAssign<Self> |
200 | | + BitOrAssign<Self> |
201 | | + BitXor<Self, Output = Self> |
202 | | + Not<Output = Self> |
203 | | + Sub<Self, Output = Self> |
204 | | { |
205 | | /// Size of type in bits |
206 | | const BITS_SIZE: u32; |
207 | | |
208 | | /// The value of 1 in this type |
209 | | const ONE: Self; |
210 | | |
211 | | /// Returns true if this value is 0, in its type |
212 | | fn is_zero(self) -> bool; |
213 | | |
214 | | /// Returns a `u8` value in this type |
215 | | fn from_u8(u: u8) -> Self; |
216 | | |
217 | | /// Assuming 0 <= value < 256, returns this value as a `u8` type |
218 | | fn to_u8(self) -> u8; |
219 | | |
220 | | /// Counts the number of 1 bits |
221 | | fn count_ones(self) -> u32; |
222 | | |
223 | | /// Counts the number of leading zeros |
224 | | fn leading_zeros(self) -> u32; |
225 | | |
226 | | /// Counts the number of trailing zeros |
227 | | fn trailing_zeros(self) -> u32; |
228 | | |
229 | | /// Convert to a generic unsigned write value for stream recording purposes |
230 | | fn unsigned_value(self) -> write::UnsignedValue; |
231 | | } |
232 | | |
233 | | macro_rules! define_numeric { |
234 | | ($t:ty) => { |
235 | | define_primitive_numeric!($t); |
236 | | |
237 | | impl Numeric for $t { |
238 | | const BITS_SIZE: u32 = mem::size_of::<$t>() as u32 * 8; |
239 | | |
240 | | const ONE: Self = 1; |
241 | | |
242 | | #[inline(always)] |
243 | 0 | fn is_zero(self) -> bool { |
244 | 0 | self == 0 |
245 | 0 | } |
246 | | #[inline(always)] |
247 | | fn from_u8(u: u8) -> Self { |
248 | | u as $t |
249 | | } |
250 | | #[inline(always)] |
251 | 0 | fn to_u8(self) -> u8 { |
252 | 0 | self as u8 |
253 | 0 | } Unexecuted instantiation: <u8 as bitstream_io::Numeric>::to_u8 Unexecuted instantiation: <i8 as bitstream_io::Numeric>::to_u8 Unexecuted instantiation: <u16 as bitstream_io::Numeric>::to_u8 Unexecuted instantiation: <i16 as bitstream_io::Numeric>::to_u8 Unexecuted instantiation: <u32 as bitstream_io::Numeric>::to_u8 Unexecuted instantiation: <i32 as bitstream_io::Numeric>::to_u8 Unexecuted instantiation: <u64 as bitstream_io::Numeric>::to_u8 |
254 | | #[inline(always)] |
255 | | fn count_ones(self) -> u32 { |
256 | | self.count_ones() |
257 | | } |
258 | | #[inline(always)] |
259 | | fn leading_zeros(self) -> u32 { |
260 | | self.leading_zeros() |
261 | | } |
262 | | #[inline(always)] |
263 | | fn trailing_zeros(self) -> u32 { |
264 | | self.trailing_zeros() |
265 | | } |
266 | | #[inline(always)] |
267 | | fn unsigned_value(self) -> write::UnsignedValue { |
268 | | self.into() |
269 | | } |
270 | | } |
271 | | }; |
272 | | } |
273 | | |
274 | | /// This trait extends many common signed integer types |
275 | | /// so that they can be used with the bitstream handling traits. |
276 | | pub trait SignedNumeric: Numeric { |
277 | | /// Returns true if this value is negative |
278 | | fn is_negative(self) -> bool; |
279 | | |
280 | | /// Given a two-complement positive value and certain number of bits, |
281 | | /// returns this value as a negative number. |
282 | | fn as_negative(self, bits: u32) -> Self; |
283 | | |
284 | | /// Given a two-complement positive value and certain number of bits, |
285 | | /// returns this value as a negative number. |
286 | | fn as_negative_fixed<const BITS: u32>(self) -> Self; |
287 | | |
288 | | /// Given a negative value and a certain number of bits, |
289 | | /// returns this value as a twos-complement positive number. |
290 | | fn as_unsigned(self, bits: u32) -> Self; |
291 | | |
292 | | /// Given a negative value and a certain number of bits, |
293 | | /// returns this value as a twos-complement positive number. |
294 | | fn as_unsigned_fixed<const BITS: u32>(self) -> Self; |
295 | | |
296 | | /// Converts to a generic signed value for stream recording purposes. |
297 | | fn signed_value(self) -> write::SignedValue; |
298 | | } |
299 | | |
300 | | macro_rules! define_signed_numeric { |
301 | | ($t:ty) => { |
302 | | impl SignedNumeric for $t { |
303 | | #[inline(always)] |
304 | 0 | fn is_negative(self) -> bool { |
305 | 0 | self < 0 |
306 | 0 | } Unexecuted instantiation: <i8 as bitstream_io::SignedNumeric>::is_negative Unexecuted instantiation: <i16 as bitstream_io::SignedNumeric>::is_negative |
307 | | #[inline(always)] |
308 | | fn as_negative(self, bits: u32) -> Self { |
309 | | self + (-1 << (bits - 1)) |
310 | | } |
311 | | #[inline(always)] |
312 | | fn as_negative_fixed<const BITS: u32>(self) -> Self { |
313 | | self + (-1 << (BITS - 1)) |
314 | | } |
315 | | #[inline(always)] |
316 | 0 | fn as_unsigned(self, bits: u32) -> Self { |
317 | 0 | self - (-1 << (bits - 1)) |
318 | 0 | } Unexecuted instantiation: <i8 as bitstream_io::SignedNumeric>::as_unsigned Unexecuted instantiation: <i16 as bitstream_io::SignedNumeric>::as_unsigned |
319 | | #[inline(always)] |
320 | | fn as_unsigned_fixed<const BITS: u32>(self) -> Self { |
321 | | self - (-1 << (BITS - 1)) |
322 | | } |
323 | | #[inline(always)] |
324 | | fn signed_value(self) -> write::SignedValue { |
325 | | self.into() |
326 | | } |
327 | | } |
328 | | }; |
329 | | } |
330 | | |
331 | | define_numeric!(u8); |
332 | | define_numeric!(i8); |
333 | | define_numeric!(u16); |
334 | | define_numeric!(i16); |
335 | | define_numeric!(u32); |
336 | | define_numeric!(i32); |
337 | | define_numeric!(u64); |
338 | | define_numeric!(i64); |
339 | | define_numeric!(u128); |
340 | | define_numeric!(i128); |
341 | | |
342 | | define_signed_numeric!(i8); |
343 | | define_signed_numeric!(i16); |
344 | | define_signed_numeric!(i32); |
345 | | define_signed_numeric!(i64); |
346 | | define_signed_numeric!(i128); |
347 | | |
348 | | define_primitive_numeric!(f32); |
349 | | define_primitive_numeric!(f64); |
350 | | |
351 | | /// A stream's endianness, or byte order, for determining |
352 | | /// how bits should be read. |
353 | | /// |
354 | | /// It comes in `BigEndian` and `LittleEndian` varieties |
355 | | /// (which may be shortened to `BE` and `LE`) |
356 | | /// and is not something programmers should have to implement |
357 | | /// in most cases. |
358 | | pub trait Endianness: Sized { |
359 | | /// Pushes the given bits and value onto an accumulator |
360 | | /// with the given bits and value. |
361 | | fn push<N>(queue: &mut BitQueue<Self, N>, bits: u32, value: N) |
362 | | where |
363 | | N: Numeric; |
364 | | |
365 | | /// Pushes the given constant number of bits and value onto an accumulator |
366 | | /// with the given bits and value. |
367 | | fn push_fixed<const B: u32, N>(queue: &mut BitQueue<Self, N>, value: N) |
368 | | where |
369 | | N: Numeric; |
370 | | |
371 | | /// Pops a value with the given number of bits from an accumulator |
372 | | /// with the given bits and value. |
373 | | fn pop<N>(queue: &mut BitQueue<Self, N>, bits: u32) -> N |
374 | | where |
375 | | N: Numeric; |
376 | | |
377 | | /// Pops a value with the given number of constant bits |
378 | | /// from an accumulator with the given bits and value. |
379 | | fn pop_fixed<const B: u32, N>(queue: &mut BitQueue<Self, N>) -> N |
380 | | where |
381 | | N: Numeric; |
382 | | |
383 | | /// Drops the given number of bits from an accumulator |
384 | | /// with the given bits and value. |
385 | | fn drop<N>(queue: &mut BitQueue<Self, N>, bits: u32) |
386 | | where |
387 | | N: Numeric; |
388 | | |
389 | | /// Returns the next number of 0 bits from an accumulator |
390 | | /// with the given bits and value. |
391 | | fn next_zeros<N>(queue: &BitQueue<Self, N>) -> u32 |
392 | | where |
393 | | N: Numeric; |
394 | | |
395 | | /// Returns the next number of 1 bits from an accumulator |
396 | | /// with the given bits and value. |
397 | | fn next_ones<N>(queue: &BitQueue<Self, N>) -> u32 |
398 | | where |
399 | | N: Numeric; |
400 | | |
401 | | /// Reads signed value from reader in this endianness |
402 | | fn read_signed<R, S>(r: &mut R, bits: u32) -> io::Result<S> |
403 | | where |
404 | | R: BitRead, |
405 | | S: SignedNumeric; |
406 | | |
407 | | /// Reads signed value from reader in this endianness |
408 | | fn read_signed_fixed<R, const B: u32, S>(r: &mut R) -> io::Result<S> |
409 | | where |
410 | | R: BitRead, |
411 | | S: SignedNumeric; |
412 | | |
413 | | /// Writes signed value to writer in this endianness |
414 | | fn write_signed<W, S>(w: &mut W, bits: u32, value: S) -> io::Result<()> |
415 | | where |
416 | | W: BitWrite, |
417 | | S: SignedNumeric; |
418 | | |
419 | | /// Writes signed value to writer in this endianness |
420 | | fn write_signed_fixed<W, const B: u32, S>(w: &mut W, value: S) -> io::Result<()> |
421 | | where |
422 | | W: BitWrite, |
423 | | S: SignedNumeric; |
424 | | |
425 | | /// Reads convertable numeric value from reader in this endianness |
426 | | fn read_primitive<R, V>(r: &mut R) -> io::Result<V> |
427 | | where |
428 | | R: BitRead, |
429 | | V: Primitive; |
430 | | |
431 | | /// Writes convertable numeric value to writer in this endianness |
432 | | fn write_primitive<W, V>(w: &mut W, value: V) -> io::Result<()> |
433 | | where |
434 | | W: BitWrite, |
435 | | V: Primitive; |
436 | | |
437 | | /// Reads entire numeric value from reader in this endianness |
438 | | fn read_numeric<R, V>(r: R) -> io::Result<V> |
439 | | where |
440 | | R: io::Read, |
441 | | V: Primitive; |
442 | | |
443 | | /// Writes entire numeric value to writer in this endianness |
444 | | fn write_numeric<W, V>(w: W, value: V) -> io::Result<()> |
445 | | where |
446 | | W: io::Write, |
447 | | V: Primitive; |
448 | | } |
449 | | |
450 | | /// Big-endian, or most significant bits first |
451 | | #[derive(Copy, Clone, Debug)] |
452 | | pub struct BigEndian; |
453 | | |
454 | | /// Big-endian, or most significant bits first |
455 | | pub type BE = BigEndian; |
456 | | |
457 | | impl Endianness for BigEndian { |
458 | | #[inline] |
459 | 0 | fn push<N>(queue: &mut BitQueue<Self, N>, bits: u32, value: N) |
460 | 0 | where |
461 | 0 | N: Numeric, |
462 | 0 | { |
463 | 0 | if !queue.value.is_zero() { |
464 | 0 | queue.value <<= bits; |
465 | 0 | } |
466 | 0 | queue.value |= value; |
467 | 0 | queue.bits += bits; |
468 | 0 | } |
469 | | |
470 | | #[inline] |
471 | 0 | fn push_fixed<const B: u32, N>(queue: &mut BitQueue<Self, N>, value: N) |
472 | 0 | where |
473 | 0 | N: Numeric, |
474 | 0 | { |
475 | 0 | if !queue.value.is_zero() { |
476 | 0 | queue.value <<= B; |
477 | 0 | } |
478 | 0 | queue.value |= value; |
479 | 0 | queue.bits += B; |
480 | 0 | } |
481 | | |
482 | | #[inline] |
483 | 0 | fn pop<N>(queue: &mut BitQueue<Self, N>, bits: u32) -> N |
484 | 0 | where |
485 | 0 | N: Numeric, |
486 | 0 | { |
487 | 0 | if bits < queue.bits { |
488 | 0 | let offset = queue.bits - bits; |
489 | 0 | let to_return = queue.value >> offset; |
490 | 0 | queue.value %= N::ONE << offset; |
491 | 0 | queue.bits -= bits; |
492 | 0 | to_return |
493 | | } else { |
494 | 0 | let to_return = queue.value; |
495 | 0 | queue.value = N::default(); |
496 | 0 | queue.bits = 0; |
497 | 0 | to_return |
498 | | } |
499 | 0 | } Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop::<i8> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop::<u8> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop::<i32> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop::<u32> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop::<i16> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop::<u16> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop::<u64> |
500 | | |
501 | | #[inline] |
502 | 0 | fn pop_fixed<const B: u32, N>(queue: &mut BitQueue<Self, N>) -> N |
503 | 0 | where |
504 | 0 | N: Numeric, |
505 | 0 | { |
506 | 0 | if B < queue.bits { |
507 | 0 | let offset = queue.bits - B; |
508 | 0 | let to_return = queue.value >> offset; |
509 | 0 | queue.value %= N::ONE << offset; |
510 | 0 | queue.bits -= B; |
511 | 0 | to_return |
512 | | } else { |
513 | 0 | let to_return = queue.value; |
514 | 0 | queue.value = N::default(); |
515 | 0 | queue.bits = 0; |
516 | 0 | to_return |
517 | | } |
518 | 0 | } Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop_fixed::<8, i8> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop_fixed::<8, u8> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop_fixed::<8, i32> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop_fixed::<8, u32> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop_fixed::<8, i16> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop_fixed::<8, u16> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::pop_fixed::<8, u64> |
519 | | |
520 | | #[inline] |
521 | | fn drop<N>(queue: &mut BitQueue<Self, N>, bits: u32) |
522 | | where |
523 | | N: Numeric, |
524 | | { |
525 | | if bits < queue.bits { |
526 | | queue.value %= N::ONE << (queue.bits - bits); |
527 | | queue.bits -= bits; |
528 | | } else { |
529 | | queue.value = N::default(); |
530 | | queue.bits = 0; |
531 | | } |
532 | | } |
533 | | |
534 | | #[inline] |
535 | | fn next_zeros<N>(queue: &BitQueue<Self, N>) -> u32 |
536 | | where |
537 | | N: Numeric, |
538 | | { |
539 | | queue.value.leading_zeros() - (N::BITS_SIZE - queue.bits) |
540 | | } |
541 | | |
542 | | #[inline] |
543 | | fn next_ones<N>(queue: &BitQueue<Self, N>) -> u32 |
544 | | where |
545 | | N: Numeric, |
546 | | { |
547 | | if queue.bits < N::BITS_SIZE { |
548 | | (queue.value ^ ((N::ONE << queue.bits) - N::ONE)).leading_zeros() |
549 | | - (N::BITS_SIZE - queue.bits) |
550 | | } else { |
551 | | (!queue.value).leading_zeros() |
552 | | } |
553 | | } |
554 | | |
555 | | fn read_signed<R, S>(r: &mut R, bits: u32) -> io::Result<S> |
556 | | where |
557 | | R: BitRead, |
558 | | S: SignedNumeric, |
559 | | { |
560 | | let is_negative = r.read_bit()?; |
561 | | let unsigned = r.read::<S>(bits - 1)?; |
562 | | Ok(if is_negative { |
563 | | unsigned.as_negative(bits) |
564 | | } else { |
565 | | unsigned |
566 | | }) |
567 | | } |
568 | | |
569 | | fn read_signed_fixed<R, const B: u32, S>(r: &mut R) -> io::Result<S> |
570 | | where |
571 | | R: BitRead, |
572 | | S: SignedNumeric, |
573 | | { |
574 | | let is_negative = r.read_bit()?; |
575 | | let unsigned = r.read::<S>(B - 1)?; |
576 | | Ok(if is_negative { |
577 | | unsigned.as_negative_fixed::<B>() |
578 | | } else { |
579 | | unsigned |
580 | | }) |
581 | | } |
582 | | |
583 | 0 | fn write_signed<W, S>(w: &mut W, bits: u32, value: S) -> io::Result<()> |
584 | 0 | where |
585 | 0 | W: BitWrite, |
586 | 0 | S: SignedNumeric, |
587 | 0 | { |
588 | 0 | if bits == S::BITS_SIZE { |
589 | 0 | w.write_bytes(value.to_be_bytes().as_ref()) |
590 | 0 | } else if value.is_negative() { |
591 | 0 | w.write_bit(true) |
592 | 0 | .and_then(|()| w.write(bits - 1, value.as_unsigned(bits))) Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::write_signed::<bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian>, i8>::{closure#0} Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::write_signed::<bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian>, i16>::{closure#0} |
593 | | } else { |
594 | 0 | w.write_bit(false).and_then(|()| w.write(bits - 1, value)) Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::write_signed::<bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian>, i8>::{closure#1} Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::write_signed::<bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian>, i16>::{closure#1} |
595 | | } |
596 | 0 | } Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::write_signed::<bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian>, i8> Unexecuted instantiation: <bitstream_io::BigEndian as bitstream_io::Endianness>::write_signed::<bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian>, i16> |
597 | | |
598 | | fn write_signed_fixed<W, const B: u32, S>(w: &mut W, value: S) -> io::Result<()> |
599 | | where |
600 | | W: BitWrite, |
601 | | S: SignedNumeric, |
602 | | { |
603 | | if B == S::BITS_SIZE { |
604 | | w.write_bytes(value.to_be_bytes().as_ref()) |
605 | | } else if value.is_negative() { |
606 | | w.write_bit(true) |
607 | | .and_then(|()| w.write(B - 1, value.as_unsigned(B))) |
608 | | } else { |
609 | | w.write_bit(false).and_then(|()| w.write(B - 1, value)) |
610 | | } |
611 | | } |
612 | | |
613 | | #[inline] |
614 | | fn read_primitive<R, V>(r: &mut R) -> io::Result<V> |
615 | | where |
616 | | R: BitRead, |
617 | | V: Primitive, |
618 | | { |
619 | | let mut buffer = V::buffer(); |
620 | | r.read_bytes(buffer.as_mut())?; |
621 | | Ok(V::from_be_bytes(buffer)) |
622 | | } |
623 | | |
624 | | #[inline] |
625 | | fn write_primitive<W, V>(w: &mut W, value: V) -> io::Result<()> |
626 | | where |
627 | | W: BitWrite, |
628 | | V: Primitive, |
629 | | { |
630 | | w.write_bytes(value.to_be_bytes().as_ref()) |
631 | | } |
632 | | |
633 | | #[inline] |
634 | | fn read_numeric<R, V>(mut r: R) -> io::Result<V> |
635 | | where |
636 | | R: io::Read, |
637 | | V: Primitive, |
638 | | { |
639 | | let mut buffer = V::buffer(); |
640 | | r.read_exact(buffer.as_mut())?; |
641 | | Ok(V::from_be_bytes(buffer)) |
642 | | } |
643 | | |
644 | | #[inline] |
645 | | fn write_numeric<W, V>(mut w: W, value: V) -> io::Result<()> |
646 | | where |
647 | | W: io::Write, |
648 | | V: Primitive, |
649 | | { |
650 | | w.write_all(value.to_be_bytes().as_ref()) |
651 | | } |
652 | | } |
653 | | |
654 | | /// Little-endian, or least significant bits first |
655 | | #[derive(Copy, Clone, Debug)] |
656 | | pub struct LittleEndian; |
657 | | |
658 | | /// Little-endian, or least significant bits first |
659 | | pub type LE = LittleEndian; |
660 | | |
661 | | impl Endianness for LittleEndian { |
662 | | #[inline] |
663 | 0 | fn push<N>(queue: &mut BitQueue<Self, N>, bits: u32, mut value: N) |
664 | 0 | where |
665 | 0 | N: Numeric, |
666 | 0 | { |
667 | 0 | if !value.is_zero() { |
668 | 0 | value <<= queue.bits; |
669 | 0 | queue.value |= value; |
670 | 0 | } |
671 | 0 | queue.bits += bits; |
672 | 0 | } |
673 | | |
674 | | #[inline] |
675 | | fn push_fixed<const B: u32, N>(queue: &mut BitQueue<Self, N>, mut value: N) |
676 | | where |
677 | | N: Numeric, |
678 | | { |
679 | | if !value.is_zero() { |
680 | | value <<= queue.bits; |
681 | | queue.value |= value; |
682 | | } |
683 | | queue.bits += B; |
684 | | } |
685 | | |
686 | | #[inline] |
687 | 0 | fn pop<N>(queue: &mut BitQueue<Self, N>, bits: u32) -> N |
688 | 0 | where |
689 | 0 | N: Numeric, |
690 | 0 | { |
691 | 0 | if bits < queue.bits { |
692 | 0 | let to_return = queue.value % (N::ONE << bits); |
693 | 0 | queue.value >>= bits; |
694 | 0 | queue.bits -= bits; |
695 | 0 | to_return |
696 | | } else { |
697 | 0 | let to_return = queue.value; |
698 | 0 | queue.value = N::default(); |
699 | 0 | queue.bits = 0; |
700 | 0 | to_return |
701 | | } |
702 | 0 | } Unexecuted instantiation: <bitstream_io::LittleEndian as bitstream_io::Endianness>::pop::<u8> Unexecuted instantiation: <bitstream_io::LittleEndian as bitstream_io::Endianness>::pop::<u64> |
703 | | |
704 | 0 | fn pop_fixed<const B: u32, N>(queue: &mut BitQueue<Self, N>) -> N |
705 | 0 | where |
706 | 0 | N: Numeric, |
707 | 0 | { |
708 | 0 | if B < queue.bits { |
709 | 0 | let to_return = queue.value % (N::ONE << B); |
710 | 0 | queue.value >>= B; |
711 | 0 | queue.bits -= B; |
712 | 0 | to_return |
713 | | } else { |
714 | 0 | let to_return = queue.value; |
715 | 0 | queue.value = N::default(); |
716 | 0 | queue.bits = 0; |
717 | 0 | to_return |
718 | | } |
719 | 0 | } |
720 | | |
721 | | #[inline] |
722 | | fn drop<N>(queue: &mut BitQueue<Self, N>, bits: u32) |
723 | | where |
724 | | N: Numeric, |
725 | | { |
726 | | if bits < queue.bits { |
727 | | queue.value >>= bits; |
728 | | queue.bits -= bits; |
729 | | } else { |
730 | | queue.value = N::default(); |
731 | | queue.bits = 0; |
732 | | } |
733 | | } |
734 | | |
735 | | #[inline(always)] |
736 | | fn next_zeros<N>(queue: &BitQueue<Self, N>) -> u32 |
737 | | where |
738 | | N: Numeric, |
739 | | { |
740 | | queue.value.trailing_zeros() |
741 | | } |
742 | | |
743 | | #[inline] |
744 | | fn next_ones<N>(queue: &BitQueue<Self, N>) -> u32 |
745 | | where |
746 | | N: Numeric, |
747 | | { |
748 | | (queue.value ^ !N::default()).trailing_zeros() |
749 | | } |
750 | | |
751 | | fn read_signed<R, S>(r: &mut R, bits: u32) -> io::Result<S> |
752 | | where |
753 | | R: BitRead, |
754 | | S: SignedNumeric, |
755 | | { |
756 | | let unsigned = r.read::<S>(bits - 1)?; |
757 | | let is_negative = r.read_bit()?; |
758 | | Ok(if is_negative { |
759 | | unsigned.as_negative(bits) |
760 | | } else { |
761 | | unsigned |
762 | | }) |
763 | | } |
764 | | |
765 | | fn read_signed_fixed<R, const B: u32, S>(r: &mut R) -> io::Result<S> |
766 | | where |
767 | | R: BitRead, |
768 | | S: SignedNumeric, |
769 | | { |
770 | | let unsigned = r.read::<S>(B - 1)?; |
771 | | let is_negative = r.read_bit()?; |
772 | | Ok(if is_negative { |
773 | | unsigned.as_negative_fixed::<B>() |
774 | | } else { |
775 | | unsigned |
776 | | }) |
777 | | } |
778 | | |
779 | | fn write_signed<W, S>(w: &mut W, bits: u32, value: S) -> io::Result<()> |
780 | | where |
781 | | W: BitWrite, |
782 | | S: SignedNumeric, |
783 | | { |
784 | | if bits == S::BITS_SIZE { |
785 | | w.write_bytes(value.to_le_bytes().as_ref()) |
786 | | } else if value.is_negative() { |
787 | | w.write(bits - 1, value.as_unsigned(bits)) |
788 | | .and_then(|()| w.write_bit(true)) |
789 | | } else { |
790 | | w.write(bits - 1, value).and_then(|()| w.write_bit(false)) |
791 | | } |
792 | | } |
793 | | |
794 | | fn write_signed_fixed<W, const B: u32, S>(w: &mut W, value: S) -> io::Result<()> |
795 | | where |
796 | | W: BitWrite, |
797 | | S: SignedNumeric, |
798 | | { |
799 | | if B == S::BITS_SIZE { |
800 | | w.write_bytes(value.to_le_bytes().as_ref()) |
801 | | } else if value.is_negative() { |
802 | | w.write(B - 1, value.as_unsigned_fixed::<B>()) |
803 | | .and_then(|()| w.write_bit(true)) |
804 | | } else { |
805 | | w.write(B - 1, value).and_then(|()| w.write_bit(false)) |
806 | | } |
807 | | } |
808 | | |
809 | | #[inline] |
810 | | fn read_primitive<R, V>(r: &mut R) -> io::Result<V> |
811 | | where |
812 | | R: BitRead, |
813 | | V: Primitive, |
814 | | { |
815 | | let mut buffer = V::buffer(); |
816 | | r.read_bytes(buffer.as_mut())?; |
817 | | Ok(V::from_le_bytes(buffer)) |
818 | | } |
819 | | |
820 | | #[inline] |
821 | | fn write_primitive<W, V>(w: &mut W, value: V) -> io::Result<()> |
822 | | where |
823 | | W: BitWrite, |
824 | | V: Primitive, |
825 | | { |
826 | | w.write_bytes(value.to_le_bytes().as_ref()) |
827 | | } |
828 | | |
829 | | fn read_numeric<R, V>(mut r: R) -> io::Result<V> |
830 | | where |
831 | | R: io::Read, |
832 | | V: Primitive, |
833 | | { |
834 | | let mut buffer = V::buffer(); |
835 | | r.read_exact(buffer.as_mut())?; |
836 | | Ok(V::from_le_bytes(buffer)) |
837 | | } |
838 | | |
839 | | #[inline] |
840 | | fn write_numeric<W, V>(mut w: W, value: V) -> io::Result<()> |
841 | | where |
842 | | W: io::Write, |
843 | | V: Primitive, |
844 | | { |
845 | | w.write_all(value.to_le_bytes().as_ref()) |
846 | | } |
847 | | } |
848 | | |
849 | | /// A queue for efficiently pushing bits onto a value |
850 | | /// and popping them off a value. |
851 | | #[derive(Clone, Debug, Default)] |
852 | | pub struct BitQueue<E: Endianness, N: Numeric> { |
853 | | phantom: PhantomData<E>, |
854 | | value: N, |
855 | | bits: u32, |
856 | | } |
857 | | |
858 | | impl<E: Endianness, N: Numeric> BitQueue<E, N> { |
859 | | /// Returns a new empty queue |
860 | | #[inline] |
861 | 0 | pub fn new() -> BitQueue<E, N> { |
862 | 0 | BitQueue { |
863 | 0 | phantom: PhantomData, |
864 | 0 | value: N::default(), |
865 | 0 | bits: 0, |
866 | 0 | } |
867 | 0 | } Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u8>>::new Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u8>>::new |
868 | | |
869 | | /// Creates a new queue from the given value with the given size |
870 | | /// Panics if the value is larger than the given number of bits. |
871 | | #[inline] |
872 | 0 | pub fn from_value(value: N, bits: u32) -> BitQueue<E, N> { |
873 | 0 | assert!(if bits < N::BITS_SIZE { |
874 | 0 | value < (N::ONE << bits) |
875 | | } else { |
876 | 0 | bits <= N::BITS_SIZE |
877 | | }); |
878 | 0 | BitQueue { |
879 | 0 | phantom: PhantomData, |
880 | 0 | value, |
881 | 0 | bits, |
882 | 0 | } |
883 | 0 | } Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u64>>::from_value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i8>>::from_value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u8>>::from_value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i32>>::from_value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u32>>::from_value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i16>>::from_value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u16>>::from_value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u64>>::from_value |
884 | | |
885 | | /// Sets the queue to a given value with the given number of bits |
886 | | /// Panics if the value is larger than the given number of bits |
887 | | #[inline] |
888 | | pub fn set(&mut self, value: N, bits: u32) { |
889 | | assert!(if bits < N::BITS_SIZE { |
890 | | value < (N::ONE << bits) |
891 | | } else { |
892 | | bits <= N::BITS_SIZE |
893 | | }); |
894 | | self.value = value; |
895 | | self.bits = bits; |
896 | | } |
897 | | |
898 | | /// Consumes the queue and returns its current value |
899 | | #[inline(always)] |
900 | 0 | pub fn value(self) -> N { |
901 | 0 | self.value |
902 | 0 | } Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u64>>::value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i8>>::value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u8>>::value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i32>>::value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u32>>::value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i16>>::value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u16>>::value Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u64>>::value |
903 | | |
904 | | /// Returns the total bits in the queue |
905 | | #[inline(always)] |
906 | 0 | pub fn len(&self) -> u32 { |
907 | 0 | self.bits |
908 | 0 | } Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u8>>::len Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u64>>::len Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i8>>::len Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u8>>::len Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i32>>::len Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u32>>::len Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i16>>::len Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u16>>::len Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u64>>::len |
909 | | |
910 | | /// Returns the maximum bits the queue can hold |
911 | | #[inline(always)] |
912 | 0 | pub fn max_len(&self) -> u32 { |
913 | 0 | N::BITS_SIZE |
914 | 0 | } Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u8>>::max_len Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u8>>::max_len |
915 | | |
916 | | /// Returns the remaining bits the queue can hold |
917 | | #[inline(always)] |
918 | 0 | pub fn remaining_len(&self) -> u32 { |
919 | 0 | self.max_len() - self.len() |
920 | 0 | } Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u8>>::remaining_len Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u8>>::remaining_len |
921 | | |
922 | | /// Returns true if the queue is empty |
923 | | #[inline(always)] |
924 | 0 | pub fn is_empty(&self) -> bool { |
925 | 0 | self.bits == 0 |
926 | 0 | } Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u8>>::is_empty Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u8>>::is_empty |
927 | | |
928 | | /// Returns true if the queue is full |
929 | | #[inline(always)] |
930 | 0 | pub fn is_full(&self) -> bool { |
931 | 0 | self.bits == N::BITS_SIZE |
932 | 0 | } |
933 | | |
934 | | /// Drops all values in the queue |
935 | | #[inline(always)] |
936 | | pub fn clear(&mut self) { |
937 | | self.set(N::default(), 0) |
938 | | } |
939 | | |
940 | | /// Returns true if all bits remaining in the queue are 0 |
941 | | #[inline(always)] |
942 | | pub fn all_0(&self) -> bool { |
943 | | self.value.count_ones() == 0 |
944 | | } |
945 | | |
946 | | /// Returns true if all bits remaining in the queue are 1 |
947 | | #[inline(always)] |
948 | | pub fn all_1(&self) -> bool { |
949 | | self.value.count_ones() == self.bits |
950 | | } |
951 | | |
952 | | /// Pushes a value with the given number of bits onto the tail of the queue |
953 | | /// Panics if the number of bits pushed is larger than the queue can hold. |
954 | | #[inline(always)] |
955 | 0 | pub fn push(&mut self, bits: u32, value: N) { |
956 | 0 | assert!(bits <= self.remaining_len()); // check for overflow |
957 | 0 | E::push(self, bits, value) |
958 | 0 | } Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u8>>::push Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u8>>::push |
959 | | |
960 | | /// Pushes a value with the given number of bits onto the tail of the queue |
961 | | /// Panics if the number of bits pushed is larger than the queue can hold. |
962 | | #[inline(always)] |
963 | 0 | pub fn push_fixed<const B: u32>(&mut self, value: N) { |
964 | 0 | assert!(B <= self.remaining_len()); // check for overflow |
965 | 0 | E::push_fixed::<B, N>(self, value) |
966 | 0 | } |
967 | | |
968 | | /// Pops a value with the given number of bits from the head of the queue |
969 | | /// Panics if the number of bits popped is larger than the number |
970 | | /// of bits in the queue. |
971 | | #[inline(always)] |
972 | 0 | pub fn pop(&mut self, bits: u32) -> N { |
973 | 0 | assert!(bits <= self.len()); // check for underflow |
974 | 0 | E::pop(self, bits) |
975 | 0 | } Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u8>>::pop Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u64>>::pop Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i8>>::pop Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u8>>::pop Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i32>>::pop Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u32>>::pop Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i16>>::pop Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u16>>::pop Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u64>>::pop |
976 | | |
977 | | /// Pops a value with the given number of bits from the head of the queue |
978 | 0 | pub fn pop_fixed<const B: u32>(&mut self) -> N { |
979 | 0 | assert!(B <= self.len()); // check for underflow |
980 | 0 | E::pop_fixed::<B, N>(self) |
981 | 0 | } Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::LittleEndian, u64>>::pop_fixed::<8> Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i8>>::pop_fixed::<8> Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u8>>::pop_fixed::<8> Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i32>>::pop_fixed::<8> Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u32>>::pop_fixed::<8> Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, i16>>::pop_fixed::<8> Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u16>>::pop_fixed::<8> Unexecuted instantiation: <bitstream_io::BitQueue<bitstream_io::BigEndian, u64>>::pop_fixed::<8> |
982 | | |
983 | | /// Pops all the current bits from the queue |
984 | | /// and resets it to an empty state. |
985 | | #[inline] |
986 | | pub fn pop_all(&mut self) -> N { |
987 | | let to_return = self.value; |
988 | | self.value = N::default(); |
989 | | self.bits = 0; |
990 | | to_return |
991 | | } |
992 | | |
993 | | /// Drops the given number of bits from the head of the queue |
994 | | /// without returning them. |
995 | | /// Panics if the number of bits dropped is larger than the |
996 | | /// number of bits in the queue. |
997 | | #[inline(always)] |
998 | | pub fn drop(&mut self, bits: u32) { |
999 | | assert!(bits <= self.len()); // check for underflow |
1000 | | E::drop(self, bits) |
1001 | | } |
1002 | | |
1003 | | /// Pops all 0 bits up to and including the next 1 bit |
1004 | | /// and returns the amount of 0 bits popped |
1005 | | #[inline] |
1006 | | pub fn pop_0(&mut self) -> u32 { |
1007 | | let zeros = E::next_zeros(self); |
1008 | | self.drop(zeros + 1); |
1009 | | zeros |
1010 | | } |
1011 | | |
1012 | | /// Pops all 1 bits up to and including the next 0 bit |
1013 | | /// and returns the amount of 1 bits popped |
1014 | | #[inline] |
1015 | | pub fn pop_1(&mut self) -> u32 { |
1016 | | let ones = E::next_ones(self); |
1017 | | self.drop(ones + 1); |
1018 | | ones |
1019 | | } |
1020 | | } |
1021 | | |
1022 | | impl<E: Endianness> BitQueue<E, u8> { |
1023 | | /// Returns the state of the queue as a single value |
1024 | | /// which can be used to perform lookups. |
1025 | | #[inline(always)] |
1026 | | pub fn to_state(&self) -> usize { |
1027 | | (1 << self.bits) | (self.value as usize) |
1028 | | } |
1029 | | } |