Skip to content

bzip2.zigThe Pure-Zig BZip2 Codec

Standard .bz2 files, bounded memory, and caller-owned allocators and I/O — nothing hidden, nothing linked.

At a glance ​

zig
const compressed = try bzip2.compress(gpa, data, .{ .level = 9 });
const restored = try bzip2.decompress(gpa, compressed, .{});

Both slices belong to the caller. Verification is on by default, so restored is either exactly data or the call fails.

When to reach for it ​

BZip2 trades speed for ratio. Text, source code, logs, database dumps and uncompressed containers all compress considerably better with it than with a faster format, at the cost of taking longer. If throughput matters more than output size, a different format is the better tool.

Use the level to trade between the two. The level is the block size in units of 100 kB, so level 1 codes 100 kB blocks and level 9 codes 900 kB ones.

Level 1Level 9
Block size100 kB900 kB
Compressionfasterslower
Ratioslightly worseslightly better

Intermediate levels are often the right answer, because the block-sorting stage dominates the cost and the difference between the extremes is usually small.

Reading input you did not create ​

Streams are validated structurally before use, and both the block and stream CRCs are verified before a result is returned. For anything fetched from outside the process, also cap the output:

zig
const restored = try bzip2.decompress(gpa, downloaded, .{
    .max_output_size = 64 * 1024 * 1024,
});

A short stream can expand into a much larger one, and the cap turns that into error.OutputTooLarge instead of an allocation whose size came from the sender.

Acknowledgements ​

This is a from-scratch, native Zig implementation of the BZip2 format. The format specification and the reference implementation used for this project is libarchive/bzip2.

Released under the MIT License.