Z64
A high-performance, robust Elixir library for parsing and extracting ZIP archives, with native support for PKWARE's Deflate64 (Compression Method 9) decompression algorithm.
Erlang's built-in :zip module and zlib wrapper do not support the Deflate64 compression method. This library bridges that gap by wrapping the official zlib infback9 C extension in a safe and efficient Zig-based NIF using the zigler compiler.
Memory allocations for the sliding window and decompression buffers are managed directly through Erlang's allocator, ensuring safety, performance, and complete compatibility with the BEAM.
Features
- Deflate64 (Method 9) Support: Decompress files compressed with PKWARE's Enhanced Deflate (64KB sliding window, up to 65536 distance, 65538 length).
- Standard Deflate (Method 8) & Stored (Method 0) Support: Can list and extract standard files in zip archives seamlessly.
- In-Memory and File-System extraction: Easily read archives from binary data or file paths.
- Integrity Validation: Automatically checks CRC-32 checksums of decompressed files to guarantee data integrity.
- Pure Zig NIF Integration: Safe and robust C/Zig interoperability without requiring manually written C-NIF boilerplates or makefiles.
Installation
Add z64 to your list of dependencies in mix.exs:
def deps do
[
{:z64, "~> 0.1.0"}
]
end
Quick Start
1. List Entries in a ZIP Archive
List all file metadata (including names, compressed size, uncompressed size, compression method, and CRC-32) within a ZIP file:
{:ok, entries} = Z64.list_entries("path/to/archive.zip")
# Or pass a binary
{:ok, entries} = Z64.list_entries(zip_binary)
# Output structure:
# [
# %Z64.Entry{
# filename: "document.txt",
# compression_method: 9, # Method 9 is Deflate64
# compressed_size: 4567,
# uncompressed_size: 15432,
# crc32: 3456789012,
# local_header_offset: 124,
# ...
# }
# ]
2. Extract a Specific Entry
Retrieve the uncompressed content of a single file from the ZIP archive:
case Z64.extract_entry("archive.zip", "large_deflate64_file.csv") do
{:ok, binary} ->
# Work with the decompressed binary data
IO.puts("Extracted #{byte_size(binary)} bytes!")
{:error, :file_not_found} ->
IO.puts("File not found in archive")
{:error, reason} ->
IO.puts("Decompression failed: #{inspect(reason)}")
end
3. Extract All Files (Unzip)
Extract the entire ZIP archive to a destination directory on the disk:
case Z64.unzip("archive.zip", "output_directory/") do
:ok ->
IO.puts("Archive extracted successfully!")
{:error, reason} ->
IO.puts("Extraction failed: #{inspect(reason)}")
end
How It Works
Deflate64 differs from standard DEFLATE (RFC 1951) primarily in:
- Sliding Window Size: 64KB instead of 32KB.
- Additional Distance Codes: Codes 30 and 31 represent distances up to 65,536 bytes.
- Larger Block/Length Limits: Support for lengths up to 65,538 bytes.
This library includes the official zlib contrib/infback9 implementation (written by Mark Adler) inside c_src/. This C code is compiled alongside a Zig wrapper (lib/z64/nif.ex), which acts as the NIF bridging Elixir and the C library.
All buffer management and allocation use the BEAM's internal memory allocator, ensuring zero memory leaks and complete safety.
Tests
Run the test suite using mix:
mix test