extendable_assets/asset/serialize/
compression.rs1use std::io::prelude::*;
2
3use flate2::{Compression, read::ZlibDecoder, write::ZlibEncoder};
4
5#[derive(Debug, Clone, Copy, PartialOrd, PartialEq)]
12#[derive(serde::Deserialize, serde::Serialize)]
13#[serde(rename_all = "snake_case")]
14#[non_exhaustive]
15pub enum CompressionMode {
16 Zlib,
18}
19impl CompressionMode {
20 pub fn compress(&self, bytes: &[u8]) -> Option<Vec<u8>> {
28 match self {
29 Self::Zlib => {
30 let mut enc = ZlibEncoder::new(Vec::new(), Compression::best());
31 enc.write_all(bytes).ok()?;
32 enc.finish().ok()
33 }
34 }
35 }
36
37 pub fn decompress(&self, bytes: &[u8]) -> Option<Vec<u8>> {
45 match self {
46 Self::Zlib => {
47 let mut dec = ZlibDecoder::new(bytes);
48 let mut out = Vec::new();
49 dec.read_to_end(&mut out).ok()?;
50 Some(out)
51 }
52 }
53 }
54}
55
56#[cfg(test)]
57mod test {
58 use super::*;
59 use rand::prelude::*;
60 #[test]
61 fn zlib_roundtrip() {
62 let values: [u8; 10] = rand::rng().random();
64 let data = values
65 .into_iter()
66 .flat_map(|v| {
67 let n: usize = rand::rng().random_range(16..48);
68 std::iter::repeat_n(v, n)
69 })
70 .collect::<Vec<_>>();
71
72 let compressed = CompressionMode::Zlib.compress(&data).unwrap();
74 assert!(compressed.len() < data.len());
75
76 let decompress = CompressionMode::Zlib.decompress(&compressed).unwrap();
78 assert_eq!(decompress, data);
79 }
80}