use std::result;
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Copy)]
#[derive(Clone)]
pub enum Symbol {
Literal(u8),
Pair {distance: u32, length: u32},
End
}
impl Eq for Symbol {}
pub trait ToBits {
fn to_bits(&self) -> u32;
fn size_bits(&self) -> u32;
}
macro_rules! bitmask {
($bits:expr) => ((1<<$bits)-1)
}
#[derive(Debug)]
pub struct BitDecodeOutput<T> {
pub decoded: T,
pub used_bits: u32
}
#[derive(Debug)]
pub enum BitDecodeError {
NotEnoughBits(u32)
}
pub type Result<T> = result::Result<T, BitDecodeError>;
pub struct LenInit {
pub len_bits: [u8; 16],
pub len_code: [u8; 16]
}
pub struct DistInit {
pub dist_bits: [u8; 64],
pub dist_code: [u8; 64]
}
pub struct ShannonInit {
pub shan_bits: [u8; 256],
pub shan_code: [u16; 256]
}
pub struct CodeTable {
pub extra_len_bits: [u8; 16],
pub len_base: [u16; 16],
pub len_add: [u16; 16],
pub len_bits: [u8; 16],
pub len_codes: [u8; 256],
pub dist_bits: [u8; 64],
pub dist_codes: [u8; 256],
pub shan_lut: [u8; 256],
pub shan_4_lut: [u8; 256],
pub shan_6_lut: [u8; 128],
pub shan_8_lut: [u8; 256],
}
pub struct EncodeTable {
pub lit_bits: [u8; 256],
pub lit_code: [u16; 256],
pub len_bits: [u8; 518],
pub len_code: [u16; 518],
pub dist_bits: [u8; 64],
pub dist_code: [u8; 64],
pub dict_bits: u32
}
pub static DEFAULT_CODE_TABLE: CodeTable = CodeTable {
extra_len_bits: [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8],
len_base: [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 14, 22, 38, 70, 134, 262],
len_add: [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 11, 26, 57, 120, 247],
len_bits: [3, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7],
len_codes: [15, 2, 5, 1, 8, 0, 3, 1, 10, 2, 4, 1, 6, 0, 3, 1, 12, 2, 5, 1, 7, 0, 3, 1, 9, 2, 4, 1, 6, 0, 3, 1,
13, 2, 5, 1, 8, 0, 3, 1, 10, 2, 4, 1, 6, 0, 3, 1, 11, 2, 5, 1, 7, 0, 3, 1, 9, 2, 4, 1, 6, 0, 3, 1,
14, 2, 5, 1, 8, 0, 3, 1, 10, 2, 4, 1, 6, 0, 3, 1, 12, 2, 5, 1, 7, 0, 3, 1, 9, 2, 4, 1, 6, 0, 3, 1,
13, 2, 5, 1, 8, 0, 3, 1, 10, 2, 4, 1, 6, 0, 3, 1, 11, 2, 5, 1, 7, 0, 3, 1, 9, 2, 4, 1, 6, 0, 3, 1,
15, 2, 5, 1, 8, 0, 3, 1, 10, 2, 4, 1, 6, 0, 3, 1, 12, 2, 5, 1, 7, 0, 3, 1, 9, 2, 4, 1, 6, 0, 3, 1,
13, 2, 5, 1, 8, 0, 3, 1, 10, 2, 4, 1, 6, 0, 3, 1, 11, 2, 5, 1, 7, 0, 3, 1, 9, 2, 4, 1, 6, 0, 3, 1,
14, 2, 5, 1, 8, 0, 3, 1, 10, 2, 4, 1, 6, 0, 3, 1, 12, 2, 5, 1, 7, 0, 3, 1, 9, 2, 4, 1, 6, 0, 3, 1,
13, 2, 5, 1, 8, 0, 3, 1, 10, 2, 4, 1, 6, 0, 3, 1, 11, 2, 5, 1, 7, 0, 3, 1, 9, 2, 4, 1, 6, 0, 3, 1],
dist_bits: [2, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
dist_codes: [63, 6, 23, 0, 39, 2, 14, 0, 47, 4, 18, 0, 31, 1, 10, 0, 55, 5, 20, 0, 35, 2, 12, 0, 43, 3, 16, 0, 27, 1, 8, 0,
59, 6, 21, 0, 37, 2, 13, 0, 45, 4, 17, 0, 29, 1, 9, 0, 51, 5, 19, 0, 33, 2, 11, 0, 41, 3, 15, 0, 25, 1, 7, 0,
61, 6, 22, 0, 38, 2, 14, 0, 46, 4, 18, 0, 30, 1, 10, 0, 53, 5, 20, 0, 34, 2, 12, 0, 42, 3, 16, 0, 26, 1, 8, 0,
57, 6, 21, 0, 36, 2, 13, 0, 44, 4, 17, 0, 28, 1, 9, 0, 49, 5, 19, 0, 32, 2, 11, 0, 40, 3, 15, 0, 24, 1, 7, 0,
62, 6, 23, 0, 39, 2, 14, 0, 47, 4, 18, 0, 31, 1, 10, 0, 54, 5, 20, 0, 35, 2, 12, 0, 43, 3, 16, 0, 27, 1, 8, 0,
58, 6, 21, 0, 37, 2, 13, 0, 45, 4, 17, 0, 29, 1, 9, 0, 50, 5, 19, 0, 33, 2, 11, 0, 41, 3, 15, 0, 25, 1, 7, 0,
60, 6, 22, 0, 38, 2, 14, 0, 46, 4, 18, 0, 30, 1, 10, 0, 52, 5, 20, 0, 34, 2, 12, 0, 42, 3, 16, 0, 26, 1, 8, 0,
56, 6, 21, 0, 36, 2, 13, 0, 44, 4, 17, 0, 28, 1, 9, 0, 48, 5, 19, 0, 32, 2, 11, 0, 40, 3, 15, 0, 24, 1, 7, 0],
shan_lut: [0; 256], shan_4_lut: [0; 256], shan_6_lut: [0; 128], shan_8_lut: [0; 256],};
pub const END: u32 = 517;
pub fn decode_bits(bits: u64, nbits: u32, table: &CodeTable, dict_bits: u32) -> Result<BitDecodeOutput<Symbol>> {
let is_pair: u64 = bits&1;
let next_byte: u64 = (bits>>1)&0xFF;
let mut used_bits;
let sym = if is_pair==1 {
let code: u32 = table.len_codes[next_byte as usize] as u32;
let code_bits: u32 = table.len_bits[code as usize] as u32;
let extra_bits: u32 = table.extra_len_bits[code as usize] as u32;
used_bits = code_bits + extra_bits + 1;
let extra: u64 = (bits>>(1+code_bits)) & bitmask!(extra_bits);
let length = if extra_bits>0 {table.len_add[code as usize] as u32} else {0} + code + (extra as u32);
if length == END {
if nbits<used_bits {
return Err(BitDecodeError::NotEnoughBits(used_bits-nbits))
}
return Ok(BitDecodeOutput::<Symbol>{decoded: Symbol::End, used_bits: used_bits})
}
let dist_code: u8 = table.dist_codes[((bits>>used_bits)&0xFF) as usize];
let add_bits: u32 = if length==0 {2} else {dict_bits};
used_bits = used_bits+(table.dist_bits[dist_code as usize] as u32);
let distance: u32 = ((dist_code as u32) << add_bits) | (((bits>>used_bits) & bitmask!(add_bits)) as u32);
used_bits = used_bits + add_bits;
Symbol::Pair{distance: distance + 1, length: length + 2}
} else {
used_bits = 9;
Symbol::Literal(next_byte as u8)
};
if nbits<used_bits {
return Err(BitDecodeError::NotEnoughBits(used_bits-nbits))
}
Ok(BitDecodeOutput::<Symbol>{decoded: sym, used_bits: used_bits})
}