use crate::codec::Codec;
use crate::error::CoreError;
pub(crate) const DEFAULT_LEVEL: u8 = 6;
pub struct DeflateCodec;
impl Codec for DeflateCodec {
fn id(&self) -> u8 {
super::CODEC_DEFLATE
}
fn name(&self) -> &'static str {
"deflate"
}
fn compress(&self, plaintext: &[u8]) -> Result<Vec<u8>, CoreError> {
compress(plaintext, DEFAULT_LEVEL)
}
fn decompress(&self, compressed: &[u8], expected_len: u32) -> Result<Vec<u8>, CoreError> {
let expected_us = usize::try_from(expected_len).map_err(|_| CoreError::Corrupt {
reason: format!("decompress: expected_len {expected_len} exceeds usize"),
})?;
let codec = omnizip_deflate::DeflateCodec::new();
let result = omnizip_codecs::Codec::decompress(&codec, compressed, expected_len)
.map_err(deflate_err)?;
if result.len() != expected_us {
return Err(CoreError::Corrupt {
reason: format!(
"deflate decompress: result length {} does not match plaintext_len {expected_us}",
result.len()
),
});
}
Ok(result)
}
}
fn deflate_err(e: omnizip_codecs::OmnizipError) -> CoreError {
CoreError::Corrupt {
reason: format!("deflate: {e}"),
}
}
#[allow(clippy::unnecessary_wraps)]
pub(crate) fn compress(plaintext: &[u8], level: u8) -> Result<Vec<u8>, CoreError> {
let codec = omnizip_deflate::DeflateCodec::new();
let omnizip_level = omnizip_codecs::CompressionLevel::new(level_to_omnizip(level));
omnizip_codecs::Codec::compress(&codec, plaintext, omnizip_level).map_err(deflate_err)
}
fn level_to_omnizip(level: u8) -> u8 {
match level {
0 => 1,
1..=9 => level,
_ => 6,
}
}