Skip to content

Decompression API

This page documents all decompression-related functions in compressionz.

Decompress data using the specified codec with default options.

pub fn decompress(
codec: Codec,
input: []const u8,
allocator: std.mem.Allocator,
) Error![]u8
ParameterTypeDescription
codecCodecCompression algorithm used
input[]const u8Compressed data
allocatorstd.mem.AllocatorAllocator for output buffer
  • []u8 — Decompressed data. Caller owns and must free with allocator.
  • Error — On failure (see Error Handling)
const cz = @import("compressionz");
const decompressed = try cz.decompress(.zstd, compressed, allocator);
defer allocator.free(decompressed);

Decompress data with custom options.

pub fn decompressWithOptions(
codec: Codec,
input: []const u8,
allocator: std.mem.Allocator,
options: DecompressOptions,
) Error![]u8
ParameterTypeDescription
codecCodecCompression algorithm
input[]const u8Compressed data
allocatorstd.mem.AllocatorAllocator for output
optionsDecompressOptionsDecompression options
pub const DecompressOptions = struct {
/// Expected output size (required for lz4_raw)
expected_size: ?usize = null,
/// Maximum output size (decompression bomb protection)
max_output_size: ?usize = null,
/// Dictionary (must match compression)
dictionary: ?[]const u8 = null,
};
// With size limit (security)
const safe = try cz.decompressWithOptions(.zstd, data, allocator, .{
.max_output_size = 100 * 1024 * 1024, // 100 MB limit
});
// LZ4 raw (requires expected_size)
const lz4_raw = try cz.decompressWithOptions(.lz4_raw, data, allocator, .{
.expected_size = original_len,
});
// With dictionary
const dict_decompressed = try cz.decompressWithOptions(.zstd, data, allocator, .{
.dictionary = my_dictionary,
});

Decompress into a pre-allocated buffer (zero-copy).

pub fn decompressInto(
codec: Codec,
input: []const u8,
output: []u8,
) Error![]u8
ParameterTypeDescription
codecCodecCompression algorithm
input[]const u8Compressed data
output[]u8Pre-allocated output buffer
  • []u8 — Slice of output containing decompressed data
  • error.OutputTooSmall — If buffer is too small

Only available for: .lz4, .lz4_raw, .snappy

var buffer: [1024 * 1024]u8 = undefined; // 1 MB buffer
const decompressed = try cz.decompressInto(.lz4, compressed, &buffer);
// decompressed is a slice of buffer

LZ4 raw block format does not include the original size. You must provide expected_size:

// Compression
const compressed = try cz.compress(.lz4_raw, data, allocator);
const original_len = data.len; // Save this!
// Decompression - REQUIRES expected_size
const decompressed = try cz.decompressWithOptions(.lz4_raw, compressed, allocator, .{
.expected_size = original_len, // Required!
});
// This will fail with error.InvalidData:
// const bad = try cz.decompress(.lz4_raw, compressed, allocator);
if (codec.requiresExpectedSize()) {
return cz.decompressWithOptions(codec, data, allocator, .{
.expected_size = known_size,
});
} else {
return cz.decompress(codec, data, allocator);
}

Malicious compressed data can expand to enormous sizes (e.g., a 1 KB “zip bomb” expanding to 1 TB). Use max_output_size to protect against this:

const safe = cz.decompressWithOptions(.gzip, untrusted_data, allocator, .{
.max_output_size = 100 * 1024 * 1024, // 100 MB limit
}) catch |err| switch (err) {
error.OutputTooLarge => {
// Data would exceed limit
return error.SuspiciousInput;
},
else => return err,
};
ContextRecommended Limit
User uploads10-100 MB
API requests1-10 MB
Config files1 MB
Internal dataBased on expected size

const cz = @import("compressionz");
// LZ4 frame
const data = try cz.lz4.frame.decompress(compressed, allocator);
// LZ4 frame with limit
const limited = try cz.lz4.frame.decompressWithLimit(compressed, allocator, max_size);
// LZ4 raw block
const block = try cz.lz4.block.decompressWithSize(compressed, expected_size, allocator);
const data = try cz.snappy.decompress(compressed, allocator);
const limited = try cz.snappy.decompressWithLimit(compressed, allocator, max_size);
const data = try cz.zstd.decompress(compressed, allocator);
// With dictionary
const dict_data = try cz.zstd.decompressWithDict(compressed, allocator, max_size, dictionary);
const data = try cz.gzip.decompress(compressed, allocator);
const limited = try cz.gzip.decompressWithLimit(compressed, allocator, max_size);
const data = try cz.brotli.decompress(compressed, allocator);
const limited = try cz.brotli.decompressWithLimit(compressed, allocator, max_size);

Automatically detect and decompress:

pub fn decompressAuto(data: []const u8, allocator: std.mem.Allocator) ![]u8 {
const codec = cz.Codec.detect(data) orelse return error.UnknownFormat;
return cz.decompress(codec, data, allocator);
}

See Codec Detection for details.


Common decompression errors:

const result = cz.decompress(.zstd, data, allocator) catch |err| switch (err) {
error.InvalidData => {
// Corrupted or not actually compressed with this codec
},
error.ChecksumMismatch => {
// Data integrity check failed
},
error.OutputTooLarge => {
// Exceeds max_output_size limit
},
error.UnexpectedEof => {
// Compressed data truncated
},
error.OutOfMemory => {
// Allocation failed
},
else => return err,
};

See Error Handling for complete error reference.