pub trait BitReader {
Show 26 methods
// Required methods
fn read_bit(&mut self) -> Option<bool>;
fn read_u8(&mut self) -> Option<u8>;
fn read_i8(&mut self) -> Option<i8>;
fn read_u16(&mut self) -> Option<u16>;
fn read_i16(&mut self) -> Option<i16>;
fn read_u32(&mut self) -> Option<u32>;
fn read_i32(&mut self) -> Option<i32>;
fn read_f32(&mut self) -> Option<f32>;
fn read_u64(&mut self) -> Option<u64>;
fn read_i64(&mut self) -> Option<i64>;
fn read_f64(&mut self) -> Option<f64>;
fn read_bits(&mut self, bits: u32) -> Option<u64>;
fn read_signed_bits(&mut self, bits: u32) -> Option<i64>;
fn bytes_remaining(&self) -> usize;
fn unbuffered_bytes_remaining(&self) -> usize;
fn bits_remaining(&self) -> Option<usize>;
fn has_bits_remaining(&self, bits: usize) -> bool;
fn read_bytes(&mut self, buf: &mut [u8]) -> bool;
fn is_empty(&self) -> bool;
fn peek(&self, count: u32) -> u64;
fn consume(&mut self, count: u32);
fn refill_lookahead(&mut self);
fn lookahead_bits(&self) -> u32;
unsafe fn refill_lookahead_unchecked(&mut self);
fn byte_aligned(&self) -> bool;
fn remainder(&self) -> Remainder<'_>;
}Expand description
Read bits in a given endian order
Required Methods§
Sourcefn read_bit(&mut self) -> Option<bool>
fn read_bit(&mut self) -> Option<bool>
Consume a bit and return if the bit was enabled
use bitter::{BitReader, BigEndianReader};
let mut bits = BigEndianReader::new(&[0b1001_0011]);
assert_eq!(bits.read_bit(), Some(true));
assert_eq!(bits.read_bit(), Some(false));Sourcefn read_u8(&mut self) -> Option<u8>
fn read_u8(&mut self) -> Option<u8>
Consume 8 bits and return the deserialized byte
use bitter::{BitReader, BigEndianReader};
let mut bits = BigEndianReader::new(&[0b1001_0011]);
assert_eq!(bits.read_u8(), Some(0b1001_0011));Sourcefn read_i8(&mut self) -> Option<i8>
fn read_i8(&mut self) -> Option<i8>
Consume 8 bits and return the deserialized byte
use bitter::{BitReader, BigEndianReader};
let mut bits = BigEndianReader::new(&[0b1001_0011]);
assert_eq!(bits.read_i8(), Some(-109));Sourcefn read_u16(&mut self) -> Option<u16>
fn read_u16(&mut self) -> Option<u16>
Consume 16 bits and return the deserialized short
use bitter::{BitReader, LittleEndianReader};
let mut bits = LittleEndianReader::new(&[0b1001_0011, 0b1111_1111]);
assert_eq!(bits.read_u16(), Some(0xff93));Sourcefn read_i16(&mut self) -> Option<i16>
fn read_i16(&mut self) -> Option<i16>
Consume 16 bits and return the deserialized short
use bitter::{BitReader, LittleEndianReader};
let data = (-500i16).to_le_bytes();
let mut bits = LittleEndianReader::new(&data);
assert_eq!(bits.read_i16(), Some(-500));Sourcefn read_u32(&mut self) -> Option<u32>
fn read_u32(&mut self) -> Option<u32>
Consume 32 bits and return the deserialized int
use bitter::{BitReader, LittleEndianReader};
let data = (22000u32).to_le_bytes();
let mut bits = LittleEndianReader::new(&data);
assert_eq!(bits.read_u32(), Some(22000u32));Sourcefn read_i32(&mut self) -> Option<i32>
fn read_i32(&mut self) -> Option<i32>
Consume 32 bits and return the deserialized int
use bitter::{BitReader, BigEndianReader};
let data = (-22000i32).to_be_bytes();
let mut bits = BigEndianReader::new(&data);
assert_eq!(bits.read_i32(), Some(-22000i32));Sourcefn read_f32(&mut self) -> Option<f32>
fn read_f32(&mut self) -> Option<f32>
Consume 32 bits and return the deserialized floating point
use bitter::{BitReader, BigEndianReader};
let data = 12.5f32.to_be_bytes();
let mut bits = BigEndianReader::new(&data);
assert_eq!(bits.read_f32(), Some(12.5f32));Sourcefn read_u64(&mut self) -> Option<u64>
fn read_u64(&mut self) -> Option<u64>
Consume 64 bits and return the deserialized int
use bitter::{BitReader, LittleEndianReader};
let data = (22000u64).to_le_bytes();
let mut bits = LittleEndianReader::new(&data);
assert_eq!(bits.read_u64(), Some(22000u64));Sourcefn read_i64(&mut self) -> Option<i64>
fn read_i64(&mut self) -> Option<i64>
Consume 64 bits and return the deserialized int
use bitter::{BitReader, BigEndianReader};
let data = (-22000i64).to_be_bytes();
let mut bits = BigEndianReader::new(&data);
assert_eq!(bits.read_i64(), Some(-22000i64));Sourcefn read_f64(&mut self) -> Option<f64>
fn read_f64(&mut self) -> Option<f64>
Consume 64 bits and return the deserialized floating point
use bitter::{BitReader, BigEndianReader};
let data = 12.5f64.to_be_bytes();
let mut bits = BigEndianReader::new(&data);
assert_eq!(bits.read_f64(), Some(12.5f64));Sourcefn read_bits(&mut self, bits: u32) -> Option<u64>
fn read_bits(&mut self, bits: u32) -> Option<u64>
Reads an arbitrary number of bits in the range of [0, 64] and returns the unsigned result
use bitter::{BitReader, BigEndianReader};
let mut bits = BigEndianReader::new(&[0xff, 0x00, 0xab, 0xcd]);
assert_eq!(bits.read_bits(32), Some(0xff00abcd));Sourcefn read_signed_bits(&mut self, bits: u32) -> Option<i64>
fn read_signed_bits(&mut self, bits: u32) -> Option<i64>
Reads an arbitrary number of bits in the range of [0, 64] and returns the signed result.
If the most significant bit is enabled, the result will be negative. This can be somewhat counterintuitive so see the examples
use bitter::{BitReader, BigEndianReader};
let mut bits = BigEndianReader::new(&[0xfa, 0x93]);
assert_eq!(bits.read_signed_bits(4), Some(-1));
assert_eq!(bits.read_signed_bits(4), Some(-6));
assert_eq!(bits.read_signed_bits(4), Some(-7));
assert_eq!(bits.read_signed_bits(4), Some(3));To think of it another way, reading the number of bits equivalent to a builtin type (i8, i16, etc), will always equal its associated ergonomic equivalent when casted.
use bitter::{BitReader, BigEndianReader};
let mut bits = BigEndianReader::new(&[0xff]);
let mut bitter2 = BigEndianReader::new(&[0xff]);
assert_eq!(
bits.read_signed_bits(8).map(|x| x as i8),
bitter2.read_i8()
);Sourcefn bytes_remaining(&self) -> usize
fn bytes_remaining(&self) -> usize
Returns how many complete bytes are left in the bitstream.
let mut bits = LittleEndianReader::new(&[0xff]);
assert_eq!(bits.bytes_remaining(), 1);
assert!(bits.read_bit().is_some());
assert_eq!(bits.bytes_remaining(), 0);
assert!(bits.read_bits(7).is_some());
assert_eq!(bits.bytes_remaining(), 0);Sourcefn unbuffered_bytes_remaining(&self) -> usize
fn unbuffered_bytes_remaining(&self) -> usize
Returns how many bytes are still left in the passed in buffer.
How many bytes remain in the original buffer is typically an
implementation detail, and one should prefer
BitReader::bytes_remaining, which includes bytes in the lookahead
buffer.
However, the bitter unchecked API,
BitReader::refill_lookahead_unchecked, requires this same
calculation to avoid undefined behavior.
Anecdotally the use of this function can assist the compiler in
eliminating branches that would appear in
BitReader::refill_lookahead without needing to introduce unsafe
blocks. Your mileage may vary.
let mut bits = LittleEndianReader::new(&[0u8; 100]);
if bits.unbuffered_bytes_remaining() >= 16 {
// The compiler can eliminate the end of buffer checks
// in both of these refills without needing to drop to unsafe
bits.refill_lookahead();
// ... do some reading ...
bits.refill_lookahead();
}Sourcefn bits_remaining(&self) -> Option<usize>
fn bits_remaining(&self) -> Option<usize>
Returns the exact number of bits remaining in the bitstream if the
number of bits can fit within a usize. For large byte slices,
calculating the number of bits can cause an overflow, hence an Option
is returned. See has_bits_remaining
for a more robust, performant, and ergonomic alternative.
let mut bits = LittleEndianReader::new(&[0xff]);
assert_eq!(bits.bits_remaining(), Some(8));
assert!(bits.read_bit().is_some());
assert_eq!(bits.bits_remaining(), Some(7));
assert!(bits.read_bits(7).is_some());
assert_eq!(bits.bits_remaining(), Some(0));Sourcefn has_bits_remaining(&self, bits: usize) -> bool
fn has_bits_remaining(&self, bits: usize) -> bool
Returns true if at least bits number of bits are left in the stream. A
more robust, performant, and ergonomic way than
bits_remaining.
let mut bits = LittleEndianReader::new(&[0xff]);
assert!(bits.has_bits_remaining(7));
assert!(bits.has_bits_remaining(8));
assert!(!bits.has_bits_remaining(9));
assert!(bits.read_bit().is_some());
assert!(bits.has_bits_remaining(7));
assert!(!bits.has_bits_remaining(8));
assert!(bits.read_bits(7).is_some());
assert!(!bits.has_bits_remaining(7));
assert!(bits.has_bits_remaining(0));Sourcefn read_bytes(&mut self, buf: &mut [u8]) -> bool
fn read_bytes(&mut self, buf: &mut [u8]) -> bool
Read the number of bytes needed to fill the provided buffer. Returns whether the read was successful and the buffer has been filled. If there aren’t enough bytes remaining, then the bit stream and buffer remains unchanged
let mut bits = LittleEndianReader::new(&[0b1010_1010, 0b0101_0101]);
let mut buf = [0; 1];
assert_eq!(bits.read_bit(), Some(false));
assert!(bits.read_bytes(&mut buf));
assert_eq!(&buf, &[0b1101_0101]);
assert!(!bits.read_bytes(&mut buf));
assert_eq!(bits.read_bits(1), Some(0));Sourcefn is_empty(&self) -> bool
fn is_empty(&self) -> bool
Returns if the bitstream has no bits left
let mut bits = LittleEndianReader::new(&[0b1010_1010, 0b0101_0101]);
assert_eq!(bits.is_empty(), false);
assert_eq!(bits.read_u16(), Some(0b0101_0101_1010_1010));
assert_eq!(bits.is_empty(), true);Sourcefn peek(&self, count: u32) -> u64
fn peek(&self, count: u32) -> u64
Peeks at the given number of bits in the lookahead buffer
It is invalid to peek at more than what was returned in the last refill
A core tenent of Manual Mode: refill / peek / consume
Sourcefn consume(&mut self, count: u32)
fn consume(&mut self, count: u32)
Consumes the number of bits from the lookahead buffer
A core tenent of Manual Mode: refill / peek / consume
Sourcefn refill_lookahead(&mut self)
fn refill_lookahead(&mut self)
Refills the lookahead buffer.
A core tenent of Manual Mode: refill / peek / consume
Refills the lookahead buffer anywhere between [MAX_READ_BITS, 64] as
long as the end of the stream has not been reached. See how many bits
are in the buffer with BitReader::lookahead_bits.
If BitReader::lookahead_bits is already in the specified range,
additional refills will have no effect.
Sourcefn lookahead_bits(&self) -> u32
fn lookahead_bits(&self) -> u32
Returns the number of bits in the lookahead buffer
These are the number of bits available to be consumed before a refill is necessary.
Guaranteed to be between [MAX_READ_BITS, 64] when at least 8 bytes
of data remains unread.
Sourceunsafe fn refill_lookahead_unchecked(&mut self)
unsafe fn refill_lookahead_unchecked(&mut self)
Refills the lookahead buffer without bounds checking
After calling, the lookahead buffer is guaranteed to have between
[MAX_READ_BITS, 64] bits available to read.
§Safety
This function assumes that there are at least 8 bytes left unbuffered for an unaligned read. It is undefined behavior if there is less than 8 bytes remaining
Guard all usages with BitReader::unbuffered_bytes_remaining
let mut bits = LittleEndianReader::new(&[0u8; 100]);
let objects_to_read = 7;
let object_bits = 39;
let desired_bits = objects_to_read * object_bits;
let bytes_needed = (desired_bits as f64 / 8.0).ceil();
if bits.unbuffered_bytes_remaining() >= bytes_needed as usize {
for _ in 0..objects_to_read {
unsafe { bits.refill_lookahead_unchecked() };
let _field1 = bits.peek(10);
bits.consume(10);
let _field2 = bits.peek(29);
bits.consume(29);
}
}Sourcefn byte_aligned(&self) -> bool
fn byte_aligned(&self) -> bool
Returns true if the reader is not partway through a byte
let mut bits = LittleEndianReader::new(&[0b1010_1010, 0b0101_0101]);
let mut buf = [0; 1];
assert!(bits.byte_aligned());
assert_eq!(bits.read_bit(), Some(false));
assert!(!bits.byte_aligned());Sourcefn remainder(&self) -> Remainder<'_>
fn remainder(&self) -> Remainder<'_>
Returns the remainder of unread data.
let mut bits = LittleEndianReader::new(&[0b1010_1010, 0b0101_0101, 0b1100_0011]);
// When byte-aligned, no partial bits
let remainder = bits.remainder();
assert_eq!(remainder.partial_bits(), 0);
assert_eq!(remainder.data(), &[0b1010_1010, 0b0101_0101, 0b1100_0011]);
// After reading 3 bits, we have 5 bits remaining in a partially read byte
assert_eq!(bits.read_bits(3), Some(0b010));
let remainder = bits.remainder();
assert_eq!(remainder.partial_bits(), 5);
assert_eq!(remainder.partial_byte(), 0b0001_0101);
assert_eq!(remainder.data(), &[0b0101_0101, 0b1100_0011]);