#![forbid(unsafe_code)]
use core::fmt;
use alloc::vec::Vec;
use crate::compress::{
CompressorRefN, DEFAULT_DICT_ENTRIES, DEFAULT_NODICT_ENTRIES, HashTableU32U16,
compress_dict_tables, get_maximum_output_size, init_dict,
};
use lz4rip_core::CompressError;
use lz4rip_core::{MINMATCH, WINDOW_SIZE};
#[derive(Debug, Default)]
pub struct CompressorN<const N: usize = DEFAULT_NODICT_ENTRIES> {
inner: CompressorRefN<N>,
}
pub type Compressor = CompressorN<DEFAULT_NODICT_ENTRIES>;
impl<const N: usize> CompressorN<N> {
#[must_use]
pub fn new() -> Self {
CompressorN {
inner: CompressorRefN::<N>::new(),
}
}
pub fn compress_into(
&mut self,
input: &[u8],
output: &mut [u8],
) -> Result<usize, CompressError> {
self.inner.compress_into(input, output)
}
pub fn compress(&mut self, input: &[u8]) -> Vec<u8> {
self.inner.compress(input)
}
}
pub struct DictCompressorN<const N: usize = DEFAULT_DICT_ENTRIES> {
dict: Vec<u8>,
table: HashTableU32U16<N>,
pristine: HashTableU32U16<N>,
}
pub type DictCompressor = DictCompressorN<DEFAULT_DICT_ENTRIES>;
impl<const N: usize> fmt::Debug for DictCompressorN<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DictCompressor")
.field("dict_len", &self.dict.len())
.finish()
}
}
impl<const N: usize> DictCompressorN<N> {
#[must_use]
pub fn new(dict: &[u8]) -> Self {
let trimmed = if dict.len() < MINMATCH {
b"".as_slice()
} else if dict.len() > WINDOW_SIZE {
&dict[dict.len() - WINDOW_SIZE..]
} else {
dict
};
let mut pristine = HashTableU32U16::<N>::new();
let mut dict_ref = trimmed;
init_dict(&mut pristine, &mut dict_ref);
DictCompressorN {
dict: trimmed.to_vec(),
table: HashTableU32U16::<N>::new(),
pristine,
}
}
pub fn compress_into(
&mut self,
input: &[u8],
output: &mut [u8],
) -> Result<usize, CompressError> {
let DictCompressorN {
dict,
table,
pristine,
} = self;
compress_dict_tables(table, pristine, dict, input, output)
}
pub fn compress(&mut self, input: &[u8]) -> Vec<u8> {
let max = get_maximum_output_size(input.len());
let mut out = alloc::vec![0u8; max];
let n = self.compress_into(input, &mut out).unwrap();
out.truncate(n);
out
}
}