You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

200 lines
4.1 KiB

//! Bit streams.
pub trait ReadBits {
/// Reads `width` bits from `b` starting at bit `cr_bit` into an
/// integer, most significant bit first.
///
/// # Errors
///
/// This function will return `None` if there are not enough bits left
/// in the buffer.
fn read_bits_be(b: &[u8], cr_bit: usize, width: usize) -> Option<Self>
where
Self: Sized;
/// The same as `read_bits_be`, but least-significant bit first.
///
/// # Errors
///
/// This function will return `None` if there are not enough bits left
/// in the buffer.
fn read_bits_le(b: &[u8], cr_bit: usize, width: usize) -> Option<Self>
where
Self: Sized;
}
macro_rules! read_bits_impl {
($t:ty) => {
#[allow(clippy::use_self)]
impl ReadBits for $t {
fn read_bits_be(b: &[u8], cr_bit: usize, mut width: usize) -> Option<Self> {
if width == 0 {
return Some(0);
}
let last = (cr_bit + width - 1) / 8;
if last >= b.len() {
return None;
}
let mut byte_ptr = cr_bit / 8;
let mut bits_ptr = cr_bit % 8;
let mut res = 0;
while width > 0 {
width -= 1;
res <<= 1;
if b[byte_ptr] & 1 << bits_ptr != 0 {
res |= 1;
}
bits_ptr += 1;
if bits_ptr > 7 {
bits_ptr = 0;
byte_ptr += 1;
}
}
Some(res)
}
fn read_bits_le(b: &[u8], cr_bit: usize, mut width: usize) -> Option<Self> {
if width == 0 {
return Some(0);
}
let last = (cr_bit + width - 1) / 8;
if last >= b.len() {
return None;
}
let mut byte_ptr = cr_bit / 8;
let mut bits_ptr = cr_bit % 8;
let mut res = 0;
let mut bit = 1;
while width > 0 {
width -= 1;
if b[byte_ptr] & 1 << bits_ptr != 0 {
res |= bit;
}
bit <<= 1;
bits_ptr += 1;
if bits_ptr > 7 {
bits_ptr = 0;
byte_ptr += 1;
}
}
Some(res)
}
}
};
}
read_bits_impl!(u8);
read_bits_impl!(u16);
read_bits_impl!(u32);
read_bits_impl!(u64);
read_bits_impl!(usize);
#[test]
fn bit_tests() {
const INPUT: &[u8] = &[
0b01100101, 0b10101010, 0b00010000, 0b00000000, 0b11111111, 0b11100001,
0b10101100, 0b00110011, 0b10100101, 0b11100000, 0b00000111, 0b00000001,
0b11001010, 0b10101111, 0b00101011, 0b01101010, 0b11010101, 0b10100011,
0b01010101, 0b11000001,
];
let mut p = 0;
let n = u8::read_bits_be(INPUT, p, 3).unwrap();
assert_eq!(n, 0b101);
p += 3;
let n = u64::read_bits_be(INPUT, p, 63).unwrap();
assert_eq!(
n,
0b001100101010100001000000000001111111110000111001101011100110010,
);
p += 63;
let n = u8::read_bits_be(INPUT, p, 4).unwrap();
assert_eq!(n, 0b1001);
p += 4;
let n = u8::read_bits_be(INPUT, p, 7).unwrap();
assert_eq!(n, 0b0100000);
p += 7;
let n = u32::read_bits_be(INPUT, p, 17).unwrap();
assert_eq!(n, 0b11111100000100000);
p += 17;
let n = u32::read_bits_be(INPUT, p, 27).unwrap();
assert_eq!(n, 0b000101001111110101110101000);
p += 27;
let n = u64::read_bits_be(INPUT, p, 33).unwrap();
assert_eq!(n, 0b101011010101011110001011010101010);
p += 33;
let n = usize::read_bits_be(INPUT, p, 6).unwrap();
assert_eq!(n, 0b000011);
p += 6;
assert!(u8::read_bits_be(INPUT, p, 1).is_none());
assert!(u8::read_bits_be(INPUT, p, 2).is_none());
p = 0;
let n = u8::read_bits_le(INPUT, 0, 3).unwrap();
assert_eq!(n, 0b101);
p += 3;
let n = u64::read_bits_le(INPUT, p, 63).unwrap();
assert_eq!(
n,
0b010011001110101100111000011111111100000000000100001010101001100,
);
p += 63;
let n = u8::read_bits_le(INPUT, p, 4).unwrap();
assert_eq!(n, 0b1001);
p += 4;
let n = u8::read_bits_le(INPUT, p, 7).unwrap();
assert_eq!(n, 0b0000010);
p += 7;
let n = u32::read_bits_le(INPUT, p, 17).unwrap();
assert_eq!(n, 0b00000100000111111);
p += 17;
let n = u32::read_bits_le(INPUT, p, 27).unwrap();
assert_eq!(n, 0b000101011101011111100101000);
p += 27;
let n = u64::read_bits_le(INPUT, p, 33).unwrap();
assert_eq!(n, 0b010101010110100011110101010110101);
p += 33;
let n = usize::read_bits_le(INPUT, p, 6).unwrap();
assert_eq!(n, 0b110000);
p += 6;
assert!(u8::read_bits_le(INPUT, p, 1).is_none());
assert!(u8::read_bits_le(INPUT, p, 2).is_none());
}
// EOF