use super::{CompressionError, Compressor};
use flate2::Compression;
use flate2::read::{GzDecoder, GzEncoder};
use std::io::Read;
#[derive(Debug, Clone)]
pub struct GzipCompressor {
level: u32,
}
impl GzipCompressor {
pub fn new() -> Self {
Self { level: 6 }
}
pub fn with_level(level: u32) -> Self {
Self { level }
}
pub fn level(&self) -> u32 {
self.level
}
}
impl Default for GzipCompressor {
fn default() -> Self {
Self::new()
}
}
impl Compressor for GzipCompressor {
fn compress(&self, data: &[u8]) -> Result<Vec<u8>, CompressionError> {
let mut encoder = GzEncoder::new(data, Compression::new(self.level));
let mut compressed = Vec::new();
encoder
.read_to_end(&mut compressed)
.map_err(|e| CompressionError::CompressionFailed(e.to_string()))?;
Ok(compressed)
}
fn decompress(&self, compressed: &[u8]) -> Result<Vec<u8>, CompressionError> {
let mut decoder = GzDecoder::new(compressed);
let mut decompressed = Vec::new();
decoder
.read_to_end(&mut decompressed)
.map_err(|e| CompressionError::DecompressionFailed(e.to_string()))?;
Ok(decompressed)
}
fn name(&self) -> &'static str {
"gzip"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gzip_compress_decompress() {
let compressor = GzipCompressor::new();
let data = b"Hello, World! This is test data for Gzip compression.";
let compressed = compressor.compress(data).unwrap();
let decompressed = compressor.decompress(&compressed).unwrap();
assert_eq!(data, decompressed.as_slice());
}
#[test]
fn test_gzip_compression_ratio() {
let compressor = GzipCompressor::new();
let data = b"A".repeat(1000);
let compressed = compressor.compress(&data).unwrap();
assert!(compressed.len() < data.len() / 10);
}
#[test]
fn test_gzip_with_level() {
let low_compression = GzipCompressor::with_level(1);
let high_compression = GzipCompressor::with_level(9);
let data = b"Test data for compression level comparison.".repeat(10);
let low_compressed = low_compression.compress(&data).unwrap();
let high_compressed = high_compression.compress(&data).unwrap();
assert!(high_compressed.len() <= low_compressed.len());
assert_eq!(low_compression.decompress(&low_compressed).unwrap(), data);
assert_eq!(high_compression.decompress(&high_compressed).unwrap(), data);
}
#[test]
fn test_gzip_empty_data() {
let compressor = GzipCompressor::new();
let data = b"";
let compressed = compressor.compress(data).unwrap();
let decompressed = compressor.decompress(&compressed).unwrap();
assert_eq!(data, decompressed.as_slice());
}
#[test]
fn test_gzip_large_data() {
let compressor = GzipCompressor::new();
let data = vec![b'X'; 100_000];
let compressed = compressor.compress(&data).unwrap();
let decompressed = compressor.decompress(&compressed).unwrap();
assert_eq!(data, decompressed);
assert!(compressed.len() < 1000);
}
#[test]
fn test_gzip_name() {
let compressor = GzipCompressor::new();
assert_eq!(compressor.name(), "gzip");
}
#[test]
fn test_gzip_level_getter() {
let compressor = GzipCompressor::with_level(9);
assert_eq!(compressor.level(), 9);
}
#[test]
fn test_gzip_default() {
let compressor = GzipCompressor::default();
assert_eq!(compressor.level(), 6);
}
#[test]
fn test_gzip_no_compression() {
let compressor = GzipCompressor::with_level(0);
let data = b"Test data";
let compressed = compressor.compress(data).unwrap();
let decompressed = compressor.decompress(&compressed).unwrap();
assert_eq!(data, decompressed.as_slice());
}
}