use rawzip::{ZipArchive, ZipArchiveWriter, RECOMMENDED_BUFFER_SIZE};
use rstest::rstest;
use std::io::{Cursor, Write};
const ZIP64_EOCD_SIGNATURE: u32 = 0x06064b50;
const ZIP64_EOCD_LOCATOR_SIGNATURE: u32 = 0x07064b50;
fn contains_zip64_signatures(data: &[u8]) -> bool {
let zip64_eocd_sig_bytes = ZIP64_EOCD_SIGNATURE.to_le_bytes();
let zip64_locator_sig_bytes = ZIP64_EOCD_LOCATOR_SIGNATURE.to_le_bytes();
let has_eocd = data.windows(4).any(|w| w == zip64_eocd_sig_bytes);
let has_locator = data.windows(4).any(|w| w == zip64_locator_sig_bytes);
has_eocd && has_locator
}
fn verify_expected_entries(data: &[u8], expected_count: u64) {
let read_archive = ZipArchive::from_slice(data).unwrap();
assert_eq!(read_archive.entries_hint(), expected_count);
let entries = read_archive.entries();
let mut count = 0;
for _ in entries {
count += 1;
}
assert_eq!(count, expected_count as usize);
let mut buffer = vec![0u8; RECOMMENDED_BUFFER_SIZE];
let read_archive = ZipArchive::from_seekable(Cursor::new(data), &mut buffer).unwrap();
assert_eq!(read_archive.entries_hint(), expected_count);
let mut entries = read_archive.entries(&mut buffer);
let mut count = 0;
while entries.next_entry().unwrap().is_some() {
count += 1;
}
assert_eq!(count, expected_count as usize);
}
#[rstest]
#[case(65534, false)]
#[case(65535, true)]
#[case(65536, true)]
fn test_zip64_threshold_entries(#[case] entry_count: usize, #[case] should_be_zip64: bool) {
let output = Cursor::new(Vec::new());
let mut archive = ZipArchiveWriter::builder()
.with_capacity(entry_count)
.build(output);
for i in 0..entry_count {
let filename = format!("file_{:05}.txt", i);
let (mut entry, config) = archive.new_file(&filename).start().unwrap();
let mut writer = config.wrap(&mut entry);
writer.write_all(b"x").unwrap();
let (_, descriptor_output) = writer.finish().unwrap();
entry.finish(descriptor_output).unwrap();
}
let writer = archive.finish().unwrap();
let data = writer.into_inner();
let archive_type = if should_be_zip64 {
"ZIP64"
} else {
"standard ZIP"
};
println!(
"Created {} archive with {} entries",
archive_type, entry_count
);
let has_zip64 = contains_zip64_signatures(&data);
assert_eq!(
has_zip64, should_be_zip64,
"{} entries expected zip64: {}",
entry_count, should_be_zip64
);
verify_expected_entries(&data, entry_count as u64);
}