pub use self::byte_weights::ByteWeights;
use super::tree::letter::HuffLetter;
use std::{
collections::{
HashMap,
hash_map::RandomState,
},
hash::{
Hash,
BuildHasher
},
};
pub trait Weights<L>: Eq + Clone + IntoIterator<Item = (L, usize)>{
fn get(&self, letter: &L) -> Option<&usize>;
fn get_mut(&mut self, letter: &L) -> Option<&mut usize>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
}
impl<L: Eq + Clone + Hash> Weights<L> for HashMap<L, usize>{
fn get(&self, letter: &L) -> Option<&usize>{
self.get(letter)
}
fn get_mut(&mut self, letter: &L) -> Option<&mut usize>{
self.get_mut(letter)
}
fn len(&self) -> usize{
self.len()
}
fn is_empty(&self) -> bool{
self.is_empty()
}
}
pub fn build_weights_map<L: HuffLetter>(letters: &[L]) -> HashMap<L, usize>{
build_weights_map_with_hasher(letters, RandomState::default())
}
pub fn build_weights_map_with_hasher<L: HuffLetter, S: BuildHasher>(letters: &[L], hash_builder: S) -> HashMap<L, usize, S>{
let mut map = HashMap::with_hasher(hash_builder);
for l in letters{
let entry = map.entry(l.clone()).or_insert(0);
*entry += 1;
}
map
}
pub mod byte_weights{
use crate::utils::ration_vec;
use super::Weights;
use std::{
ops::{Add, AddAssign},
thread,
};
#[derive(Clone, Copy, Eq)]
pub struct ByteWeights{
weights: [usize; 256],
len: usize,
}
impl Weights<u8> for ByteWeights{
fn get(&self, byte: &u8) -> Option<&usize>{
self.get(byte)
}
fn get_mut(&mut self, byte: &u8) -> Option<&mut usize>{
self.get_mut(byte)
}
fn len(&self) -> usize{
self.len()
}
fn is_empty(&self) -> bool{
self.is_empty()
}
}
impl IntoIterator for ByteWeights{
type Item = (u8, usize);
type IntoIter = IntoIter;
fn into_iter(self) -> IntoIter{
IntoIter{weights: self, current_index: 0}
}
}
impl <'a> IntoIterator for &'a ByteWeights{
type Item = (u8, usize);
type IntoIter = Iter<'a>;
fn into_iter(self) -> Iter<'a>{
Iter{weights: &self, current_index: 0}
}
}
impl PartialEq for ByteWeights{
fn eq(&self, other: &Self) -> bool {
self.weights == other.weights
}
}
impl Add for ByteWeights{
type Output = Self;
fn add(mut self, other: Self) -> Self {
self.add_byte_weights(&other);
self
}
}
impl AddAssign for ByteWeights{
fn add_assign(&mut self, other: Self){
self.add_byte_weights(&other);
}
}
impl Default for ByteWeights{
fn default() -> Self{
Self::new()
}
}
impl ByteWeights{
pub fn new() -> Self{
Self{
weights: [0;256],
len: 0,
}
}
pub fn from_bytes(bytes: &[u8]) -> Self{
let mut weights: [usize; 256] = [0;256];
let mut len = 0;
for byte in bytes{
if weights[*byte as usize] == 0{len += 1;}
weights[*byte as usize] += 1;
}
ByteWeights{
weights,
len,
}
}
pub fn threaded_from_bytes(bytes: &[u8], thread_num: usize) -> Self{
let byte_rations = ration_vec(bytes, thread_num);
let mut handles = Vec::with_capacity(thread_num);
for ration in byte_rations{
let handle = thread::spawn(move || {
ByteWeights::from_bytes(&ration)
});
handles.push(handle);
}
let mut weights_vec: Vec<ByteWeights> = Vec::with_capacity(thread_num);
for handle in handles{
weights_vec.push(handle.join().unwrap());
}
let mut weights = weights_vec.pop().unwrap();
for weights_other in weights_vec{
weights += weights_other;
}
weights
}
pub fn get(&self, byte: &u8) -> Option<&usize>{
let weight = self.weights.get(*byte as usize)?;
if *weight == 0{
return None
}
Some(weight)
}
pub fn get_mut(&mut self, byte: &u8) -> Option<&mut usize>{
let weight = self.weights.get_mut(*byte as usize)?;
if *weight == 0{
return None
}
Some(weight)
}
pub fn len(&self) -> usize{
self.len
}
pub fn is_empty(&self) -> bool{
self.len == 0
}
pub fn iter(&self) -> Iter{
self.into_iter()
}
pub fn add_byte_weights(&mut self, other: &ByteWeights){
for (b, f) in other{
let self_entry = self.get_mut(&b);
match self_entry{
Some(self_entry) =>{
*self_entry += f;
}
None =>{
self.weights[b as usize] = f;
self.len += 1;
}
}
}
}
}
pub struct IntoIter{
weights: ByteWeights,
current_index: usize,
}
impl Iterator for IntoIter{
type Item = (u8, usize);
fn next(&mut self) -> Option<Self::Item>{
if self.current_index == 256{
return None
}
while self.weights.get(&(self.current_index as u8)).is_none(){
if self.current_index == 256{
return None
}
self.current_index += 1
}
let entry = Some((self.current_index as u8, *self.weights.get(&(self.current_index as u8)).unwrap()));
if self.current_index != 256{self.current_index += 1;}
entry
}
}
pub struct Iter<'a>{
weights: &'a ByteWeights,
current_index: usize,
}
impl Iterator for Iter<'_>{
type Item = (u8, usize);
fn next(&mut self) -> Option<Self::Item>{
if self.current_index == 256{
return None
}
while self.weights.get(&(self.current_index as u8)).is_none(){
if self.current_index == 256{
return None
}
self.current_index += 1
}
let entry = Some((self.current_index as u8, *self.weights.get(&(self.current_index as u8)).unwrap()));
if self.current_index != 256{self.current_index += 1;}
entry
}
}
}