use miniz_oxide::deflate::compress_to_vec;
pub(super) fn gzip(data: &[u8], level: u8) -> Vec<u8> {
let deflated = compress_to_vec(data, level);
let mut out = Vec::with_capacity(deflated.len() + 18);
out.extend_from_slice(&[
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, ]);
out.extend_from_slice(&deflated);
out.extend_from_slice(&crc32fast::hash(data).to_le_bytes());
out.extend_from_slice(&(data.len() as u32).to_le_bytes());
out
}
#[cfg(test)]
mod tests {
use super::*;
use miniz_oxide::inflate::decompress_to_vec;
#[test]
fn roundtrips_through_raw_inflate() {
let src: Vec<u8> = (0..4096u32).map(|i| (i * 31) as u8).collect();
let comp = gzip(&src, 6);
assert_eq!(&comp[..2], &[0x1f, 0x8b]);
let body = &comp[10..comp.len() - 8];
assert_eq!(decompress_to_vec(body).unwrap(), src);
let isize_le = &comp[comp.len() - 4..];
assert_eq!(
u32::from_le_bytes(isize_le.try_into().unwrap()),
src.len() as u32
);
}
#[test]
fn level_zero_stores_and_still_roundtrips() {
let src: Vec<u8> = (0..2048u32).map(|i| (i * 7) as u8).collect();
let stored = gzip(&src, 0);
let best = gzip(&src, 9);
assert!(best.len() <= stored.len());
let body = &stored[10..stored.len() - 8];
assert_eq!(decompress_to_vec(body).unwrap(), src);
}
}