use crate::{
MAX_OFFSET_ZX0,
MAX_OFFSET_ZX7
};
use crate::compress::{Block, compress};
use crate::optimize::optimize;
pub struct CompressionResult {
pub output: Vec<u8>,
pub delta: usize
}
pub type ProgressCallback<'a> = Box<dyn FnMut(f32) + 'a>;
pub struct Compressor<'a> {
skip: usize,
quick_mode: bool,
backwards_mode: bool,
classic_mode: bool,
progress_callback: ProgressCallback<'a>
}
impl<'a> Compressor<'a> {
pub fn new() -> Self {
Self {
skip: 0,
quick_mode: false,
backwards_mode: false,
classic_mode: false,
progress_callback: Box::new(|_| ())
}
}
pub fn quick_mode(&mut self, quick_mode: bool) -> &mut Self {
self.quick_mode = quick_mode;
self
}
pub fn backwards_mode(&mut self, backwards_mode: bool) -> &mut Self {
self.backwards_mode = backwards_mode;
self
}
pub fn classic_mode(&mut self, classic_mode: bool) -> &mut Self {
self.classic_mode = classic_mode;
self
}
pub fn progress_callback<C: FnMut(f32) + 'a>(&mut self, progress_callback: C) -> &mut Self {
self.progress_callback = Box::new(progress_callback);
self
}
pub fn skip(&mut self, skip: usize) -> &mut Self {
self.skip = skip;
self
}
pub fn compress(&mut self, input: &[u8]) -> CompressionResult {
let chain = {
let (allocator, mut optimal) = optimize(
input,
self.skip,
if self.quick_mode { MAX_OFFSET_ZX7 } else { MAX_OFFSET_ZX0 },
&mut self.progress_callback
);
let mut chain = Vec::new();
while optimal != 0 {
let oblock = allocator.get(optimal);
chain.push(Block {
bits: oblock.bits as u32,
index: oblock.index as isize,
offset: oblock.offset as usize
});
optimal = oblock.next_index;
}
chain
};
let invert_mode = !self.classic_mode && !self.backwards_mode;
let mut delta = 0;
let output = compress(
chain,
input,
self.skip,
self.backwards_mode,
invert_mode,
&mut delta
);
CompressionResult {
output,
delta
}
}
}
impl<'a> Default for Compressor<'a> {
fn default() -> Self {
Self::new()
}
}