Skip to content

Latest commit

 

History

1,552 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

brotli.zig

Documentation Zig Version GitHub stars GitHub issues GitHub pull requests GitHub last commit License Supported Platforms Latest Release Sponsor GitHub Sponsors

Native Zig implementation of the Brotli RFC 7932 compression format.

Documentation | API Reference | Quick Start | Contributing

brotli.zig is a complete native Zig implementation of the Brotli compressed-data format (RFC 7932, including Large Window Brotli). No C bindings, no external dependencies. Every byte is Zig.

Tip

If you build with brotli.zig, make sure to give it a star.

Important

Version 0.0.1 used C bindings as a wrapper around the reference Brotli C library. It is deprecated and should not be used in new projects. Starting with v0.0.3, brotli.zig is a fully native Zig implementation — no C code, no libc, no external dependencies. All compression and decompression runs entirely in Zig.

Note

This implementation is based on Brotli v1.2.0 as the format specification (RFC 7932), re-designed with Zig idioms and implemented natively.

Pure Zig — zero C dependencies: Unlike binding-based approaches, brotli.zig implements the Brotli format directly in Zig, including:

  • Streaming decoder state machine — window bits (incl. large window), metablock headers, metadata blocks, uncompressed metablocks, partial input/output resumption
  • Huffman decoding — code-length tables, two-level explicit tables, simple/tree-select tables
  • Context modeling — the full 2048-entry literal context lookup table; the encoder emits second-order context-modeled literals with clustered context maps
  • LZ77 back-references with distance ring-buffer shortcuts
  • Static dictionary — the complete 122,784-byte RFC 7932 word list; the encoder emits dictionary word references (including uppercase transforms) and both sides accept custom raw dictionaries
  • Custom dictionaries — attach shared raw bytes to encoder and decoder for small-payload compression
  • Native encoder — hash-chain match finder, Huffman table construction, metablock emission, quality levels 0–11, literal block switching, second-order context modeling with clustered context maps, NPOSTFIX/NDIRECT distance coding, large-window streams up to LGWIN 30, and metadata metablocks
  • Progress callbacks — observe streaming compression progress for large files
  • Parameter API — all nine PARAM_* encoder knobs mirroring the C enumeration

Features (click to expand)
Feature Description
One-shot Compression brotli.compress() for single-call compression with default options
One-shot Decompression brotli.decompress() for single-call decompression
Compression Levels Quality 0–11 via brotli.compressWithOptions(.{ .quality = ... })
Reusable Encoder Encoder for efficient multi-block streaming with setParameter() control
Reusable Decoder Decoder streaming state machine with detailed error codes
Streaming Compression StreamingCompressor chunked processing with process/flush/finish
Streaming Decompression StreamingDecompressor chunked processing with feed/take
Dictionary Compression attachDictionary() on both encoder and decoder
Built-in Static Dictionary Complete RFC 7932 122,784-byte word list + 121 transforms, zero config
Window Sizes LGWIN 10–24 standard; large-window decode up to 30
Modes Generic, text, and font analysis hints
Large Window Optional LGWIN up to 30 encode/decode (incompatible extension)
Metadata Blocks Emit side-channel metadata via emitMetadata() / .emit_metadata
Parameter API All nine PARAM_* identifiers mirroring BrotliEncoderSetParameter
Progress Callbacks Optional observer during streaming compression
Preallocated Output decompressInto() and maxCompressedSize() for buffer control
Detailed Errors Every decoder failure carries a named ErrorCode mirroring C strings
Cross-platform Linux, Windows, macOS; x86_64, aarch64, x86 (32-bit)
Zero Dependencies Pure Zig implementation — no C libraries, no system dependencies

Prerequisites and Supported Platforms (click to expand)

Prerequisites

Requirement Version Notes
Zig 0.16.0 (required) Download from ziglang.org
Operating System Windows 10+, Linux, macOS Cross-platform support

Supported Platforms

brotli.zig targets these architectures:

Platform x86_64 (64-bit) aarch64 (ARM64) x86 (32-bit)
Linux Yes Yes Yes
Windows Yes Yes Yes
macOS Yes Yes (Apple Silicon) Yes

Cross-Compilation

Zig makes cross-compilation easy. Build for any target from any host:

# Build for Linux ARM64 from Windows
zig build -Dtarget=aarch64-linux

# Build for Windows from Linux
zig build -Dtarget=x86_64-windows

# Build for macOS Apple Silicon from Linux
zig build -Dtarget=aarch64-macos

# Build for 32-bit Windows
zig build -Dtarget=x86-windows

Installation

Method 1: Zig Fetch (Recommended)

Latest Release (v0.0.3)

zig fetch --save https://github.com/muhammad-fiaz/brotli.zig/archive/refs/tags/0.0.3.tar.gz

Method 2: Zig Fetch (Main Branch)

zig fetch --save git+https://github.com/muhammad-fiaz/brotli.zig.git

Method 3: Manual build.zig.zon Configuration

.dependencies = .{
    .brotli = .{
        .url = "https://github.com/muhammad-fiaz/brotli.zig/archive/refs/tags/0.0.3.tar.gz",
        .hash = "...", // Run `zig fetch --save <url>` to generate the hash.
    },
},

Method 4: Local Source Checkout

git clone https://github.com/muhammad-fiaz/brotli.zig.git
cd brotli.zig
zig build

Path dependency in another project's build.zig.zon:

.dependencies = .{
    .brotli = .{
        .path = "../brotli.zig",
    },
},

Wire into build.zig

const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

const brotli_dep = b.dependency("brotli", .{
    .target = target,
    .optimize = optimize,
});
exe.root_module.addImport("brotli", brotli_dep.module("brotli"));

Quick Start

One-Liner Compression

const brotli = @import("brotli");

const compressed = try brotli.compress(allocator, data);
defer allocator.free(compressed);

const decompressed = try brotli.decompress(allocator, compressed);
defer allocator.free(decompressed);

Full Options

const compressed = try brotli.compressWithOptions(allocator, data, .{
    .quality = 9,          // 0..11
    .lgwin = 22,           // 10..24 window bits
    .mode = .text,         // generic | text | font
    .size_hint = data.len, // improves progress reporting
});
defer allocator.free(compressed);

Reusable Contexts

var enc = brotli.Encoder.init(allocator, .{ .quality = 11 });
defer enc.deinit();

try enc.compressStream(.process, chunk_a);
try enc.compressStream(.flush, null);
try enc.compressStream(.finish, null);
// drain enc.out.items[enc.out_pos..]

Simplified API Aliases

// Compression
const compressed = try brotli.compress(allocator, data);
const tuned = try brotli.compressWithOptions(allocator, data, .{ .quality = 9 });
const bound = brotli.maxCompressedSize(data.len);

// Decompression
const out = try brotli.decompress(allocator, compressed);
var dst: [1024]u8 = undefined;
const n = try brotli.decompressInto(allocator, compressed, &dst);

// Dictionaries
_ = enc.attachDictionary(dict_bytes);
_ = dec.attachDictionary(dict_bytes);

// Progress
enc.setProgress(myCallback, &my_ctx);

// Version
const ver = brotli.versionNumber();
const str = brotli.versionString();

Streaming

// Compression
var sc = brotli.StreamingCompressor.init(allocator, .{ .quality = 9 });
defer sc.deinit();
const piece = try sc.process(chunk);   // returns owned slice
const tail = try sc.finish();          // final block

// Decompression
var sd = brotli.StreamingDecompressor.init(allocator, .{});
defer sd.deinit();
sd.feed(chunk);
var buf: [4096]u8 = undefined;
const n = try sd.take(&buf);

Dictionary Compression

// Attach identical bytes to both sides BEFORE use.
if (!enc.attachDictionary(dict_bytes)) return error.InvalidDictionary;
if (!dec.attachDictionary(dict_bytes)) return error.InvalidDictionary;

// Now streams reference the corpus compactly:
const tiny = try brotli.compress(allocator, overlapping_input);
defer allocator.free(tiny); // only decodable with the same dict attached

The built-in RFC 7932 static dictionary works automatically on both sides.

API Reference

Top-Level Functions

Function Description
brotli.compress(alloc, src) One-shot compression (quality 11)
brotli.decompress(alloc, src) One-shot decompression
brotli.compressWithOptions(alloc, src, opts) Compress with CompressionOptions
brotli.decompressWithOptions(alloc, src, opts) Decompress with DecoderOptions
brotli.decompressInto(dst, src) Decompress into preallocated buffer
brotli.maxCompressedSize(src_size) Maximum compressed size for allocation
brotli.versionString() / versionNumber() Library version

Types

Type Description
Encoder Streaming encoder: init(alloc, opts), setParameter(id, val), attachDictionary(), setProgress(), compressStream(op, in), takeOutput(), isFinished()
Decoder Streaming decoder: init(alloc, opts), attachDictionary(), decompressStream(&in,&out,&total), errorCode().name()
StreamingCompressor Chunk facade: init(alloc, opts), process(chunk), flush(), finish(), setProgress(), attachDictionary()
StreamingDecompressor Chunk facade: init(alloc, opts), feed(chunk), take(out), isFinished(), totalOut()
CompressionOptions quality, lgwin, mode, lgblock, size_hint, large_window, npostfix, ndirect, progress, progress_ctx
DecoderOptions large_window: bool
ErrorCode Named decoder errors mirroring BrotliDecoderErrorStr
MetadataCallbacks Decoder metadata-block observers

Parameter Identifiers

PARAM_MODE, PARAM_QUALITY, PARAM_LGWIN, PARAM_LGBLOCK, PARAM_DISABLE_LITERAL_CONTEXT_MODELING, PARAM_SIZE_HINT, PARAM_LARGE_WINDOW, PARAM_NPOSTFIX, PARAM_NDIRECT — pass to Encoder.setParameter(id, value).

Namespaces

Namespace Description
brotli.constants Format limits: alphabet sizes, window bounds, distance caps
brotli.Dictionary Embedded RFC 7932 static dictionary resource
brotli.huffman / bit_writer / BitReader Low-level primitives (advanced use)

Examples

The examples/ directory contains runnable examples:

Example File Description
compress_file examples/compress_file.zig One-shot compression across quality levels with round-trip verification
streaming_compression examples/streaming_compression.zig 4 MiB chunked streaming with progress callback
decompress_file examples/decompress_file.zig Basic decompression
streaming_decompression examples/streaming_decompression.zig Chunked decompression
dictionary_compression examples/dictionary_compression.zig Shared-dictionary round trip (plain decode fails without it!)
reusable_context examples/reusable_context.zig Multiple streams on one context
error_handling examples/error_handling.zig Corruption, truncation, and error diagnostics
format_introspection examples/format_introspection.zig Version, limits, and constants
bit_level examples/bit_level.zig Low-level bit reader/writer primitives

To run any example:

zig build run-compress_file
zig build run-streaming_compression
zig build run-dictionary_compression
zig build run-all-examples   # everything at once

Validation Matrix

Validate host functionality and cross-target compatibility:

# Host runtime validation
zig build test --summary all
zig build run-all-examples

# Cross-target library compile validation
zig build -Dtarget=aarch64-linux
zig build -Dtarget=x86_64-windows
zig build -Dtarget=aarch64-macos
zig build -Dtarget=x86-windows

Building & Testing

zig build                    # Build library
zig build test               # Run all tests
zig build test --summary all # With summary
zig build run-all-examples   # Run all examples
zig build fuzz               # Decoder robustness fuzzer
zig build docs               # Generate API documentation

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass: zig build test --summary all
  5. Ensure formatting passes: zig fmt --check src/
  6. Submit a pull request

See CONTRIBUTING.md for detailed guidelines.

License

MIT License — see LICENSE for details.

Author

Muhammad Fiaz (https://github.com/muhammad-fiaz)

Releases

Sponsor this project

Packages

Contributors

Languages