use crate::{
prelude::*,
utils::size_of_bits,
bitvec::prelude::{bitvec, BitVec, Msb0},
};
use super::branch_heap::HuffBranchHeap;
use std::{
fmt,
mem,
collections::{hash_map::RandomState, HashMap},
hash::BuildHasher,
};
#[derive(Debug, Clone)]
pub struct HuffTree<L: HuffLetter>{
root: HuffBranch<L>,
}
impl<L: HuffLetter> HuffTree<L>{
pub fn from_weights<W: Weights<L>>(weights: W) -> Self{
if weights.is_empty(){
panic!("provided empty weights")
}
let mut branch_heap = HuffBranchHeap::from_weights(weights);
while branch_heap.len() > 1{
let min = branch_heap.pop_min();
let next_min = branch_heap.pop_min();
let branch = HuffBranch::new(
HuffLeaf::new(
None,
min.leaf().weight() + next_min.leaf().weight()
),
Some((min, next_min))
);
branch_heap.push(branch);
}
let mut root = branch_heap.pop_min();
if root.has_children(){
HuffTree::set_codes_in_child_branches(&mut root, None);
}
else{
root.set_code({let mut c = BitVec::with_capacity(1); c.push(false); c});
}
HuffTree{
root
}
}
pub fn root(&self) -> &HuffBranch<L>{
&self.root
}
pub fn root_mut(&mut self) -> &mut HuffBranch<L>{
&mut self.root
}
pub fn read_codes(&self) -> HashMap<L, BitVec<Msb0, u8>>{
self.read_codes_with_hasher(RandomState::default())
}
pub fn read_codes_with_hasher<S: BuildHasher>(&self, hash_builder: S) -> HashMap<L, BitVec<Msb0, u8>, S>{
fn set_codes<L: HuffLetter, S: BuildHasher>(codes: &mut HashMap<L, BitVec<Msb0, u8>, S>, root: &HuffBranch<L>, pos_in_parent: bool){
if let Some(children_iter) = root.children_iter(){
for (pos, child) in children_iter.enumerate(){
let branch = child;
let leaf = branch.leaf();
if let Some(letter) = leaf.letter(){
codes.insert(letter.clone(), leaf.code().unwrap().clone());
}
else{
set_codes(codes, child, pos != 0);
}
}
}
else{
codes.insert(root.leaf().letter().unwrap().clone(), bitvec![Msb0, u8; pos_in_parent as u8]);
}
}
let mut codes = HashMap::with_hasher(hash_builder);
let root = self.root();
if root.has_children(){
set_codes(&mut codes, root.left_child().unwrap(), false);
set_codes(&mut codes, root.right_child().unwrap(), true);
codes
}
else{
codes.insert(root.leaf().letter().unwrap().clone(), bitvec![Msb0, u8; 0]);
codes
}
}
fn set_codes_in_child_branches(parent: &mut HuffBranch<L>, parent_code: Option<BitVec<Msb0, u8>>){
if parent.has_children(){
let set_code = |child: &mut HuffBranch<L>, pos|{
let mut child_code = BitVec::with_capacity(1);
if let Some(parent_code) = parent_code{
child_code = parent_code;
}
child_code.push(pos != 0);
child.set_code(child_code.clone());
HuffTree::set_codes_in_child_branches(child, Some(child_code));
};
set_code.clone()(parent.left_child_mut().unwrap(), 0);
set_code(parent.right_child_mut().unwrap(), 1);
}
}
}
impl<L: HuffLetterAsBytes> HuffTree<L>{
pub fn try_from_bin(bin: BitVec<Msb0, u8>) -> Result<Self, FromBinError<L>>{
fn read_branches_from_bits<L: HuffLetterAsBytes>(bits: &mut bitvec::slice::IterMut<Msb0, u8>) ->
Result<HuffBranch<L>, FromBinError<L>>{
if if let Some(bit) = bits.next(){*bit}
else{
return Err(FromBinError::new(
"Provided BitVec is too small for an encoded HuffTree"
))
}{
let branch = HuffBranch::new(
HuffLeaf::new(None, 0),
Some((
read_branches_from_bits(bits)?,
read_branches_from_bits(bits)?
))
);
Ok(branch)
}
else{
let mut letter_bytes = Vec::<u8>::with_capacity(mem::size_of::<L>());
let mut byte = 0b0000_0000;
let mut bit_ptr = 7;
let letter_bits = bits.take(size_of_bits::<L>());
if letter_bits.len() != size_of_bits::<L>(){
return Err(FromBinError::new(
"Provided BitVec is too small for an encoded HuffTree",
))
};
for bit in letter_bits{
byte |= (*bit as u8) << bit_ptr;
if bit_ptr == 0{
letter_bytes.push(byte);
byte = 0b0000_0000;
bit_ptr = 7;
}
else{bit_ptr -= 1};
}
let branch = HuffBranch::new(
HuffLeaf::new(Some(L::try_from_be_bytes(&letter_bytes).unwrap()), 0),
None,
);
Ok(branch)
}
}
let mut bin = bin;
let mut bin_iter_mut = bin.iter_mut();
let mut root = read_branches_from_bits(&mut bin_iter_mut)?;
if bin_iter_mut.next().is_some(){
return Err(FromBinError::new(
"Provided BitVec is too big for an encoded HuffTree",
))
}
if root.has_children(){
HuffTree::set_codes_in_child_branches(&mut root, None);
}
else{
root.set_code(bitvec![Msb0, u8; 0]);
}
Ok(HuffTree{
root
})
}
pub fn as_bin(&self) -> BitVec<Msb0, u8>{
fn set_tree_as_bin<L: HuffLetterAsBytes>(tree_bin: &mut BitVec<Msb0, u8>, root: &HuffBranch<L>){
let root = root;
let children_iter = root.children_iter();
if let Some(children_iter) = children_iter{
tree_bin.push(true);
for child in children_iter{
set_tree_as_bin(tree_bin, child);
}
}
else{
tree_bin.push(false);
for byte in root.leaf().letter().unwrap().as_be_bytes().iter(){
for bit_ptr in 0..8{
tree_bin.push((byte >> (7 - bit_ptr)) & 1 == 1)
}
}
}
}
let mut treebin = BitVec::new();
set_tree_as_bin(&mut treebin, self.root());
treebin
}
}
#[derive(Debug)]
pub struct FromBinError<L: HuffLetterAsBytes>{
message: &'static str,
_typebind: std::marker::PhantomData<L>,
}
impl<L: HuffLetterAsBytes> fmt::Display for FromBinError<L>{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}<{}>", self.message, std::any::type_name::<L>())
}
}
impl<L: HuffLetterAsBytes> std::error::Error for FromBinError<L>{}
impl<L: HuffLetterAsBytes> FromBinError<L>{
pub fn new(message: &'static str) -> Self{
Self{
message,
_typebind: std::marker::PhantomData,
}
}
pub fn message(&self) -> &str{
self.message
}
}