Skip to content

Async API

zesven provides an async/await API for non-blocking archive operations. Both halves of it cover a subset of the blocking API: see Limitations before choosing between them.

Feature Flag

Enable the async feature:

toml
[dependencies]
zesven = { version = "3.2", features = ["async"] }

Quick Example

rust
use zesven::{AsyncArchive, AsyncExtractOptions, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let mut archive = AsyncArchive::open_path("archive.7z").await?;

    for entry in archive.entries() {
        println!("{}: {} bytes", entry.path.as_str(), entry.size);
    }

    archive.extract("./output", (), &AsyncExtractOptions::default()).await?;
    Ok(())
}

Key Types

TypeDescription
AsyncArchiveAsync archive reader
AsyncWriterAsync archive writer
AsyncExtractOptionsExtraction configuration

Limitations

AsyncWriter writes the same archives as the blocking Writer, from the same folder model and header encoder, and awaits its I/O rather than blocking on it. It does not implement everything the blocking writer does, and returns an error rather than quietly ignoring what it cannot apply:

  • Encryption, including header encryption
  • Pre-compression filters, such as delta and the branch converters
  • Solid mode
  • Archive comments

It also has no multi-volume output: there is no async counterpart to Writer::create_multivolume. And it buffers each entry whole before compressing it, so memory_limit bounds the concurrency of compression but not what the writer holds.

AsyncArchive reads plain single-file archives. The blocking Archive also handles two shapes it does not:

  • Multi-volume sets. Archive::open_path recognises one from its name and reads through the volumes; AsyncArchive::open_path opens the one file it was given, so archive.7z.001 fails once reading passes the end of that volume.
  • Self-extracting archives. The blocking reader finds the 7z data after the executable stub; the async one looks at offset zero and reports an invalid signature.
  • BCJ2 folders. A BCJ2 chain takes four inputs, and the async decoder builds single-input chains only, so such an entry is reported as failed rather than decoded. Other folders in the same archive still read.

Use the blocking Archive for either.

For any of the above, use the blocking API.

When to Use Async

Use the async API when:

  • Building async applications (web servers, CLI tools with async runtimes)
  • Processing multiple archives concurrently
  • Need non-blocking I/O
  • Integrating with Tokio ecosystem

Topics

Basic Operations

Reading Archives

rust
use zesven::{AsyncArchive, AsyncExtractOptions, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let mut archive = AsyncArchive::open_path("archive.7z").await?;

    // List entries
    for entry in archive.entries() {
        println!("{}", entry.path.as_str());
    }

    // Extract all
    archive.extract("./output", (), &AsyncExtractOptions::default()).await?;
    Ok(())
}

Creating Archives

rust
use zesven::{AsyncWriter, ArchivePath, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let mut writer = AsyncWriter::create_path("new.7z").await?;

    writer.add_bytes(ArchivePath::new("hello.txt")?, b"Hello").await?;
    writer.finish().await?;
    Ok(())
}

Concurrent Processing

Process multiple archives concurrently:

rust
use zesven::{AsyncArchive, AsyncExtractOptions, Result};
use futures::future::join_all;

#[tokio::main]
async fn main() -> Result<()> {
    let archives = vec!["a.7z", "b.7z", "c.7z"];

    let tasks: Vec<_> = archives.iter().map(|path| {
        async move {
            let mut archive = AsyncArchive::open_path(path).await?;
            archive.extract(
                format!("./output/{}", path),
                (),
                &AsyncExtractOptions::default()
            ).await
        }
    }).collect();

    join_all(tasks).await;
    Ok(())
}

See Also

Released under MIT OR Apache-2.0 License