use crate::{CompressorError, CompressorResult, CompressorWriter, Config, VariantCompressor};
const SAFE_COMPRESSION_OVERHEAD: u64 = 51;
const CLOSE_OVERHEAD_ZLIB: u64 = 9;
#[derive(Debug, Clone)]
pub struct ShadowCompressor {
config: Config,
compressor: VariantCompressor,
shadow: VariantCompressor,
is_full: bool,
bound: u64,
}
impl ShadowCompressor {
pub const fn new(
config: Config,
compressor: VariantCompressor,
shadow: VariantCompressor,
) -> Self {
Self { config, is_full: false, compressor, shadow, bound: SAFE_COMPRESSION_OVERHEAD }
}
}
impl From<Config> for ShadowCompressor {
fn from(config: Config) -> Self {
let compressor = VariantCompressor::from(config.compression_algo);
let shadow = VariantCompressor::from(config.compression_algo);
Self::new(config, compressor, shadow)
}
}
impl CompressorWriter for ShadowCompressor {
fn write(&mut self, data: &[u8]) -> CompressorResult<usize> {
if self.is_full {
return Err(CompressorError::Full);
}
self.shadow.write(data)?;
let mut newbound = data.len() as u64;
if newbound > self.config.target_output_size {
self.shadow.flush()?;
newbound = self.shadow.len() as u64 + CLOSE_OVERHEAD_ZLIB;
if newbound > self.config.target_output_size {
self.is_full = true;
if self.compressor.len() > 0 {
return Err(CompressorError::Full);
}
}
}
self.bound = newbound;
self.compressor.write(data)
}
fn len(&self) -> usize {
self.compressor.len()
}
fn flush(&mut self) -> CompressorResult<()> {
self.shadow.flush()
}
fn close(&mut self) -> CompressorResult<()> {
self.shadow.close()
}
fn reset(&mut self) {
self.compressor.reset();
self.shadow.reset();
self.is_full = false;
self.bound = SAFE_COMPRESSION_OVERHEAD;
}
fn read(&mut self, buf: &mut [u8]) -> CompressorResult<usize> {
self.compressor.read(buf)
}
}