use bun_zlib::{Options, ZlibReaderArrayList};
fn stream_decode(format_bits: i32, compressed: &[u8], chunks: &[usize]) -> Vec<u8> {
let mut seats: Vec<&[u8]> = Vec::new();
let mut off = 0usize;
for &len in chunks {
let end = off.saturating_add(len).min(compressed.len());
seats.push(&compressed[off..end]);
off = end;
}
if off < compressed.len() {
seats.push(&compressed[off..]);
}
let mut out: Vec<u8> = Vec::new();
let mut reader = ZlibReaderArrayList::init_with_options(
seats[0],
&mut out,
Options { window_bits: format_bits, ..Default::default() },
)
.expect("init");
let last = seats.len() - 1;
for (i, seat) in seats.iter().enumerate() {
if i > 0 {
reader.input = seat;
}
match reader.read_all(i == last) {
Ok(()) => {}
Err(e) if i != last && e == bun_zlib::ZlibError::ShortRead => {}
Err(e) => panic!("read_all(seat {i}/{last}) failed: {e:?}"),
}
}
drop(reader);
out
}
fn gz(input: &[u8]) -> Vec<u8> {
let mut enc = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::default());
use std::io::Write;
enc.write_all(input).unwrap();
enc.finish().unwrap()
}
fn zlib_stream(input: &[u8]) -> Vec<u8> {
let mut enc = flate2::write::ZlibEncoder::new(Vec::new(), flate2::Compression::default());
use std::io::Write;
enc.write_all(input).unwrap();
enc.finish().unwrap()
}
fn raw_stream(input: &[u8]) -> Vec<u8> {
let mut enc = flate2::write::DeflateEncoder::new(Vec::new(), flate2::Compression::default());
use std::io::Write;
enc.write_all(input).unwrap();
enc.finish().unwrap()
}
fn body() -> Vec<u8> {
let mut x: u64 = 0x9E3779B97F4A7C15;
(0..(63 * 1024))
.map(|_| {
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
(x >> 33) as u8
})
.collect()
}
#[test]
fn gzip_single_shot() {
let body = body();
let out = stream_decode(31, &gz(&body), &[usize::MAX]);
assert_eq!(out, body);
}
#[test]
fn gzip_header_split_across_chunks() {
let out = stream_decode(31, &gz(&body()), &[3, usize::MAX]);
assert_eq!(out.len(), body().len());
}
#[test]
fn gzip_trailer_split_across_chunks() {
let compressed = gz(&body());
let split = compressed.len() - 4; let out = stream_decode(31, &compressed, &[split, usize::MAX]);
assert_eq!(out.len(), body().len());
}
#[test]
fn gzip_byte_at_a_time() {
let compressed = gz(b"hello streaming gzip world");
let seats: Vec<usize> = (0..compressed.len()).map(|_| 1usize).collect();
let out = stream_decode(31, &compressed, &seats);
assert_eq!(out, b"hello streaming gzip world");
}
#[test]
fn gzip_multi_member() {
let mut both = gz(b"first-member|").clone();
both.extend_from_slice(&gz(b"second-member"));
let out = stream_decode(31, &both, &[usize::MAX]);
assert_eq!(out, b"first-member|second-member");
}
#[test]
fn gzip_multi_member_split_between_members() {
let mut both = gz(b"AAA").clone();
let boundary = both.len();
both.extend_from_slice(&gz(b"BBB"));
let out = stream_decode(31, &both, &[boundary, usize::MAX]);
assert_eq!(out, b"AAABBB");
}
#[test]
fn gzip_mid_deflate_chunks() {
let compressed = gz(&body());
let seats: Vec<usize> = compressed.chunks(8 * 1024).map(|c| c.len()).collect();
let out = stream_decode(31, &compressed, &seats);
assert_eq!(out.len(), body().len());
}
#[test]
fn zlib_stream_multi_chunk() {
let compressed = zlib_stream(&body());
let seats: Vec<usize> = compressed.chunks(5 * 1024).map(|c| c.len()).collect();
let out = stream_decode(15, &compressed, &seats);
assert_eq!(out.len(), body().len());
}
#[test]
fn raw_stream_multi_chunk() {
let compressed = raw_stream(&body());
let seats: Vec<usize> = compressed.chunks(7 * 1024).map(|c| c.len()).collect();
let out = stream_decode(-15, &compressed, &seats);
assert_eq!(out.len(), body().len());
}
#[test]
fn auto_detect_gzip_and_zlib() {
assert_eq!(stream_decode(0, &gz(b"auto-gzip"), &[usize::MAX]), b"auto-gzip");
assert_eq!(stream_decode(0, &zlib_stream(b"auto-zlib"), &[usize::MAX]), b"auto-zlib");
assert_eq!(stream_decode(47, &gz(b"auto47"), &[usize::MAX]), b"auto47");
}
#[test]
fn gzip_corrupt_crc_fails() {
let mut compressed = gz(&body());
let last = compressed.len() - 1;
compressed[last] ^= 0xff; let mut out = Vec::new();
let mut reader = ZlibReaderArrayList::init_with_options(
&compressed,
&mut out,
Options { window_bits: 31, ..Default::default() },
)
.unwrap();
assert!(reader.read_all(true).is_err());
drop(reader);
}
#[test]
fn gzip_truncated_final_fails_not_shortread() {
let compressed = gz(&body());
let cut = &compressed[..compressed.len() - 5]; let mut out = Vec::new();
let mut reader = ZlibReaderArrayList::init_with_options(
cut,
&mut out,
Options { window_bits: 31, ..Default::default() },
)
.unwrap();
match reader.read_all(true) {
Err(bun_zlib::ZlibError::ZlibError) => {} other => panic!("expected ZlibError, got {other:?}"),
}
}
#[test]
fn gzip_partial_without_is_done_returns_short_read() {
let compressed = gz(&body());
let mut out = Vec::new();
let mut reader = ZlibReaderArrayList::init_with_options(
&compressed[..8 * 1024],
&mut out,
Options { window_bits: 31, ..Default::default() },
)
.unwrap();
match reader.read_all(false) {
Err(bun_zlib::ZlibError::ShortRead) => {}
other => panic!("expected ShortRead, got {other:?}"),
}
}
#[test]
fn max_output_size_enforced_streaming() {
let compressed = gz(&body());
let mut out = Vec::new();
let mut reader = ZlibReaderArrayList::init_with_options(
&compressed,
&mut out,
Options { window_bits: 31, ..Default::default() },
)
.unwrap();
reader.max_output_size = 1024;
assert!(reader.read_all(true).is_err());
drop(reader);
assert!(out.len() <= 1024 + 32 * 1024); }