diff options
Diffstat (limited to 'src/compress.rs')
| -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"); |
