use super::huffman::{HuffmanDecodingTable, FAST_LOOKUP_BITS};
const MAX_SYMS_LOG2: u32 = 14;
const MAX_SYMS: u32 = 1 << MAX_SYMS_LOG2;
const TOTAL_CODELENGTH_CODES: usize = 21;
const SMALL_ZERO_RUN_CODE: u32 = 17;
const BIG_ZERO_RUN_CODE: u32 = 18;
const SMALL_REPEAT_CODE: u32 = 19;
const SMALL_ZERO_RUN_SIZE_MIN: u32 = 3;
const SMALL_ZERO_RUN_EXTRA_BITS: u32 = 3;
const BIG_ZERO_RUN_SIZE_MIN: u32 = 11;
const BIG_ZERO_RUN_EXTRA_BITS: u32 = 7;
const SMALL_REPEAT_SIZE_MIN: u32 = 3;
const SMALL_REPEAT_EXTRA_BITS: u32 = 2;
const BIG_REPEAT_SIZE_MIN: u32 = 7;
const BIG_REPEAT_EXTRA_BITS: u32 = 7;
const SORTED_CODELENGTH_CODES: [u8; TOTAL_CODELENGTH_CODES] = [
17, 18, 19, 20, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, 16,
];
fn floor_log2i(mut v: u32) -> u32 {
let mut b = 0;
while v > 1 {
v >>= 1;
b += 1;
}
b
}
pub struct BitwiseDecoder<'a> {
buf: &'a [u8],
pos: usize,
bit_buf: u32,
bit_buf_size: u32,
}
impl<'a> BitwiseDecoder<'a> {
pub fn new(buf: &'a [u8]) -> Self {
Self {
buf,
pos: 0,
bit_buf: 0,
bit_buf_size: 0,
}
}
#[inline]
fn next_byte(&mut self) -> u32 {
if self.pos < self.buf.len() {
let v = self.buf[self.pos] as u32;
self.pos += 1;
v
} else {
0
}
}
pub fn peek_bits(&mut self, num_bits: u32) -> u32 {
if num_bits == 0 {
return 0;
}
while self.bit_buf_size < num_bits {
let c = self.next_byte();
self.bit_buf |= c << self.bit_buf_size;
self.bit_buf_size += 8;
}
self.bit_buf & ((1u32 << num_bits) - 1)
}
pub fn remove_bits(&mut self, num_bits: u32) {
self.bit_buf >>= num_bits;
self.bit_buf_size -= num_bits;
}
pub fn get_bits(&mut self, mut num_bits: u32) -> u32 {
if num_bits > 25 {
let bits0 = self.peek_bits(25);
self.bit_buf >>= 25;
self.bit_buf_size -= 25;
num_bits -= 25;
let bits = self.peek_bits(num_bits);
self.bit_buf >>= num_bits;
self.bit_buf_size -= num_bits;
return bits0 | (bits << 25);
}
let bits = self.peek_bits(num_bits);
self.bit_buf >>= num_bits;
self.bit_buf_size -= num_bits;
bits
}
pub fn bits_remaining(&self) -> usize {
(self.buf.len() - self.pos) * 8 + self.bit_buf_size as usize
}
pub fn decode_truncated_binary(&mut self, n: u32) -> u32 {
let k = floor_log2i(n);
let u = (1u32 << (k + 1)) - n;
let mut result = self.get_bits(k);
if result >= u {
result = ((result << 1) | self.get_bits(1)) - u;
}
result
}
pub fn decode_rice(&mut self, m: u32) -> u32 {
let mut q = 0u32;
loop {
let mut k = self.peek_bits(16);
let mut l = 0u32;
while k & 1 != 0 {
l += 1;
k >>= 1;
}
q += l;
self.remove_bits(l);
if l < 16 {
break;
}
}
(q << m) + (self.get_bits(m + 1) >> 1)
}
pub fn decode_vlc(&mut self, chunk_bits: u32) -> u32 {
let chunk_size = 1u32 << chunk_bits;
let chunk_mask = chunk_size - 1;
let mut v = 0u32;
let mut ofs = 0u32;
loop {
let s = self.get_bits(chunk_bits + 1);
v |= (s & chunk_mask) << ofs;
ofs += chunk_bits;
if s & chunk_size == 0 {
break;
}
if ofs >= 32 {
break;
}
}
v
}
pub fn decode_huffman(&mut self, ct: &HuffmanDecodingTable) -> u32 {
let fast_lookup_size = 1u32 << FAST_LOOKUP_BITS;
while self.bit_buf_size < 16 {
let c = self.next_byte();
self.bit_buf |= c << self.bit_buf_size;
self.bit_buf_size += 8;
}
let mut sym = ct.lookup[(self.bit_buf & (fast_lookup_size - 1)) as usize];
let code_len;
if sym >= 0 {
code_len = (sym >> 16) as u32;
sym &= 0xFFFF;
} else {
let mut cl = FAST_LOOKUP_BITS;
loop {
let bit = (self.bit_buf >> cl) & 1;
cl += 1;
sym = ct.tree[(!sym + bit as i32) as usize] as i32;
if sym >= 0 {
break;
}
}
code_len = cl;
}
self.bit_buf >>= code_len;
self.bit_buf_size -= code_len;
sym as u32
}
pub fn read_huffman_table(&mut self, ct: &mut HuffmanDecodingTable) -> bool {
ct.clear();
let total_used_syms = self.get_bits(MAX_SYMS_LOG2);
if total_used_syms == 0 {
return true;
}
if total_used_syms > MAX_SYMS {
return false;
}
let mut code_length_code_sizes = [0u8; TOTAL_CODELENGTH_CODES];
let num_codelength_codes = self.get_bits(5);
if num_codelength_codes < 1 || num_codelength_codes as usize > TOTAL_CODELENGTH_CODES {
return false;
}
for i in 0..num_codelength_codes as usize {
code_length_code_sizes[SORTED_CODELENGTH_CODES[i] as usize] = self.get_bits(3) as u8;
}
let mut code_length_table = HuffmanDecodingTable::new();
if !code_length_table.init(TOTAL_CODELENGTH_CODES, &code_length_code_sizes) {
return false;
}
if !code_length_table.is_valid() {
return false;
}
let total = total_used_syms as usize;
let mut code_sizes = vec![0u8; total];
let mut cur = 0usize;
while cur < total {
let c = self.decode_huffman(&code_length_table);
if c <= 16 {
code_sizes[cur] = c as u8;
cur += 1;
} else if c == SMALL_ZERO_RUN_CODE {
cur +=
(self.get_bits(SMALL_ZERO_RUN_EXTRA_BITS) + SMALL_ZERO_RUN_SIZE_MIN) as usize;
} else if c == BIG_ZERO_RUN_CODE {
cur += (self.get_bits(BIG_ZERO_RUN_EXTRA_BITS) + BIG_ZERO_RUN_SIZE_MIN) as usize;
} else {
if cur == 0 {
return false;
}
let mut l = if c == SMALL_REPEAT_CODE {
self.get_bits(SMALL_REPEAT_EXTRA_BITS) + SMALL_REPEAT_SIZE_MIN
} else {
self.get_bits(BIG_REPEAT_EXTRA_BITS) + BIG_REPEAT_SIZE_MIN
};
let prev = code_sizes[cur - 1];
if prev == 0 {
return false;
}
loop {
if cur >= total {
return false;
}
code_sizes[cur] = prev;
cur += 1;
l -= 1;
if l == 0 {
break;
}
}
}
}
if cur != total {
return false;
}
ct.init(total, &code_sizes)
}
}