extern crate bit_vec;
extern crate bincode;
extern crate serde;
use core::fmt;
use std::fs::File;
use std::io::{Read, Write};
use std::{str, usize};
use std::collections::HashMap;
use bit_vec::BitVec;
use serde::{Serialize, Deserialize};
use crate::math::general::NumTools;
pub trait Encode {
#[must_use]
fn full_encode(&self) -> (BitVec, Box<Node>);
}
pub trait Decode {
#[must_use]
fn full_decode(&self) -> String;
}
impl Encode for String {
fn full_encode(&self) -> (BitVec, Box<Node>) {
let root = get_root(self);
let mut char_codes: HashMap<char, BitVec> = HashMap::new();
assign_codes(&root, &mut char_codes, &mut BitVec::new());
(huffman_encode(self, &char_codes), root)
}
}
impl Encode for &str {
fn full_encode(&self) -> (BitVec, Box<Node>) {
let root = get_root(self);
let mut char_codes: HashMap<char, BitVec> = HashMap::new();
assign_codes(&root, &mut char_codes, &mut BitVec::new());
(huffman_encode(self, &char_codes), root)
}
}
impl Decode for (BitVec, Box<Node>) {
fn full_decode(&self) -> String {
decode_string(&self.0, &self.1)
}
}
type Link = Option<Box<Node>>;
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Default)]
pub struct Node {
pub character: Option<char>,
pub frequency: u128,
pub left: Link,
pub right: Link
}
impl Node {
fn new(freq: u128, c: Option<char>) -> Node {
Node {
frequency: freq,
character: c,
left: None,
right: None,
}
}
fn new_box(n: Node) -> Box<Node> {
Box::new(n)
}
}
impl fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.character {
None => write!(f, "Count: {})", self.frequency),
_ => write!(f, "(Char: '{}', Count: {})", self.character.unwrap(), self.frequency),
}
}
}
fn get_frequency(s: &str) -> HashMap<char, usize> {
let mut hm: HashMap<char, usize> = HashMap::new(); for c in s.chars() {
let counter: &mut usize = hm.entry(c)
.or_insert(0); counter.inc(); }
hm
}
pub fn assign_codes(root: &Box<Node>,
hashmap: &mut HashMap<char, BitVec>,
bitvec: &mut BitVec ) {
match root.character {
Some(character) => { hashmap.insert(character, bitvec.clone()); }
None => {
if let Some(ref l) = root.left
{ bitvec.push(false);
assign_codes(l, hashmap, bitvec); }
if let Some(ref r) = root.right
{ bitvec.push(true);
assign_codes(r, hashmap, bitvec); }
}
}
bitvec.pop();
}
#[must_use]
pub fn huffman_encode(s: &str, char_codes: &HashMap<char, BitVec>) -> BitVec {
let mut res: BitVec = BitVec::with_capacity(s.len());
let mut t: Option<&BitVec>;
for c in s.chars() {
t = char_codes.get(&c);
res.append(&mut t.cloned()
.unwrap());
}
res
}
fn decode_string(bitvec: &BitVec, root: &Box<Node>) -> String {
let mut res: String = String::new();
let mut nodeptr: &Box<Node> = root;
for b in bitvec {
match b {
false => { if let Some(ref l) = nodeptr.left { nodeptr = l; } }
true => { if let Some(ref r) = nodeptr.right { nodeptr = r; } }
}
if let Some(c) = nodeptr.character { res.push(c); nodeptr = root; }
}
res
}
#[must_use]
pub fn huffman_decode(bitvec: &BitVec, root: &Box<Node>) -> String {
decode_string(bitvec, root)
}
#[must_use]
pub fn get_root(s: &str) -> Box<Node> {
let frequency = get_frequency(s);
let mut vec_nodes: Vec<Box<Node>> = frequency.iter().map(|x| Node::new_box(Node::new(*(x.1) as u128, Some(*(x.0))))).collect();
let mut a;
let mut b;
let mut c;
while vec_nodes.len() > 1 {
vec_nodes.sort_by(|a: &Box<Node>, b: &Box<Node>| (&(b.frequency)).cmp(&(a.frequency)));
a = vec_nodes.pop().unwrap();
b = vec_nodes.pop().unwrap();
c = Node::new_box(Node::new( a.frequency + b.frequency, None));
c.left = Some(a);
c.right = Some(b);
vec_nodes.push(c);
}
vec_nodes.pop().unwrap()
}
pub fn write_to_file(path: String, bitvec: &BitVec, root: &Box<Node>) {
let mut mainfile: File = File::create(path.clone() + ".hlr").unwrap();
let mut treefile: File = File::create(path + ".htlr").unwrap();
let _ = mainfile.write(&bitvec.to_bytes());
let _ = treefile.write(&bincode::serialize(root).unwrap());
}
#[must_use]
pub fn read_from_file(path: String) -> String {
let mut encoded_file: File = File::open(path.clone() + ".hlr").unwrap();
let mut tree_file: File = File::open(path + ".htlr").unwrap();
let mut enc_file: Vec<u8> = Vec::<u8>::new();
let mut enc_tree: Vec<u8> = Vec::<u8>::new();
let _ = encoded_file.read_to_end(&mut enc_file);
let _ = tree_file.read_to_end(&mut enc_tree);
let mut bitvec: BitVec = BitVec::from_bytes(&enc_file); bitvec.pop();
let root:Box<Node> = bincode::deserialize(&enc_tree).unwrap();
huffman_decode(&bitvec, &root)
}