use flate2::{
write::{GzEncoder, GzDecoder, DeflateEncoder, DeflateDecoder, ZlibEncoder, ZlibDecoder},
Compression,
};
use std::io::Write;
pub enum CompressionFormat {
Gzip,
Deflate,
Zlib,
}
pub enum CompressionLevel {
Fastest,
Default,
Best,
}
impl CompressionLevel {
fn to_flate2_compression(&self) -> Compression {
match self {
CompressionLevel::Fastest => Compression::fast(),
CompressionLevel::Default => Compression::default(),
CompressionLevel::Best => Compression::best(),
}
}
}
pub fn compress(
input: &[u8],
format: CompressionFormat,
level: CompressionLevel,
) -> Result<Vec<u8>, String> {
let compression = level.to_flate2_compression();
match format {
CompressionFormat::Gzip => {
let mut encoder = GzEncoder::new(Vec::new(), compression);
encoder
.write_all(input)
.map_err(|e| format!("Compression error: {}", e))?;
encoder
.finish()
.map_err(|e| format!("Failed to finish compression: {}", e))
}
CompressionFormat::Deflate => {
let mut encoder = DeflateEncoder::new(Vec::new(), compression);
encoder
.write_all(input)
.map_err(|e| format!("Compression error: {}", e))?;
encoder
.finish()
.map_err(|e| format!("Failed to finish compression: {}", e))
}
CompressionFormat::Zlib => {
let mut encoder = ZlibEncoder::new(Vec::new(), compression);
encoder
.write_all(input)
.map_err(|e| format!("Compression error: {}", e))?;
encoder
.finish()
.map_err(|e| format!("Failed to finish compression: {}", e))
}
}
}
pub fn decompress(input: &[u8], format: CompressionFormat) -> Result<Vec<u8>, String> {
match format {
CompressionFormat::Gzip => {
let mut decoder = GzDecoder::new(Vec::new());
decoder
.write_all(input)
.map_err(|e| format!("Decompression error: {}", e))?;
decoder
.finish()
.map_err(|e| format!("Failed to finish decompression: {}", e))
}
CompressionFormat::Deflate => {
let mut decoder = DeflateDecoder::new(Vec::new());
decoder
.write_all(input)
.map_err(|e| format!("Decompression error: {}", e))?;
decoder
.finish()
.map_err(|e| format!("Failed to finish decompression: {}", e))
}
CompressionFormat::Zlib => {
let mut encoder = ZlibDecoder::new(Vec::new());
encoder
.write_all(input)
.map_err(|e| format!("Compression error: {}", e))?;
encoder
.finish()
.map_err(|e| format!("Failed to finish compression: {}", e))
}
}
}
pub fn compress_stream(
chunks: &[&[u8]],
format: CompressionFormat,
level: CompressionLevel,
) -> Result<Vec<u8>, String> {
let compression = level.to_flate2_compression();
match format {
CompressionFormat::Gzip => {
let mut encoder = GzEncoder::new(Vec::new(), compression);
for chunk in chunks {
encoder
.write_all(chunk)
.map_err(|e| format!("Stream compression error: {}", e))?;
}
encoder
.finish()
.map_err(|e| format!("Failed to finish streaming compression: {}", e))
}
CompressionFormat::Deflate => {
let mut encoder = DeflateEncoder::new(Vec::new(), compression);
for chunk in chunks {
encoder
.write_all(chunk)
.map_err(|e| format!("Stream compression error: {}", e))?;
}
encoder
.finish()
.map_err(|e| format!("Failed to finish streaming compression: {}", e))
}
CompressionFormat::Zlib => {
let mut encoder = ZlibEncoder::new(Vec::new(), compression);
for chunk in chunks {
encoder
.write_all(chunk)
.map_err(|e| format!("Stream compression error: {}", e))?;
}
encoder
.finish()
.map_err(|e| format!("Failed to finish streaming compression: {}", e))
}
}
}
pub fn decompress_stream(
chunks: &[&[u8]],
format: CompressionFormat,
) -> Result<Vec<u8>, String> {
match format {
CompressionFormat::Gzip => {
let mut decoder = GzDecoder::new(Vec::new());
for chunk in chunks {
decoder
.write_all(chunk)
.map_err(|e| format!("Stream decompression error: {}", e))?;
}
decoder
.finish()
.map_err(|e| format!("Failed to finish streaming decompression: {}", e))
}
CompressionFormat::Deflate => {
let mut decoder = DeflateDecoder::new(Vec::new());
for chunk in chunks {
decoder
.write_all(chunk)
.map_err(|e| format!("Stream decompression error: {}", e))?;
}
decoder
.finish()
.map_err(|e| format!("Failed to finish streaming decompression: {}", e))
}
CompressionFormat::Zlib => {
let mut decoder = ZlibDecoder::new(Vec::new());
for chunk in chunks {
decoder
.write_all(chunk)
.map_err(|e| format!("Stream decompression error: {}", e))?;
}
decoder
.finish()
.map_err(|e| format!("Failed to finish streaming decompression: {}", e))
}
}
}
pub fn compress_string(input: &str, level: CompressionLevel) -> Result<Vec<u8>, String> {
compress(input.as_bytes(), CompressionFormat::Gzip, level)
}
pub fn decompress_to_string(compressed_data: &[u8]) -> Result<String, String> {
let decompressed_data = decompress(compressed_data, CompressionFormat::Gzip)?;
String::from_utf8(decompressed_data).map_err(|e| format!("UTF-8 error: {}", e))
}