use std::io::Write;
use flate2::read::GzDecoder;
use flate2::write::GzEncoder;
use flate2::Compression;
use super::{read_to_limit, CompressionError, Compressor};
const NAME: &str = "gzip";
const DEFAULT_LEVEL: u32 = 6;
#[derive(Debug, Clone, Copy)]
pub struct GzipCompressor {
level: u32,
}
impl GzipCompressor {
#[must_use]
pub fn new(level: u32) -> Self {
Self { level }
}
}
impl Default for GzipCompressor {
fn default() -> Self {
Self { level: DEFAULT_LEVEL }
}
}
impl Compressor for GzipCompressor {
fn name(&self) -> &str {
NAME
}
fn compress(&self, input: &[u8]) -> Result<Vec<u8>, CompressionError> {
let mut encoder = GzEncoder::new(Vec::new(), Compression::new(self.level));
encoder
.write_all(input)
.and_then(|()| encoder.finish())
.map_err(|e| CompressionError::Compress {
algorithm: NAME,
message: e.to_string(),
})
}
fn decompress(&self, input: &[u8], max_bytes: usize) -> Result<Vec<u8>, CompressionError> {
read_to_limit(GzDecoder::new(input), max_bytes, NAME)
}
}
pub struct GzipStreamCompressor {
level: Compression,
encoder: GzEncoder<Vec<u8>>,
}
impl GzipStreamCompressor {
#[must_use]
pub fn new(level: u32) -> Self {
let level = Compression::new(level);
Self {
level,
encoder: GzEncoder::new(Vec::new(), level),
}
}
pub fn write(&mut self, data: &[u8]) -> Result<(), CompressionError> {
self.encoder.write_all(data).map_err(|e| CompressionError::Compress {
algorithm: NAME,
message: e.to_string(),
})
}
pub fn finish_message(&mut self) -> Result<Vec<u8>, CompressionError> {
let finished = std::mem::replace(
&mut self.encoder,
GzEncoder::new(Vec::new(), self.level),
);
finished.finish().map_err(|e| CompressionError::Compress {
algorithm: NAME,
message: e.to_string(),
})
}
}
impl Default for GzipStreamCompressor {
fn default() -> Self {
Self::new(DEFAULT_LEVEL)
}
}