#![allow(dead_code)]
pub struct BitReader<'a> {
data: &'a [u8],
position: usize, }
impl<'a> BitReader<'a> {
pub fn new(data: &'a [u8]) -> Self {
Self { data, position: 0 }
}
pub fn with_offset(data: &'a [u8], byte_offset: usize) -> Self {
Self {
data,
position: byte_offset * 8,
}
}
pub fn position(&self) -> usize {
self.position
}
pub fn set_position(&mut self, pos: usize) {
self.position = pos;
}
#[inline]
fn check_bit(&self, bit_pos: usize) -> u32 {
let byte_idx = bit_pos / 8;
let bit_idx = 7 - (bit_pos % 8);
if byte_idx < self.data.len() {
((self.data[byte_idx] >> bit_idx) & 1) as u32
} else {
0
}
}
pub fn peek(&self, bits: usize) -> u32 {
if bits == 0 || bits > 32 {
return 0;
}
let mut value: u32 = 0;
for i in 0..bits {
value = (value << 1) | self.check_bit(self.position + i);
}
value
}
pub fn read(&mut self, bits: usize) -> u32 {
let value = self.peek(bits);
self.position += bits;
value
}
pub fn skip(&mut self, bits: usize) {
self.position += bits;
}
#[inline]
pub fn read_bit(&mut self) -> bool {
let result = self.check_bit(self.position) != 0;
self.position += 1;
result
}
pub fn remaining_bits(&self) -> usize {
let total_bits = self.data.len() * 8;
total_bits.saturating_sub(self.position)
}
pub fn has_bits(&self, bits: usize) -> bool {
self.remaining_bits() >= bits
}
pub fn read_signed(&mut self, bits: usize) -> i32 {
if bits == 0 {
return 0;
}
let value = self.read(bits) as i32;
let sign_bit = 1 << (bits - 1);
if value & sign_bit != 0 {
value | ((-1i32) << bits)
} else {
value
}
}
pub fn read_scale_count(&mut self) -> (u32, u32) {
let delta_bits = self.read(3);
if delta_bits == 0 {
return (0, 0);
}
let count = self.read(delta_bits as usize);
let resolution = self.read(4);
(count + 1, resolution)
}
pub fn read_off_by_one(&mut self, bits: usize) -> u32 {
let value = self.read(bits);
if value != 0 {
value + 1
} else {
0
}
}
}
pub struct BitWriter {
data: Vec<u8>,
position: usize,
}
impl BitWriter {
pub fn new(capacity: usize) -> Self {
Self {
data: vec![0; capacity],
position: 0,
}
}
pub fn write(&mut self, value: u32, bits: usize) {
if bits == 0 || bits > 32 {
return;
}
for i in 0..bits {
let bit = (value >> (bits - 1 - i)) & 1;
let byte_idx = self.position / 8;
let bit_idx = 7 - (self.position % 8);
if byte_idx < self.data.len() {
if bit != 0 {
self.data[byte_idx] |= 1 << bit_idx;
} else {
self.data[byte_idx] &= !(1 << bit_idx);
}
}
self.position += 1;
}
}
pub fn data(&self) -> &[u8] {
&self.data
}
pub fn position(&self) -> usize {
self.position
}
pub fn into_vec(self) -> Vec<u8> {
self.data
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_bits() {
let data = [0b10110100, 0b01101001];
let mut reader = BitReader::new(&data);
assert_eq!(reader.read(1), 1); assert_eq!(reader.read(1), 0); assert_eq!(reader.read(2), 0b11); assert_eq!(reader.read(4), 0b0100); assert_eq!(reader.read(4), 0b0110); }
#[test]
fn test_peek() {
let data = [0b10110100];
let reader = BitReader::new(&data);
assert_eq!(reader.peek(4), 0b1011);
assert_eq!(reader.peek(8), 0b10110100);
}
#[test]
fn test_skip() {
let data = [0b10110100, 0b01101001];
let mut reader = BitReader::new(&data);
reader.skip(4);
assert_eq!(reader.read(4), 0b0100);
}
#[test]
fn test_read_signed() {
let data = [0b11110000];
let mut reader = BitReader::new(&data);
assert_eq!(reader.read_signed(4), -1);
}
#[test]
fn test_bit_writer() {
let mut writer = BitWriter::new(2);
writer.write(0b1011, 4);
writer.write(0b0100, 4);
assert_eq!(writer.data()[0], 0b10110100);
}
}