tinyzip 0.4.0

Low level ZIP file parsing and navigation
Documentation
mod fixture;

use criterion::{criterion_group, criterion_main, Criterion};
use std::io::{Cursor, Read};

fn bench_find_file(c: &mut Criterion) {
    let zip_bytes = fixture::generate();

    let mut group = c.benchmark_group("find_file");

    group.bench_function("tinyzip", |b| {
        b.iter(|| {
            let archive = tinyzip::Archive::open(zip_bytes.as_slice()).unwrap();
            archive
                .find_file(fixture::TARGET_FILE.as_bytes())
                .unwrap();
        });
    });

    group.bench_function("zip", |b| {
        b.iter(|| {
            let archive = zip::ZipArchive::new(Cursor::new(&zip_bytes)).unwrap();
            archive.index_for_name(fixture::TARGET_FILE).unwrap();
        });
    });

    group.finish();
}

fn bench_extract(c: &mut Criterion) {
    let zip_bytes = fixture::generate();

    let expected_size = {
        let mut archive = zip::ZipArchive::new(Cursor::new(&zip_bytes)).unwrap();
        archive.by_name(fixture::TARGET_FILE).unwrap().size() as usize
    };

    let mut group = c.benchmark_group("extract");

    group.bench_function("tinyzip + miniz_oxide", |b| {
        let mut decompressed = vec![0u8; expected_size];
        b.iter(|| {
            let archive = tinyzip::Archive::open(zip_bytes.as_slice()).unwrap();
            let entry = archive
                .find_file(fixture::TARGET_FILE.as_bytes())
                .unwrap();
            match entry.compression().unwrap() {
                tinyzip::Compression::Deflated => {
                    let mut chunks = entry.read_chunks::<4096>().unwrap();
                    let mut state = miniz_oxide::inflate::stream::InflateState::new(
                        miniz_oxide::DataFormat::Raw,
                    );
                    let mut out_pos = 0;
                    while let Some(chunk) = chunks.next() {
                        let result = miniz_oxide::inflate::stream::inflate(
                            &mut state,
                            chunk.unwrap(),
                            &mut decompressed[out_pos..],
                            miniz_oxide::MZFlush::None,
                        );
                        out_pos += result.bytes_written;
                    }
                }
                tinyzip::Compression::Stored => {
                    entry.read_to_slice(&mut decompressed).unwrap();
                }
            }
        });
    });

    group.bench_function("zip", |b| {
        let mut buf = Vec::with_capacity(expected_size);
        b.iter(|| {
            buf.clear();
            let mut archive = zip::ZipArchive::new(Cursor::new(&zip_bytes)).unwrap();
            let mut entry = archive.by_name(fixture::TARGET_FILE).unwrap();
            entry.read_to_end(&mut buf).unwrap();
        });
    });

    group.finish();
}

criterion_group!(benches, bench_find_file, bench_extract);
criterion_main!(benches);