163 lines
3.7 KiB
Rust
163 lines
3.7 KiB
Rust
//! Bit streams.
|
|
|
|
use crate::err::*;
|
|
|
|
/// Reads `width` bits from `b` starting at bit `cr_bit` into an integer, most
|
|
/// significant bit first.
|
|
///
|
|
/// # Errors
|
|
///
|
|
/// The function will return an error if `width` is more than 64, or if
|
|
/// `(cr_bit + width - 1) / 8` would overflow an index into `b`.
|
|
pub fn read_bits_b(b: &[u8], cr_bit: usize, width: u8) -> ResultS<u64>
|
|
{
|
|
if width == 0 {
|
|
return Ok(0);
|
|
}
|
|
|
|
if width > 64 {
|
|
bail!("invalid number of bits");
|
|
}
|
|
|
|
let last = (cr_bit + usize::from(width) - 1) / 8;
|
|
|
|
if last >= b.len() {
|
|
bail!("not enough data");
|
|
}
|
|
|
|
let mut byte_ptr = cr_bit / 8;
|
|
let mut bits_ptr = cr_bit % 8;
|
|
|
|
let mut res = 0;
|
|
|
|
for _ in 0..width {
|
|
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;
|
|
}
|
|
}
|
|
|
|
Ok(res)
|
|
}
|
|
|
|
/// The same as `read_bits_b`, but least-significant bit first.
|
|
pub fn read_bits_l(b: &[u8], cr_bit: usize, width: u8) -> ResultS<u64>
|
|
{
|
|
if width == 0 {
|
|
Ok(0)
|
|
} else {
|
|
let res = read_bits_b(b, cr_bit, width)?;
|
|
|
|
Ok(reverse_bits(res) >> (64 - width))
|
|
}
|
|
}
|
|
|
|
// FIXME: change this to u64::reverse_bits when stabilized
|
|
const fn reverse_bits(v: u64) -> u64
|
|
{
|
|
let v = v >> 1 & 0x5555_5555_5555_5555 | ((v & 0x5555_5555_5555_5555) << 1);
|
|
let v = v >> 2 & 0x3333_3333_3333_3333 | ((v & 0x3333_3333_3333_3333) << 2);
|
|
let v = v >> 4 & 0x0F0F_0F0F_0F0F_0F0F | ((v & 0x0F0F_0F0F_0F0F_0F0F) << 4);
|
|
v.swap_bytes()
|
|
}
|
|
|
|
#[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 = read_bits_b(INPUT, p, 3).unwrap();
|
|
assert_eq!(n, 0b101);
|
|
p += 3;
|
|
|
|
let n = read_bits_b(INPUT, p, 63).unwrap();
|
|
assert_eq!(n, 0b001100101010100001000000000001111111110000111001101011100110010);
|
|
p += 63;
|
|
|
|
let n = read_bits_b(INPUT, p, 4).unwrap();
|
|
assert_eq!(n, 0b1001);
|
|
p += 4;
|
|
|
|
let n = read_bits_b(INPUT, p, 7).unwrap();
|
|
assert_eq!(n, 0b0100000);
|
|
p += 7;
|
|
|
|
let n = read_bits_b(INPUT, p, 17).unwrap();
|
|
assert_eq!(n, 0b11111100000100000);
|
|
p += 17;
|
|
|
|
let n = read_bits_b(INPUT, p, 27).unwrap();
|
|
assert_eq!(n, 0b000101001111110101110101000);
|
|
p += 27;
|
|
|
|
let n = read_bits_b(INPUT, p, 33).unwrap();
|
|
assert_eq!(n, 0b101011010101011110001011010101010);
|
|
p += 33;
|
|
|
|
let n = read_bits_b(INPUT, p, 6).unwrap();
|
|
assert_eq!(n, 0b000011);
|
|
p += 6;
|
|
|
|
let e = read_bits_b(INPUT, p, 1);
|
|
assert!(if let Err(_) = e {true} else {false});
|
|
|
|
let e = read_bits_b(INPUT, p, 2);
|
|
assert!(if let Err(_) = e {true} else {false});
|
|
|
|
let mut p = 0;
|
|
|
|
let n = read_bits_l(INPUT, 0, 3).unwrap();
|
|
assert_eq!(n, 0b101);
|
|
p += 3;
|
|
|
|
let n = read_bits_l(INPUT, p, 63).unwrap();
|
|
assert_eq!(n, 0b010011001110101100111000011111111100000000000100001010101001100);
|
|
p += 63;
|
|
|
|
let n = read_bits_l(INPUT, p, 4).unwrap();
|
|
assert_eq!(n, 0b1001);
|
|
p += 4;
|
|
|
|
let n = read_bits_l(INPUT, p, 7).unwrap();
|
|
assert_eq!(n, 0b0000010);
|
|
p += 7;
|
|
|
|
let n = read_bits_l(INPUT, p, 17).unwrap();
|
|
assert_eq!(n, 0b00000100000111111);
|
|
p += 17;
|
|
|
|
let n = read_bits_l(INPUT, p, 27).unwrap();
|
|
assert_eq!(n, 0b000101011101011111100101000);
|
|
p += 27;
|
|
|
|
let n = read_bits_l(INPUT, p, 33).unwrap();
|
|
assert_eq!(n, 0b010101010110100011110101010110101);
|
|
p += 33;
|
|
|
|
let n = read_bits_l(INPUT, p, 6).unwrap();
|
|
assert_eq!(n, 0b110000);
|
|
p += 6;
|
|
|
|
let e = read_bits_l(INPUT, p, 1);
|
|
assert!(if let Err(_) = e {true} else {false});
|
|
|
|
let e = read_bits_l(INPUT, p, 2);
|
|
assert!(if let Err(_) = e {true} else {false});
|
|
}
|
|
|
|
// EOF
|