Quick Start
This guide covers the essential compressionz APIs with practical examples.
Basic Compression & Decompression
Section titled “Basic Compression & Decompression”The simplest usage requires just two functions:
const std = @import("std");const cz = @import("compressionz");
pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator();
const original = "Hello, compressionz! This text will be compressed.";
// Compress const compressed = try cz.compress(.zstd, original, allocator); defer allocator.free(compressed);
// Decompress const decompressed = try cz.decompress(.zstd, compressed, allocator); defer allocator.free(decompressed);
std.debug.print("Original: {d} bytes\n", .{original.len}); std.debug.print("Compressed: {d} bytes\n", .{compressed.len}); std.debug.print("Match: {}\n", .{std.mem.eql(u8, original, decompressed)});}Choosing a Codec
Section titled “Choosing a Codec”Change the codec by swapping the enum value:
// Fast, good ratio (recommended for most cases)const zstd = try cz.compress(.zstd, data, allocator);
// Maximum speedconst lz4 = try cz.compress(.lz4, data, allocator);
// Self-describing, real-timeconst snappy = try cz.compress(.snappy, data, allocator);
// Universal compatibilityconst gzip = try cz.compress(.gzip, data, allocator);
// Best compression ratioconst brotli = try cz.compress(.brotli, data, allocator);Compression Levels
Section titled “Compression Levels”Control the speed/ratio trade-off:
// Fastest compression, lower ratioconst fast = try cz.compressWithOptions(.zstd, data, allocator, .{ .level = .fast,});
// Best compression, slowerconst best = try cz.compressWithOptions(.zstd, data, allocator, .{ .level = .best,});
// Available levels: .fastest, .fast, .default, .better, .bestDecompression Safety
Section titled “Decompression Safety”Protect against decompression bombs (malicious data that expands massively):
const decompressed = try cz.decompressWithOptions(.zstd, compressed, allocator, .{ .max_output_size = 100 * 1024 * 1024, // 100 MB limit});If the decompressed size exceeds the limit, returns error.OutputTooLarge.
Auto-Detecting Format
Section titled “Auto-Detecting Format”Automatically detect the compression format from magic bytes:
fn decompressUnknown(data: []const u8, allocator: std.mem.Allocator) ![]u8 { if (cz.Codec.detect(data)) |codec| { return cz.decompress(codec, data, allocator); } return error.UnknownFormat;}Streaming Compression
Section titled “Streaming Compression”Process large files without loading everything into memory:
const std = @import("std");const cz = @import("compressionz");
pub fn compressFile(allocator: std.mem.Allocator, input_path: []const u8, output_path: []const u8) !void { // Open files const input = try std.fs.cwd().openFile(input_path, .{}); defer input.close();
const output = try std.fs.cwd().createFile(output_path, .{}); defer output.close();
// Create streaming compressor var compressor = try cz.compressor(.gzip, allocator, output.writer(), .{}); defer compressor.deinit();
// Stream data through compressor var buf: [4096]u8 = undefined; while (true) { const n = try input.read(&buf); if (n == 0) break; try compressor.writer().writeAll(buf[0..n]); }
// Finalize try compressor.finish();}Streaming Decompression
Section titled “Streaming Decompression”pub fn decompressFile(allocator: std.mem.Allocator, input_path: []const u8) ![]u8 { const file = try std.fs.cwd().openFile(input_path, .{}); defer file.close();
var decompressor = try cz.decompressor(.gzip, allocator, file.reader()); defer decompressor.deinit();
return decompressor.reader().readAllAlloc(allocator, 100 * 1024 * 1024);}Working with Archives
Section titled “Working with Archives”Extract files from a ZIP archive:
const cz = @import("compressionz");
pub fn extractZip(allocator: std.mem.Allocator, zip_data: []const u8) !void { const files = try cz.archive.extractZip(allocator, zip_data); defer { for (files) |f| { allocator.free(f.name); allocator.free(f.data); } allocator.free(files); }
for (files) |file| { std.debug.print("{s}: {d} bytes\n", .{ file.name, file.data.len }); }}Create a ZIP archive:
const files = [_]cz.archive.FileEntry{ .{ .name = "hello.txt", .data = "Hello, World!" }, .{ .name = "data.json", .data = "{\"key\": \"value\"}" },};
const zip_data = try cz.archive.createZip(allocator, &files);defer allocator.free(zip_data);Error Handling
Section titled “Error Handling”compressionz uses a unified error type:
const result = cz.decompress(.zstd, data, allocator) catch |err| switch (err) { error.InvalidData => { std.debug.print("Corrupted or invalid data\n", .{}); return err; }, error.ChecksumMismatch => { std.debug.print("Data integrity check failed\n", .{}); return err; }, error.OutputTooLarge => { std.debug.print("Decompressed size exceeds limit\n", .{}); return err; }, error.OutOfMemory => { std.debug.print("Allocation failed\n", .{}); return err; }, else => return err,};Complete Example
Section titled “Complete Example”Here’s a complete program that compresses a file with multiple codecs and reports results:
const std = @import("std");const cz = @import("compressionz");
pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator();
// Read input file const args = try std.process.argsAlloc(allocator); defer std.process.argsFree(allocator, args);
if (args.len < 2) { std.debug.print("Usage: {s} <file>\n", .{args[0]}); return; }
const data = try std.fs.cwd().readFileAlloc(allocator, args[1], 100 * 1024 * 1024); defer allocator.free(data);
std.debug.print("Original size: {d} bytes\n\n", .{data.len}); std.debug.print("{s:<12} {s:>12} {s:>10}\n", .{ "Codec", "Size", "Ratio" }); std.debug.print("{s}\n", .{"-" ** 36});
// Test each codec inline for ([_]cz.Codec{ .lz4, .snappy, .zstd, .gzip, .brotli }) |codec| { const compressed = try cz.compress(codec, data, allocator); defer allocator.free(compressed);
const ratio = 100.0 * (1.0 - @as(f64, @floatFromInt(compressed.len)) / @as(f64, @floatFromInt(data.len)));
std.debug.print("{s:<12} {d:>12} {d:>9.1}%\n", .{ codec.name(), compressed.len, ratio, }); }}Next Steps
Section titled “Next Steps”You now know the basics! Continue with:
- Choosing a Codec — Detailed codec comparison
- API Reference — Complete API documentation
- Benchmarks — Performance data
- Advanced Features — Dictionary compression, archives, and more