use crate::bit_reader::{bit_width, BitRead};
#[derive(Debug, Clone, Default)]
pub struct FixedWidthIntArray {
pub count: u32,
pub value_bit_width: u8,
pub index_bit_width: u8,
pub values: Vec<u32>,
}
impl FixedWidthIntArray {
pub fn is_active(&self) -> bool {
self.count > 0 && self.value_bit_width > 0 && self.values.len() == self.count as usize
}
pub fn read(reader: &mut impl BitRead) -> Option<Self> {
let count = reader.read_bits(24)?;
let value_bit_width = reader.read_bits(8)? as u8;
let index_bit_width = if count > 0 { bit_width(count) } else { 0 };
if count == 0 || value_bit_width == 0 {
return Some(Self {
count,
value_bit_width,
index_bit_width,
values: Vec::new(),
});
}
if value_bit_width > 32 {
let bits_to_skip = count as usize * value_bit_width as usize;
reader.skip_bits(bits_to_skip);
return Some(Self {
count,
value_bit_width,
index_bit_width,
values: Vec::new(),
});
}
if count > 1_000_000 {
return None;
}
let mut values = Vec::with_capacity(count as usize);
for _ in 0..count {
values.push(reader.read_bits(value_bit_width)?);
}
Some(Self {
count,
value_bit_width,
index_bit_width,
values,
})
}
pub fn remap(&self, raw_index: u32) -> Option<u32> {
if raw_index < self.count {
Some(self.values[raw_index as usize])
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::bit_reader::BitReader;
#[test]
fn test_fixed_width_array_read() {
let data = [
0x03, 0x00, 0x00, 0x08, 0x0A, 0x14, 0x1E, ];
let mut reader = BitReader::new(&data);
let arr = FixedWidthIntArray::read(&mut reader).unwrap();
assert_eq!(arr.count, 3);
assert_eq!(arr.value_bit_width, 8);
assert_eq!(arr.values, vec![10, 20, 30]);
assert!(arr.is_active());
assert_eq!(arr.index_bit_width, 2); }
#[test]
fn test_remap() {
let arr = FixedWidthIntArray {
count: 3,
value_bit_width: 8,
index_bit_width: 2,
values: vec![10, 20, 30],
};
assert_eq!(arr.remap(0), Some(10));
assert_eq!(arr.remap(1), Some(20));
assert_eq!(arr.remap(2), Some(30));
assert_eq!(arr.remap(3), None);
}
#[test]
fn test_empty_array() {
let data = [0x00, 0x00, 0x00, 0x00];
let mut reader = BitReader::new(&data);
let arr = FixedWidthIntArray::read(&mut reader).unwrap();
assert_eq!(arr.count, 0);
assert!(!arr.is_active());
}
}