use std::io::prelude::*;
use flate2::{Compression, read::ZlibDecoder, write::ZlibEncoder};
#[derive(Debug, Clone, Copy, PartialOrd, PartialEq)]
#[derive(serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum CompressionMode {
Zlib,
}
impl CompressionMode {
pub fn compress(&self, bytes: &[u8]) -> Option<Vec<u8>> {
match self {
Self::Zlib => {
let mut enc = ZlibEncoder::new(Vec::new(), Compression::best());
enc.write_all(bytes).ok()?;
enc.finish().ok()
}
}
}
pub fn decompress(&self, bytes: &[u8]) -> Option<Vec<u8>> {
match self {
Self::Zlib => {
let mut dec = ZlibDecoder::new(bytes);
let mut out = Vec::new();
dec.read_to_end(&mut out).ok()?;
Some(out)
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
use rand::prelude::*;
#[test]
fn zlib_roundtrip() {
let values: [u8; 10] = rand::rng().random();
let data = values
.into_iter()
.flat_map(|v| {
let n: usize = rand::rng().random_range(16..48);
std::iter::repeat_n(v, n)
})
.collect::<Vec<_>>();
let compressed = CompressionMode::Zlib.compress(&data).unwrap();
assert!(compressed.len() < data.len());
let decompress = CompressionMode::Zlib.decompress(&compressed).unwrap();
assert_eq!(decompress, data);
}
}