Skip to content

Shua-github/Shua-Zip

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Shua-Zip

A slim, #![no_std] compatible ZIP library written in pure Rust.

Feature Flags

Feature Default Description
deflate on Deflate decompression via miniz_oxide
crc32 on CRC-32 checksums via crc32fast

With default-features = false you get a minimal no_std build — no compression support, no CRC-32 dependency. Bring your own CRC via the Crc32 trait.

Library Usage

Creating archives

use shua_zip::ZipArchive;

let mut archive = ZipArchive::new();
archive.add_file("hello.txt", b"Hello, world!");
archive.add_file("data.bin", vec![0, 1, 2, 3]);

let zip_bytes: Vec<u8> = archive.build().unwrap();
std::fs::write("output.zip", &zip_bytes).unwrap();

Removing files

// Remove by index
if let Some(entry) = archive.remove_file(0) {
    println!("Removed: {}", entry.name);
}

// Remove by name
if let Some(idx) = archive.find_by_name("hello.txt") {
    archive.remove_file(idx);
}

Appending to an existing archive

Use build_with_readat to avoid loading existing file data into memory:

use shua_zip::{ZipArchive, ReadAt};

let reader = /* impl ReadAt */;
let mut archive = ZipArchive::new()
    .with_binary(&reader)?;    // parse existing entries
archive.add_file("new.txt", b"fresh content");
let zip_bytes = archive.build_with_readat(&reader)?;

Reading archives

ReadAt is the central trait — implement it for your storage backend:

use shua_zip::{ZipArchive, ReadAt, ZipReadStrategy};

let reader = /* impl ReadAt */;
let archive = ZipArchive::new().with_binary(&reader)?;

// List entries from the central directory
for entry in archive.entries() {
    println!("{} ({} bytes)", entry.name, entry.uncompressed_size);
}

// Find by name
if let Some(idx) = archive.find_by_name("hello.txt") {
    let data = archive.read_file(idx, &reader)?;
}

// Or use a specific read strategy
let data = archive.read_file_with_strategy(
    idx,
    &reader,
    ZipReadStrategy::Merged,
)?;

Read Strategies

Strategy Reads Description
Merged 1–2 Reads LFH + compressed data in one chunk. Falls back to a second read if data extends beyond the chunk. Recommended for high-latency backends.
Strict 2 Reads and validates the LFH first, then the data at the resolved offset. Safest for malformed files.
Optimistic 1 Skips header verification, jumps straight to the cached data offset. Fastest, may read garbage if offsets are wrong.

ReadAt trait

pub trait ReadAt {
    type Error: core::error::Error;
    fn size(&self) -> u64;
    fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<(), Self::Error>;
}

No Seek or Read required — just random-access reads. Works with files, byte slices, HTTP range requests, embedded flash, etc.

Custom decompressors

archive.register_decompressor(114514, |data| {
    // your custom decompression logic
    Ok(data.to_vec())
});

no_std with custom CRC

When crc32 feature is disabled, use add_file_with_crc with your own implementation:

struct MyCrc;
impl Crc32 for MyCrc {
    fn hash(data: &[u8]) -> u32 { /* ... */ }
}

archive.add_file_with_crc::<MyCrc>("data.bin", payload);

Supported Compression

Method ID Read Write
Stored 0 Yes Yes
Deflate 8 Yes (opt-in) No
Custom * Yes (via register_decompressor) No

CLI Example

# List contents
cargo run --example cli -- list archive.zip

# Extract to a directory
cargo run --example cli -- extract archive.zip ./output/

# Extract to default directory (archive name without extension)
cargo run --example cli -- extract archive.zip

# Create a new archive
cargo run --example cli -- create new.zip file1.txt file2.png

# Add files to an existing archive
cargo run --example cli -- add existing.zip another.txt

# Remove files from an archive
cargo run --example cli -- remove archive.zip old.txt unused.bin

Compatibility

Cross-tested against the zip crate: archives written by either library are correctly read by the other, including deflate-compressed entries, empty files, Unicode filenames, and large payloads. See tests/compat_zip.rs for the full suite.

Benchmarks in benches/compare_zip.rs cover build/parse/read/roundtrip against zip-rs.

License

MIT

About

A slim, #![no_std] compatible ZIP library written in pure Rust.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages