///|
/// Create a new LSB-first bit reader from bytes.
fn new_bit_reader(data : Bytes) -> BitReader {
BitReader::{ data, length_bits: data.length() * 8, bit_pos: 0 }
}
///|
/// Read n bits from the bitstream (LSB-first). Returns the value.
fn read_bits(br : BitReader, n : Int) -> Int raise AudioError {
if n == 0 {
return 0
}
if br.bit_pos + n > br.length_bits {
raise AudioError::DecodeFailed("read_bits: not enough bits remaining")
}
let mut result = 0
for i in 0..> bit_idx) & 1
result = result | (bit << i)
}
br.bit_pos = br.bit_pos + n
result
}
///|
/// Read a single bit from the bitstream.
fn read_bit(br : BitReader) -> Bool raise AudioError {
if br.bit_pos >= br.length_bits {
raise AudioError::DecodeFailed("read_bit: no bits remaining")
}
let byte_idx = br.bit_pos / 8
let bit_idx = br.bit_pos % 8
let bit = (br.data[byte_idx].to_int() >> bit_idx) & 1
br.bit_pos = br.bit_pos + 1
bit == 1
}
///|
/// Return the number of bits remaining in the reader.
fn bits_remaining(br : BitReader) -> Int {
br.length_bits - br.bit_pos
}
///|
/// Align the bit position to the next byte boundary.
fn byte_align(br : BitReader) -> Unit {
let remainder = br.bit_pos % 8
if remainder != 0 {
br.bit_pos = br.bit_pos + (8 - remainder)
}
}
///|
test "bitreader LSB-first read_bits" {
// Byte 0xB1 = 10110001
// LSB-first: bits 0,1,2 = 1,0,0 = 0b001 = 1
let data = Bytes::from_array([b'\xB1'])
let br = new_bit_reader(data)
let v = read_bits(br, 3)
assert_eq(v, 1)
}
///|
test "bitreader read_bits multi-byte" {
let data = Bytes::from_array([b'\xFF', b'\x00'])
let br = new_bit_reader(data)
let v = read_bits(br, 8)
assert_eq(v, 255)
let v2 = read_bits(br, 8)
assert_eq(v2, 0)
}
///|
test "bitreader read_bits across byte boundary" {
// 0xAB = 10101011, 0xCD = 11001101
// Read 12 bits LSB-first: bits 0-7 from byte0 = 0xAB = 171
// bits 8-11 from byte1 bits 0-3 = low nibble of 0xCD = 0xD = 13
// result = 171 | (13 << 8) = 0xDAB
let data = Bytes::from_array([b'\xAB', b'\xCD'])
let br = new_bit_reader(data)
let v = read_bits(br, 12)
assert_eq(v, 0xDAB)
}
///|
test "bitreader read_bit" {
let data = Bytes::from_array([b'\x05']) // 00000101
let br = new_bit_reader(data)
assert_true(read_bit(br) == true) // bit 0 = 1
assert_true(read_bit(br) == false) // bit 1 = 0
assert_true(read_bit(br) == true) // bit 2 = 1
assert_true(read_bit(br) == false) // bit 3 = 0
}
///|
test "bitreader bits_remaining" {
let data = Bytes::from_array([b'\x00', b'\x00'])
let br = new_bit_reader(data)
assert_eq(bits_remaining(br), 16)
read_bits(br, 5) |> ignore
assert_eq(bits_remaining(br), 11)
}
///|
test "bitreader byte_align" {
let data = Bytes::from_array([b'\xFF', b'\xAB'])
let br = new_bit_reader(data)
read_bits(br, 3) |> ignore
byte_align(br)
assert_eq(bits_remaining(br), 8)
let v = read_bits(br, 8)
assert_eq(v, 0xAB)
}
///|
test "bitreader read_bits error on overflow" {
let data = Bytes::from_array([b'\xFF'])
let br = new_bit_reader(data)
let mut caught = false
try read_bits(br, 9) |> ignore catch {
AudioError::DecodeFailed(_) => caught = true
_ => ()
}
assert_true(caught)
}
///|
test "bitreader read zero bits" {
let data = Bytes::from_array([b'\xFF'])
let br = new_bit_reader(data)
let v = read_bits(br, 0)
assert_eq(v, 0)
assert_eq(bits_remaining(br), 8)
}