use super::bits::BitReader;
use crate::error::Error;
const fn code_lengths() -> [u8; 64] {
let mut lens = [0u8; 64];
let counts: [(u8, usize); 6] = [(3, 1), (4, 3), (5, 8), (6, 12), (7, 24), (8, 16)];
let mut sym = 0usize;
let mut ci = 0usize;
while ci < counts.len() {
let (len, count) = counts[ci];
let mut k = 0usize;
while k < count {
lens[sym] = len;
sym += 1;
k += 1;
}
ci += 1;
}
lens
}
pub struct OffsetCode {
first_code: [u32; 9],
first_sym: [u16; 9],
count: [u16; 9],
}
impl OffsetCode {
pub fn new() -> Self {
let lengths = code_lengths();
let mut count = [0u16; 9];
for &l in lengths.iter() {
count[l as usize] += 1;
}
let mut first_code = [0u32; 9];
let mut first_sym = [0u16; 9];
let mut code = 0u32;
let mut sym_seen = 0u16;
for l in 1..=8usize {
first_code[l] = code;
first_sym[l] = sym_seen;
sym_seen += count[l];
code = (code + count[l] as u32) << 1;
}
let _ = lengths;
Self {
first_code,
first_sym,
count,
}
}
pub fn decode(&self, br: &mut BitReader<'_>) -> Result<u32, Error> {
let mut code = 0u32;
for l in 1..=8usize {
code = (code << 1) | br.get_bit();
if br.exhausted() {
return Err(Error::UnexpectedEnd);
}
if self.count[l] != 0 {
let first = self.first_code[l];
let cnt = self.count[l] as u32;
if code >= first && code < first + cnt {
return Ok(self.first_sym[l] as u32 + (code - first));
}
}
}
Err(Error::Corrupt)
}
}