use std::collections::VecDeque;
pub const VARICODE_MAX_BITS: usize = 11;
const VARICODE: [(u16, u8); 128] = [
(0b1010101011, 10), (0b1011011011, 10), (0b1011101101, 10), (0b1101110111, 10), (0b1011101011, 10), (0b1101011111, 10), (0b1011101111, 10), (0b1011111101, 10), (0b1011111111, 10), (0b11100111111, 11), (0b11101111111, 11), (0b11111011111, 11), (0b11111110111, 11), (0b11111111011, 11), (0b11111111101, 11), (0b11111111111, 11), (0b10110111111, 11), (0b10111111101, 11), (0b10111111111, 11), (0b11101101111, 11), (0b11101111011, 11), (0b11110101111, 11), (0b11110111101, 11), (0b11111101011, 11), (0b11111101101, 11), (0b11111110101, 11), (0b11111110111, 11), (0b11111111111, 11), (0b11011111111, 11), (0b11101011111, 11), (0b11110101101, 11), (0b11110110111, 11), (0b1, 1), (0b111111111, 9), (0b101011111, 9), (0b111110101, 9), (0b111011011, 9), (0b1011010101, 10), (0b1010111011, 10), (0b101111111, 9), (0b11111011, 8), (0b11110111, 8), (0b101101111, 9), (0b111011111, 9), (0b1110101, 7), (0b110101, 6), (0b1010111, 7), (0b110101111, 9), (0b10110111, 8), (0b10111101, 8), (0b11101101, 8), (0b11111111, 8), (0b101110111, 9), (0b101011011, 9), (0b101101011, 9), (0b110101101, 9), (0b110101011, 9), (0b110110111, 9), (0b11110101, 8), (0b110111101, 9), (0b111101101, 9), (0b1010101, 7), (0b111010111, 9), (0b1010101111, 10), (0b1010111101, 10), (0b1111101, 7), (0b11101011, 8), (0b10101101, 8), (0b10110101, 8), (0b1110111, 7), (0b11011011, 8), (0b11111101, 8), (0b101010101, 9), (0b1111111, 7), (0b111111101, 9), (0b101111101, 9), (0b11010111, 8), (0b10111011, 8), (0b11011101, 8), (0b10101011, 8), (0b11010101, 8), (0b111011101, 9), (0b10101111, 8), (0b1101111, 7), (0b1011011, 7), (0b11101111, 8), (0b101101101, 9), (0b101010111, 9), (0b110110101, 9), (0b101011101, 9), (0b110101110, 9), (0b11101110111, 11), (0b11110111011, 11), (0b11110111111, 11), (0b1010111111, 10), (0b101110111111, 12), (0b101010111111, 12), (0b1011, 4), (0b1011111, 7), (0b101111, 6), (0b101101, 6), (0b11, 2), (0b111101, 6), (0b1011011, 7), (0b101011, 6), (0b1101, 4), (0b111101011, 9), (0b10111111, 8), (0b11011, 5), (0b111011, 6), (0b1111, 4), (0b111, 3), (0b111111, 6), (0b110111111, 9), (0b10101, 5), (0b10111, 5), (0b101, 3), (0b110111, 6), (0b1111011, 7), (0b1101011, 7), (0b11011111, 8), (0b1011101, 7), (0b111010101, 9), (0b10101101111, 11), (0b10110111011, 11), (0b10111011111, 11), (0b1010101011, 10), (0b10110111111, 11), ];
#[inline]
pub fn varicode_encode(byte: u8) -> (u16, u8) {
if byte >= 128 { VARICODE[0] } else { VARICODE[byte as usize] }
}
#[inline]
pub fn varicode_decode(bits: u16, len: u8) -> Option<u8> {
for (i, &(cw, cw_len)) in VARICODE.iter().enumerate() {
if cw_len == len && cw == bits {
return Some(i as u8);
}
}
None
}
#[derive(Debug, Clone)]
pub struct VaricodeEncoder {
pending: VecDeque<u8>,
first: bool,
}
impl Default for VaricodeEncoder {
fn default() -> Self { Self::new() }
}
impl VaricodeEncoder {
pub fn new() -> Self {
Self { pending: VecDeque::new(), first: true }
}
pub fn push_preamble(&mut self, n_bits: usize) {
for _ in 0..n_bits {
self.pending.push_back(0);
}
self.first = true;
}
pub fn push_byte(&mut self, b: u8) {
if !self.first {
self.pending.push_back(0);
self.pending.push_back(0);
}
self.first = false;
let (cw, len) = varicode_encode(b);
for i in (0..len).rev() {
self.pending.push_back(((cw >> i) & 1) as u8);
}
}
pub fn push_postamble(&mut self, n_bits: usize) {
if !self.first {
self.pending.push_back(0);
self.pending.push_back(0);
}
for _ in 0..n_bits {
self.pending.push_back(1);
}
}
pub fn next_bit(&mut self) -> Option<u8> {
self.pending.pop_front()
}
pub fn is_empty(&self) -> bool {
self.pending.is_empty()
}
pub fn drain_bits(&mut self) -> Vec<u8> {
self.pending.drain(..).collect()
}
}
#[derive(Debug, Clone, Default)]
pub struct VaricodeDecoder {
shift: u16,
len: u8,
prev_zero: bool,
chars: VecDeque<u8>,
}
impl VaricodeDecoder {
pub fn new() -> Self { Self::default() }
pub fn push_bit(&mut self, bit: u8) {
let is_zero = bit == 0;
if is_zero && self.prev_zero {
let cw = if self.len > 0 { self.shift >> 1 } else { 0 };
let cw_len = self.len.saturating_sub(1);
if cw_len > 0 {
if let Some(ch) = varicode_decode(cw, cw_len) {
self.chars.push_back(ch);
}
}
self.shift = 0;
self.len = 0;
self.prev_zero = false;
} else {
self.shift = (self.shift << 1) | (bit & 1) as u16;
if self.len < VARICODE_MAX_BITS as u8 {
self.len += 1;
}
self.prev_zero = is_zero;
}
}
pub fn pop_char(&mut self) -> Option<u8> {
self.chars.pop_front()
}
}