Trait bitter::BitReader[][src]

pub trait BitReader {
Show 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_u64(&mut self) -> Option<u64>;
fn read_i64(&mut self) -> Option<i64>;
fn read_f32(&mut self) -> Option<f32>;
fn read_f64(&mut self) -> Option<f64>;
fn read_bits(&mut self, bits: i32) -> Option<u64>;
fn read_signed_bits(&mut self, bits: i32) -> Option<i64>;
fn if_get<T, F>(&mut self, f: F) -> Option<Option<T>>
    where
        F: FnMut(&mut Self) -> Option<T>
;
fn read_bits_max(&mut self, max: u64) -> Option<u64>;
fn read_bits_max_computed(&mut self, bits: i32, max: u64) -> Option<u64>;
fn read_bit_unchecked(&mut self) -> bool;
fn read_u8_unchecked(&mut self) -> u8;
fn read_i8_unchecked(&mut self) -> i8;
fn read_u16_unchecked(&mut self) -> u16;
fn read_i16_unchecked(&mut self) -> i16;
fn read_u32_unchecked(&mut self) -> u32;
fn read_i32_unchecked(&mut self) -> i32;
fn read_u64_unchecked(&mut self) -> u64;
fn read_i64_unchecked(&mut self) -> i64;
fn read_f32_unchecked(&mut self) -> f32;
fn read_f64_unchecked(&mut self) -> f64;
fn read_bits_unchecked(&mut self, bits: i32) -> u64;
fn read_signed_bits_unchecked(&mut self, bits: i32) -> i64;
fn if_get_unchecked<T, F>(&mut self, f: F) -> Option<T>
    where
        F: FnMut(&mut Self) -> T
;
fn read_bits_max_unchecked(&mut self, max: u64) -> u64;
fn read_bits_max_computed_unchecked(&mut self, bits: i32, max: u64) -> u64;
fn approx_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;
}
Expand description

Read bits in a given endian order

Required methods

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));

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));

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));

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));

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));

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));

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));

Consume 64 bits and return the deserialized long

use bitter::{BitReader, BigEndianReader};
let data = (22000u64).to_be_bytes();
let mut bits = BigEndianReader::new(&data);
assert_eq!(bits.read_u64(), Some(22000u64));

Consume 64 bits and return the deserialized long

use bitter::{BitReader, BigEndianReader};
let data = (-22000i64).to_be_bytes();
let mut bits = BigEndianReader::new(&data);
assert_eq!(bits.read_i64(), Some(-22000i64));

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));

Consume 64 bits and return the deserialized double 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));

Reads an arbitrary number of bits from 1 to 64 (inclusive) and returns the unsigned result

use bitter::{BitReader, BigEndianReader};
let mut bitter = BigEndianReader::new(&[0xff, 0x00, 0xab, 0xcd]);
assert_eq!(bitter.read_bits(32), Some(0xff00abcd));

Reads an arbitrary number of bits from 1 to 64 (inclusive) 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 bitter = BigEndianReader::new(&[0xfa, 0x93]);
assert_eq!(bitter.read_signed_bits(4), Some(-1));
assert_eq!(bitter.read_signed_bits(4), Some(-6));
assert_eq!(bitter.read_signed_bits(4), Some(-7));
assert_eq!(bitter.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 bitter = BigEndianReader::new(&[0xff]);
let mut bitter2 = BigEndianReader::new(&[0xff]);
assert_eq!(
    bitter.read_signed_bits(8).map(|x| x as i8),
    bitter2.read_i8()
);

If the next bit is available and on, decode the next chunk of data (which can return None). The return value can be one of the following:

  • None: Not enough data was available
  • Some(None): Bit was off so data not decoded
  • Some(x): Bit was on and data was decoded
use bitter::{LittleEndianReader, BitReader};
let mut bitter = LittleEndianReader::new(&[0xff, 0x04]);
assert_eq!(bitter.if_get(BitReader::read_u8), Some(Some(0x7f)));
assert_eq!(bitter.if_get(BitReader::read_u8), Some(None));
assert_eq!(bitter.if_get(BitReader::read_u8), None);

Reads a value from the stream that consumes the same or fewer number of bits of a given max. The value read will always be less than the given max.

For example if one wants to read a value that is less than 20, bitter will read at least 4 bits from the stream. If the 5th bit would cause the accumulator to exceed the max, the 5th bit is not consumed. Else the 5th bit is consumed and added to accumulator. If the necessary number of bits are not available, None is returned.

use bitter::{LittleEndianReader, BitReader};
let mut bitter = LittleEndianReader::new(&[0b1111_1000]);
assert_eq!(bitter.read_bits_max(20), Some(8));
assert_eq!(bitter.read_bits_max(20), Some(15));

Same as read_bits_max except that this function accepts the already computed number of bits to at least read. For instance, if 20 is the max, then 4 bits are at least needed.

In general, prefer read_bits_max for ease of use, as passing an incorrectly computed max can lead to undefined behavior

use bitter::{LittleEndianReader, BitReader};
let mut bitter = LittleEndianReader::new(&[0b1111_1000]);
assert_eq!(bitter.read_bits_max_computed(4, 20), Some(8));
assert_eq!(bitter.read_bits_max_computed(4, 20), Some(15));

Assumes there is at least one bit left in the stream.

use bitter::{LittleEndianReader, BitReader};
let mut bitter = LittleEndianReader::new(&[0b1010_1010, 0b0101_0101]);
assert_eq!(bitter.read_bit_unchecked(), false);

Assumes there is at least 8 bits left in the stream.

use bitter::{BigEndianReader, BitReader};
let mut bitter = BigEndianReader::new(&[0b1010_1010, 0b0101_0101]);
assert_eq!(bitter.read_u8_unchecked(), 0b1010_1010);

Assumes there is at least 8 bits left in the stream.

use bitter::{BigEndianReader, BitReader};
let mut bitter = BigEndianReader::new(&[0b1010_1010, 0b0101_0101]);
assert_eq!(bitter.read_i8_unchecked(), i8::from_be_bytes([0b1010_1010]));

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_unchecked(), 0xff93);

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_unchecked(), -500);

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_unchecked(), 22000u32);

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_unchecked(), -22000i32);

Consume 64 bits and return the deserialized long

use bitter::{BitReader, BigEndianReader};
let data = (22000u64).to_be_bytes();
let mut bits = BigEndianReader::new(&data);
assert_eq!(bits.read_u64_unchecked(), 22000u64);

Consume 64 bits and return the deserialized long

use bitter::{BitReader, BigEndianReader};
let data = (-22000i64).to_be_bytes();
let mut bits = BigEndianReader::new(&data);
assert_eq!(bits.read_i64_unchecked(), -22000i64);

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_unchecked(), 12.5f32);

Consume 64 bits and return the deserialized double floating point

use bitter::{BitReader, BigEndianReader};
let data = 12.5f64.to_be_bytes();
let mut bits = BigEndianReader::new(&data);
assert_eq!(bits.read_f64_unchecked(), 12.5f64);

Reads an arbitrary number of bits from 1 to 64 (inclusive) and returns the unsigned result

use bitter::{BitReader, BigEndianReader};
let mut bitter = BigEndianReader::new(&[0xff, 0x00, 0xab, 0xcd]);
assert_eq!(bitter.read_bits_unchecked(32), 0xff00abcd);

Reads an arbitrary number of bits from 1 to 64 (inclusive) and returns the signed result. See the discussion for the checked version of this API.

use bitter::{BitReader, BigEndianReader};
let mut bitter = BigEndianReader::new(&[0xff, 0x00, 0xab, 0xcd]);
let result = i64::from(i32::from_be_bytes([0xff, 0x00, 0xab, 0xcd]));
assert_eq!(bitter.read_signed_bits_unchecked(32), result);

If the next bit is available and on, decode the next chunk of data. The return value can be one of the following:

  • Some(None): Bit was off so data not decoded
  • Some(x): Bit was on and data was decoded
use bitter::{LittleEndianReader, BitReader};
let mut bitter = LittleEndianReader::new(&[0xff, 0x04]);
assert_eq!(bitter.if_get_unchecked(LittleEndianReader::read_u8_unchecked), Some(0x7f));
assert_eq!(bitter.if_get_unchecked(LittleEndianReader::read_u8_unchecked), None);

Reads a value from the stream that consumes the same or fewer number of bits of a given max. The value read will always be less than the given max.

For example if one wants to read a value that is less than 20, bitter will read at least 4 bits from the stream. If the 5th bit would cause the accumulator to exceed the max, the 5th bit is not consumed. Else the 5th bit is consumed and added to accumulator. If the necessary number of bits are not available, None is returned.

use bitter::{LittleEndianReader, BitReader};
let mut bitter = LittleEndianReader::new(&[0b1111_1000]);
assert_eq!(bitter.read_bits_max_unchecked(20), 8);
assert_eq!(bitter.read_bits_max_unchecked(20), 15);

Same as read_bits_max_unchecked except that this function accepts the already computed number of bits to at least read. For instance, if 20 is the max, then 4 bits are at least needed.

In general, prefer read_bits_max_unchecked for ease of use, as passing an incorrectly computed max can lead to undefined behavior

use bitter::{LittleEndianReader, BitReader};
let mut bitter = LittleEndianReader::new(&[0b1111_1000]);
assert_eq!(bitter.read_bits_max_computed_unchecked(4, 20), 8);
assert_eq!(bitter.read_bits_max_computed_unchecked(4, 20), 15);

Return approximately how many bytes are left in the bitstream. This can overestimate by one when the reader is at a position that is not byte aligned. Thus it is recommended to always compare with a greater than sign to avoid undefined behavior with unchecked reads

let mut bitter = LittleEndianReader::new(&[0xff]);
assert_eq!(bitter.approx_bytes_remaining(), 1);
assert!(bitter.read_bit().is_some());
assert_eq!(bitter.approx_bytes_remaining(), 1);
assert!(bitter.read_bits(7).is_some());
assert_eq!(bitter.approx_bytes_remaining(), 0);

Returns the exact number of bits remaining in the bitstream if the number of bits can fit within a usize. For large byte slices, the calculating the number of bits can cause an overflow, hence an Option is returned. See has_bits_remaining for a more performant and ergonomic alternative.

let mut bitter = LittleEndianReader::new(&[0xff]);
assert_eq!(bitter.bits_remaining(), Some(8));
assert!(bitter.read_bit().is_some());
assert_eq!(bitter.bits_remaining(), Some(7));
assert!(bitter.read_bits(7).is_some());
assert_eq!(bitter.bits_remaining(), Some(0));

Returns true if at least bits number of bits are left in the stream. A more performant and ergonomic way than bits_remaining.

let mut bitter = LittleEndianReader::new(&[0xff]);
assert!(bitter.has_bits_remaining(7));
assert!(bitter.has_bits_remaining(8));
assert!(!bitter.has_bits_remaining(9));

assert!(bitter.read_bit().is_some());
assert!(bitter.has_bits_remaining(7));
assert!(!bitter.has_bits_remaining(8));

assert!(bitter.read_bits(7).is_some());
assert!(!bitter.has_bits_remaining(7));
assert!(bitter.has_bits_remaining(0));

Read the number of bytes needed to fill the provided buffer. Returns whether the read was successful and the buffer has been filled.

let mut bitter = LittleEndianReader::new(&[0b1010_1010, 0b0101_0101]);
let mut buf = [0; 1];
assert_eq!(bitter.read_bit_unchecked(), false);
assert!(bitter.read_bytes(&mut buf));
assert_eq!(&buf, &[0b1101_0101]);
assert!(!bitter.read_bytes(&mut buf));

Returns if the bitstream has no bits left

let mut bitter = LittleEndianReader::new(&[0b1010_1010, 0b0101_0101]);
assert_eq!(bitter.is_empty(), false);
assert_eq!(bitter.read_u16_unchecked(), 0b0101_0101_1010_1010);
assert_eq!(bitter.is_empty(), true);

Implementors