diff options
| author | tv <tv@krebsco.de> | 2026-11-05 04:17:21 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-05 04:17:21 +0100 |
| commit | c1b2645f3097f038c37ffa520f2a24ffd3c65649 (patch) | |
| tree | fb0e2359ed63f8a73a9f96021e285b86ba14fc2b | |
| parent | 0d3e68e20f0812a2fdf5c9736cf3161f30912211 (diff) | |
compress level 2
| -rw-r--r-- | src/compress.rs | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/src/compress.rs b/src/compress.rs index 77e634d..d175cda 100644 --- a/src/compress.rs +++ b/src/compress.rs @@ -12,12 +12,19 @@ use flate2::write::DeflateEncoder; /// Below this, deflating saves too little to be worth it. pub(crate) const WORTH_FROM: usize = 1024; +/// Not 1 (`Compression::fast`): `flate2` runs on zlib-rs here (another dependency asks +/// for it), whose level 1 is zlib-ng's quick deflate, with fixed Huffman codes only. +/// Those can't use a skewed alphabet: 64 KiB of random hex shrinks to 87% at level 1, to +/// 54% at level 2 (as at level 6), still quick. +const LEVEL: u32 = 2; + /// `bytes` deflated, if that makes them at least a tenth smaller. pub(crate) fn deflate(bytes: &[u8]) -> Option<Vec<u8>> { if bytes.len() < WORTH_FROM { return None; } - let mut encoder = DeflateEncoder::new(Vec::with_capacity(bytes.len() / 2), Compression::fast()); + let mut encoder = + DeflateEncoder::new(Vec::with_capacity(bytes.len() / 2), Compression::new(LEVEL)); encoder.write_all(bytes).ok()?; let deflated = encoder.finish().ok()?; (deflated.len() < bytes.len() - bytes.len() / 10).then_some(deflated) @@ -53,6 +60,18 @@ mod tests { "over the limit" ); assert!(deflate(b"short").is_none()); + // Hex has 4 bits in 8: about half, as Huffman codes alone get it. + let mut rng = crate::testrand::Rng::new(2); + let hex: String = (0..4096) + .map(|_| format!("{:016x}", rng.next_u64())) + .collect(); + let deflated = deflate(hex.as_bytes()).expect("hex shrinks"); + assert!( + deflated.len() < hex.len() * 6 / 10, + "{} of {}", + deflated.len(), + hex.len() + ); let mut rng = crate::testrand::Rng::new(1); let noise: Vec<u8> = (0..4096).map(|_| rng.next_u64() as u8).collect(); assert!(deflate(&noise).is_none(), "noise doesn't shrink"); |
