use std::collections::{BinaryHeap, HashMap};
use std::cmp::Reverse;
use std::fmt::Error;
use std::process::Output;
use bitvec::prelude::*;
use std::fs;
use serde::{Serialize, Deserialize};
pub type CodeDict = HashMap<u8, (u16, u8)>;
pub struct HuffmanTree {
tree: Vec<Node>,
root_idx: usize,
dict: CodeDict,
}
#[derive(PartialEq, Eq, Clone, Copy, Default, Hash)]
struct Node {
symbol: Option<u8>,
weight: usize,
children: Option<(usize, usize)>,
parent: Option<usize>,
idx: usize,
}
impl HuffmanTree {
const MAX_LEN: u8 = 15;
pub fn from_bytes(bytes: &[u8]) -> Self {
let mut freq_map = HashMap::new();
for byte in bytes {
*freq_map.entry(*byte).or_insert(0) += 1;
}
let mut elems: Vec<(u8, usize)> = freq_map.into_iter().collect();
elems.sort_by(|a, b| a.0.cmp(&b.0));
Self::new(elems)
}
pub fn new(elems: Vec<(u8, usize)>) -> Self {
let mut nodes = Vec::with_capacity(elems.len());
let mut pq = BinaryHeap::new();
for (i, elem) in elems.iter().enumerate() {
let node = Node {
symbol: Some(elem.0),
weight: elem.1,
children: None,
parent: None,
idx: i,
};
nodes.push(node);
pq.push(Reverse(node));
}
while pq.len() > 1 {
let first = pq.pop().unwrap().0;
let second = pq.pop().unwrap().0;
let parent = Node {
symbol: None,
weight: first.weight + second.weight,
children: Some((first.idx, second.idx)),
parent: None,
idx: nodes.len(),
};
nodes[first.idx].parent = Some(parent.idx);
nodes[second.idx].parent = Some(parent.idx);
nodes.push(parent);
pq.push(Reverse(parent));
}
Self { root_idx: nodes.len()-1, tree: nodes, dict: HashMap::new() }
}
pub fn gen_dict(&mut self) -> CodeDict {
self.recurse(self.root_idx, &mut Vec::new());
std::mem::take(&mut self.dict)
}
fn limit_length(&mut self) {
let mut bitstack = Vec::new();
self.recurse(self.root_idx, &mut bitstack);
let mut depth = self.dict.iter().max_by(|a, b| { a.1.1.cmp(&b.1.1).then(a.0.cmp(b.0)) }).unwrap().1.1;
self.dict.clear();
println!("depth: {depth}");
}
fn recurse(&mut self, idx: usize, bitstack: &mut Vec<u8>) {
if self.tree[idx].symbol.is_some() {
let mut code: u16 = 0;
for bit in bitstack.iter() {
code <<= 1;
code |= *bit as u16;
}
self.dict.insert(self.tree[idx].symbol.expect("Expected symbol in this node"),
(code, bitstack.len() as u8));
}
if let Some((left, right)) = self.tree[idx].children {
bitstack.push(0);
self.recurse(left, bitstack);
bitstack.pop();
bitstack.push(1);
self.recurse(right, bitstack);
bitstack.pop();
}
}
}
impl PartialOrd for Node {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.weight.partial_cmp(&other.weight)
.and_then(|ord| match ord {
std::cmp::Ordering::Equal => self.symbol.partial_cmp(&other.symbol),
_ => Some(ord),
})
}
}
impl Ord for Node {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.weight.cmp(&other.weight)
.then(self.symbol.cmp(&other.symbol))
}
}
#[derive(Serialize, Deserialize)]
struct Zpp {
huff_table: CodeDict,
binary_data: Vec<u8>,
binary_len: usize,
}
pub fn huff_encode(source: &[u8], dict: &CodeDict) -> Result<(Vec<u8>, usize), Error> {
let mut zpp = Zpp {
huff_table: HashMap::new(),
binary_data: Vec::new(),
binary_len: 0,
};
let mut bit_stream = BitVec::<u8, Lsb0>::new();
let mut real_length: usize = 0;
for byte in source {
if let Some(&(next_code, code_len)) = dict.get(&byte) {
for i in (0..code_len).rev() {
bit_stream.push((next_code>>i)&0b1 == 1);
real_length += 1;
}
} else { return Err(Error) }
}
Ok((Vec::<u8>::from(bit_stream), real_length))
}
pub fn huff_decode(source: &[u8], dict: &CodeDict, bit_len: usize) -> Result<Vec<u8>, Error> {
let mut bit_stream: BitVec<u8, Lsb0> = BitVec::from_vec(source.to_vec());
let mut output = Vec::new();
let inverted_code_dict: HashMap<(u16, u8), u8> = dict.iter()
.map(|(&k, &v)| { (v, k) }).collect();
let mut err_count: usize = 0;
let mut next_code: u16 = 0;
let mut code_len: u8 = 0;
for i in 0..bit_len {
next_code <<= 1;
next_code |= bit_stream[i] as u16;
code_len += 1;
if let Some(symbol) = inverted_code_dict.get(&(next_code, code_len)) {
output.push(*symbol);
next_code = 0;
code_len = 0;
} else if code_len > 16 { return Err(Error) }
}
Ok(output)
}