use std::fmt;
use std::sync::OnceLock;
use bytes::Bytes;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Symbol {
pub code: u32,
pub length: u8,
}
impl Symbol {
pub const fn new(code: u32, length: u8) -> Self {
Self { code, length }
}
}
pub const EOS: u16 = 256;
pub static TABLE: [Symbol; 257] = [
Symbol::new(0x1ff8, 13), Symbol::new(0x7fffd8, 23), Symbol::new(0xfffffe2, 28), Symbol::new(0xfffffe3, 28), Symbol::new(0xfffffe4, 28), Symbol::new(0xfffffe5, 28), Symbol::new(0xfffffe6, 28), Symbol::new(0xfffffe7, 28), Symbol::new(0xfffffe8, 28), Symbol::new(0xffffea, 24), Symbol::new(0x3ffffffc, 30), Symbol::new(0xfffffe9, 28), Symbol::new(0xfffffea, 28), Symbol::new(0x3ffffffd, 30), Symbol::new(0xfffffeb, 28), Symbol::new(0xfffffec, 28), Symbol::new(0xfffffed, 28), Symbol::new(0xfffffee, 28), Symbol::new(0xfffffef, 28), Symbol::new(0xffffff0, 28), Symbol::new(0xffffff1, 28), Symbol::new(0xffffff2, 28), Symbol::new(0x3ffffffe, 30), Symbol::new(0xffffff3, 28), Symbol::new(0xffffff4, 28), Symbol::new(0xffffff5, 28), Symbol::new(0xffffff6, 28), Symbol::new(0xffffff7, 28), Symbol::new(0xffffff8, 28), Symbol::new(0xffffff9, 28), Symbol::new(0xffffffa, 28), Symbol::new(0xffffffb, 28), Symbol::new(0x14, 6), Symbol::new(0x3f8, 10), Symbol::new(0x3f9, 10), Symbol::new(0xffa, 12), Symbol::new(0x1ff9, 13), Symbol::new(0x15, 6), Symbol::new(0xf8, 8), Symbol::new(0x7fa, 11), Symbol::new(0x3fa, 10), Symbol::new(0x3fb, 10), Symbol::new(0xf9, 8), Symbol::new(0x7fb, 11), Symbol::new(0xfa, 8), Symbol::new(0x16, 6), Symbol::new(0x17, 6), Symbol::new(0x18, 6), Symbol::new(0x0, 5), Symbol::new(0x1, 5), Symbol::new(0x2, 5), Symbol::new(0x19, 6), Symbol::new(0x1a, 6), Symbol::new(0x1b, 6), Symbol::new(0x1c, 6), Symbol::new(0x1d, 6), Symbol::new(0x1e, 6), Symbol::new(0x1f, 6), Symbol::new(0x5c, 7), Symbol::new(0xfb, 8), Symbol::new(0x7ffc, 15), Symbol::new(0x20, 6), Symbol::new(0xffb, 12), Symbol::new(0x3fc, 10), Symbol::new(0x1ffa, 13), Symbol::new(0x21, 6), Symbol::new(0x5d, 7), Symbol::new(0x5e, 7), Symbol::new(0x5f, 7), Symbol::new(0x60, 7), Symbol::new(0x61, 7), Symbol::new(0x62, 7), Symbol::new(0x63, 7), Symbol::new(0x64, 7), Symbol::new(0x65, 7), Symbol::new(0x66, 7), Symbol::new(0x67, 7), Symbol::new(0x68, 7), Symbol::new(0x69, 7), Symbol::new(0x6a, 7), Symbol::new(0x6b, 7), Symbol::new(0x6c, 7), Symbol::new(0x6d, 7), Symbol::new(0x6e, 7), Symbol::new(0x6f, 7), Symbol::new(0x70, 7), Symbol::new(0x71, 7), Symbol::new(0x72, 7), Symbol::new(0xfc, 8), Symbol::new(0x73, 7), Symbol::new(0xfd, 8), Symbol::new(0x1ffb, 13), Symbol::new(0x7fff0, 19), Symbol::new(0x1ffc, 13), Symbol::new(0x3ffc, 14), Symbol::new(0x22, 6), Symbol::new(0x7ffd, 15), Symbol::new(0x3, 5), Symbol::new(0x23, 6), Symbol::new(0x4, 5), Symbol::new(0x24, 6), Symbol::new(0x5, 5), Symbol::new(0x25, 6), Symbol::new(0x26, 6), Symbol::new(0x27, 6), Symbol::new(0x6, 5), Symbol::new(0x74, 7), Symbol::new(0x75, 7), Symbol::new(0x28, 6), Symbol::new(0x29, 6), Symbol::new(0x2a, 6), Symbol::new(0x7, 5), Symbol::new(0x2b, 6), Symbol::new(0x76, 7), Symbol::new(0x2c, 6), Symbol::new(0x8, 5), Symbol::new(0x9, 5), Symbol::new(0x2d, 6), Symbol::new(0x77, 7), Symbol::new(0x78, 7), Symbol::new(0x79, 7), Symbol::new(0x7a, 7), Symbol::new(0x7b, 7), Symbol::new(0x7ffe, 15), Symbol::new(0x7fc, 11), Symbol::new(0x3ffd, 14), Symbol::new(0x1ffd, 13), Symbol::new(0xffffffc, 28), Symbol::new(0xfffe6, 20), Symbol::new(0x3fffd2, 22), Symbol::new(0xfffe7, 20), Symbol::new(0xfffe8, 20), Symbol::new(0x3fffd3, 22), Symbol::new(0x3fffd4, 22), Symbol::new(0x3fffd5, 22), Symbol::new(0x7fffd9, 23), Symbol::new(0x3fffd6, 22), Symbol::new(0x7fffda, 23), Symbol::new(0x7fffdb, 23), Symbol::new(0x7fffdc, 23), Symbol::new(0x7fffdd, 23), Symbol::new(0x7fffde, 23), Symbol::new(0xffffeb, 24), Symbol::new(0x7fffdf, 23), Symbol::new(0xffffec, 24), Symbol::new(0xffffed, 24), Symbol::new(0x3fffd7, 22), Symbol::new(0x7fffe0, 23), Symbol::new(0xffffee, 24), Symbol::new(0x7fffe1, 23), Symbol::new(0x7fffe2, 23), Symbol::new(0x7fffe3, 23), Symbol::new(0x7fffe4, 23), Symbol::new(0x1fffdc, 21), Symbol::new(0x3fffd8, 22), Symbol::new(0x7fffe5, 23), Symbol::new(0x3fffd9, 22), Symbol::new(0x7fffe6, 23), Symbol::new(0x7fffe7, 23), Symbol::new(0xffffef, 24), Symbol::new(0x3fffda, 22), Symbol::new(0x1fffdd, 21), Symbol::new(0xfffe9, 20), Symbol::new(0x3fffdb, 22), Symbol::new(0x3fffdc, 22), Symbol::new(0x7fffe8, 23), Symbol::new(0x7fffe9, 23), Symbol::new(0x1fffde, 21), Symbol::new(0x7fffea, 23), Symbol::new(0x3fffdd, 22), Symbol::new(0x3fffde, 22), Symbol::new(0xfffff0, 24), Symbol::new(0x1fffdf, 21), Symbol::new(0x3fffdf, 22), Symbol::new(0x7fffeb, 23), Symbol::new(0x7fffec, 23), Symbol::new(0x1fffe0, 21), Symbol::new(0x1fffe1, 21), Symbol::new(0x3fffe0, 22), Symbol::new(0x1fffe2, 21), Symbol::new(0x7fffed, 23), Symbol::new(0x3fffe1, 22), Symbol::new(0x7fffee, 23), Symbol::new(0x7fffef, 23), Symbol::new(0xfffea, 20), Symbol::new(0x3fffe2, 22), Symbol::new(0x3fffe3, 22), Symbol::new(0x3fffe4, 22), Symbol::new(0x7ffff0, 23), Symbol::new(0x3fffe5, 22), Symbol::new(0x3fffe6, 22), Symbol::new(0x7ffff1, 23), Symbol::new(0x3ffffe0, 26), Symbol::new(0x3ffffe1, 26), Symbol::new(0xfffeb, 20), Symbol::new(0x7fff1, 19), Symbol::new(0x3fffe7, 22), Symbol::new(0x7ffff2, 23), Symbol::new(0x3fffe8, 22), Symbol::new(0x1ffffec, 25), Symbol::new(0x3ffffe2, 26), Symbol::new(0x3ffffe3, 26), Symbol::new(0x3ffffe4, 26), Symbol::new(0x7ffffde, 27), Symbol::new(0x7ffffdf, 27), Symbol::new(0x3ffffe5, 26), Symbol::new(0xfffff1, 24), Symbol::new(0x1ffffed, 25), Symbol::new(0x7fff2, 19), Symbol::new(0x1fffe3, 21), Symbol::new(0x3ffffe6, 26), Symbol::new(0x7ffffe0, 27), Symbol::new(0x7ffffe1, 27), Symbol::new(0x3ffffe7, 26), Symbol::new(0x7ffffe2, 27), Symbol::new(0xfffff2, 24), Symbol::new(0x1fffe4, 21), Symbol::new(0x1fffe5, 21), Symbol::new(0x3ffffe8, 26), Symbol::new(0x3ffffe9, 26), Symbol::new(0xffffffd, 28), Symbol::new(0x7ffffe3, 27), Symbol::new(0x7ffffe4, 27), Symbol::new(0x7ffffe5, 27), Symbol::new(0xfffec, 20), Symbol::new(0xfffff3, 24), Symbol::new(0xfffed, 20), Symbol::new(0x1fffe6, 21), Symbol::new(0x3fffe9, 22), Symbol::new(0x1fffe7, 21), Symbol::new(0x1fffe8, 21), Symbol::new(0x7ffff3, 23), Symbol::new(0x3fffea, 22), Symbol::new(0x3fffeb, 22), Symbol::new(0x1ffffee, 25), Symbol::new(0x1ffffef, 25), Symbol::new(0xfffff4, 24), Symbol::new(0xfffff5, 24), Symbol::new(0x3ffffea, 26), Symbol::new(0x7ffff4, 23), Symbol::new(0x3ffffeb, 26), Symbol::new(0x7ffffe6, 27), Symbol::new(0x3ffffec, 26), Symbol::new(0x3ffffed, 26), Symbol::new(0x7ffffe7, 27), Symbol::new(0x7ffffe8, 27), Symbol::new(0x7ffffe9, 27), Symbol::new(0x7ffffea, 27), Symbol::new(0x7ffffeb, 27), Symbol::new(0xffffffe, 28), Symbol::new(0x7ffffec, 27), Symbol::new(0x7ffffed, 27), Symbol::new(0x7ffffee, 27), Symbol::new(0x7ffffef, 27), Symbol::new(0x7fffff0, 27), Symbol::new(0x3ffffee, 26), Symbol::new(0x3fffffff, 30), ];
pub fn table() -> &'static [Symbol; 257] {
&TABLE
}
pub static LENGTHS: [u8; 257] = {
let mut lengths = [0u8; 257];
let mut value = 0;
while value < 257 {
lengths[value] = TABLE[value].length;
value += 1;
}
lengths
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Branch {
Node(usize),
Symbol(u16),
}
pub const NIBBLE: usize = 16;
pub const EMIT: u8 = 1 << 0;
pub const FAIL: u8 = 1 << 1;
pub const ENDED: u8 = 1 << 2;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Transition {
pub next: u16,
pub symbol: u8,
pub flags: u8,
}
impl Transition {
pub const STUCK: Self = Self { next: 0, symbol: 0, flags: FAIL };
}
pub struct DecodeTable {
pub branches: Vec<[Option<Branch>; 2]>,
pub rows: Vec<[Transition; NIBBLE]>,
pub accepting: Vec<bool>,
}
impl DecodeTable {
pub fn new(table: &[Symbol; 257]) -> Self {
let mut branches = vec![[None, None]];
for (value, symbol) in table.iter().enumerate() {
let mut node = 0;
for depth in (0..symbol.length).rev() {
let bit = (symbol.code >> depth & 1) as usize;
if depth == 0 {
branches[node][bit] = Some(Branch::Symbol(value as u16));
} else {
node = match branches[node][bit] {
Some(Branch::Node(next)) => next,
_ => {
branches.push([None, None]);
let next = branches.len() - 1;
branches[node][bit] = Some(Branch::Node(next));
next
}
};
}
}
}
let (rows, accepting) = Self::compile(&branches);
Self { branches, rows, accepting }
}
pub fn compile(branches: &[[Option<Branch>; 2]]) -> (Vec<[Transition; NIBBLE]>, Vec<bool>) {
let mut state_of = vec![u16::MAX; branches.len()];
let mut nodes = vec![0usize];
state_of[0] = 0;
let mut rows: Vec<[Transition; NIBBLE]> = Vec::new();
let mut state = 0;
while state < nodes.len() {
let mut row = [Transition::STUCK; NIBBLE];
for (nibble, slot) in row.iter_mut().enumerate() {
let mut node = nodes[state];
let mut symbol = 0u8;
let mut flags = 0u8;
for shift in (0..4).rev() {
match branches[node][nibble >> shift & 1] {
Some(Branch::Node(next)) => node = next,
Some(Branch::Symbol(EOS)) => {
flags |= ENDED;
break;
}
Some(Branch::Symbol(value)) => {
symbol = value as u8;
flags |= EMIT;
node = 0;
}
None => {
flags |= FAIL;
break;
}
}
}
if flags & (FAIL | ENDED) != 0 {
*slot = Transition { next: 0, symbol, flags };
continue;
}
if state_of[node] == u16::MAX {
state_of[node] = nodes.len() as u16;
nodes.push(node);
}
*slot = Transition { next: state_of[node], symbol, flags };
}
rows.push(row);
state += 1;
}
let mut on_ones = vec![false; branches.len()];
let mut node = 0usize;
on_ones[0] = true;
for _ in 0..7 {
match branches[node][1] {
Some(Branch::Node(next)) => {
node = next;
on_ones[node] = true;
}
_ => break,
}
}
let accepting = nodes.iter().map(|node| on_ones[*node]).collect();
(rows, accepting)
}
pub fn step(&self, node: usize, bit: bool) -> Option<Branch> {
self.branches.get(node).and_then(|pair| pair[bit as usize])
}
}
pub fn decode_table() -> &'static DecodeTable {
static DECODE_TABLE: OnceLock<DecodeTable> = OnceLock::new();
DECODE_TABLE.get_or_init(|| DecodeTable::new(table()))
}
#[derive(Debug, PartialEq, Eq)]
pub enum DecodeError {
InvalidPadding,
UnknownSymbol,
}
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidPadding => write!(f, "huffman padding is not all one-bits"),
Self::UnknownSymbol => write!(f, "huffman code does not map to a known symbol"),
}
}
}
impl std::error::Error for DecodeError {}
pub fn encode(input: &[u8]) -> Bytes {
let encoded = encoded_len(input);
let mut out = Vec::with_capacity(encoded);
encode_sized(input, encoded, &mut out);
Bytes::from(out)
}
pub fn encode_into(input: &[u8], out: &mut Vec<u8>) {
encode_sized(input, encoded_len(input), out)
}
pub fn encode_sized(input: &[u8], encoded: usize, out: &mut Vec<u8>) {
let table = table();
out.reserve(encoded);
let mut pending: u64 = 0;
let mut bits: u32 = 0;
for byte in input {
let symbol = table[*byte as usize];
pending = pending << symbol.length | symbol.code as u64;
bits += symbol.length as u32;
if bits >= 32 {
bits -= 32;
out.extend_from_slice(&((pending >> bits) as u32).to_be_bytes());
}
}
while bits >= 8 {
bits -= 8;
out.push((pending >> bits) as u8);
}
if bits > 0 {
let padding = 8 - bits;
out.push(((pending << padding) | ((1 << padding) - 1)) as u8);
}
}
pub fn decode(input: &[u8]) -> Result<Bytes, DecodeError> {
let mut out = Vec::new();
decode_into(input, &mut out)?;
Ok(Bytes::from(out))
}
pub fn decode_into(input: &[u8], out: &mut Vec<u8>) -> Result<(), DecodeError> {
decode_into_ascii(input, out).map(|_| ())
}
pub fn decode_into_ascii(input: &[u8], out: &mut Vec<u8>) -> Result<bool, DecodeError> {
let table = decode_table();
let rows = table.rows.as_slice();
out.reserve(input.len() * 8 / 5 + 1);
let mut state = 0usize;
let mut seen = 0u8;
for byte in input {
for nibble in [(byte >> 4) as usize, (byte & 0x0f) as usize] {
let step = rows[state][nibble];
if step.flags & (FAIL | ENDED) != 0 {
return Err(if step.flags & FAIL != 0 {
DecodeError::UnknownSymbol
} else {
DecodeError::InvalidPadding
});
}
if step.flags & EMIT != 0 {
seen |= step.symbol;
out.push(step.symbol);
}
state = step.next as usize;
}
}
if !table.accepting[state] {
return Err(DecodeError::InvalidPadding);
}
Ok(seen & 0x80 == 0)
}
pub fn encoded_len(input: &[u8]) -> usize {
let bits: usize = input.iter().map(|byte| LENGTHS[*byte as usize] as usize).sum();
bits.div_ceil(8)
}