# 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`:
```elixir
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:
```elixir
{: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:
```elixir
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:
```elixir
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:
1. **Sliding Window Size**: 64KB instead of 32KB.
2. **Additional Distance Codes**: Codes 30 and 31 represent distances up to 65,536 bytes.
3. **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`:
```bash
mix test
```