Skip to content
zit Artifact [6ca69b19f4]
Login

Artifact [6ca69b19f4]

Artifact 6ca69b19f4c40c25a18823de51395bdf0d2369d762276a4fb39854731f2a8910:


//! Pack-time zstd ENCODER seam (offline `zit pack` only). Links C libzstd
//! (allyourcodebase/zstd) — confined to this module so the core `zit` library
//! stays C-free. DECODE is never here: the runtime read path uses pure-Zig
//! `std.compress.zstd`. The artifact hash is over UNCOMPRESSED bytes (§7.7) and
//! the wire re-emits the §4.1 zlib container, so this storage codec never
//! touches identity or interop. Frames are written WITHOUT a content checksum
//! (zit verifies §7.7 itself; 0.16 std's zstd checksum path is unimplemented).
const std = @import("std");
const c = @cImport(@cInclude("zstd.h"));

pub const Error = error{ ZstdCompress, OutOfMemory };

/// Compress `src` with libzstd at `level` (19 for pack). Simple one-shot API,
/// which emits no content checksum — exactly what std.compress.zstd decodes.
pub fn compress(gpa: std.mem.Allocator, src: []const u8, level: c_int) Error![]u8 {
    const bound = c.ZSTD_compressBound(src.len);
    const dst = try gpa.alloc(u8, bound);
    const n = c.ZSTD_compress(dst.ptr, bound, src.ptr, src.len, level);
    if (c.ZSTD_isError(n) != 0) {
        gpa.free(dst);
        return error.ZstdCompress;
    }
    // Trim the bound-sized buffer to the exact compressed length. resize shrinks
    // in place when it can; otherwise copy into an exact allocation so the caller
    // frees a slice whose length matches its allocation.
    if (gpa.resize(dst, n)) return dst[0..n];
    defer gpa.free(dst);
    const out = try gpa.alloc(u8, n);
    @memcpy(out, dst[0..n]);
    return out;
}

test "zstd §storage: libzstd level-19 encode round-trips through pure-Zig std decode" {
    const gpa = std.testing.allocator;
    // ~256 KiB with long-distance redundancy (a solid-block stand-in).
    const orig = try gpa.alloc(u8, 256 * 1024);
    defer gpa.free(orig);
    for (orig, 0..) |*b, i| b.* = @truncate((i / 61) *% 7 + i);

    const comp = try compress(gpa, orig, 19);
    defer gpa.free(comp);
    try std.testing.expect(comp.len < orig.len); // it actually compressed

    // Decode with pure-Zig std (verify_checksum=false — zit does §7.7 itself).
    var r = std.Io.Reader.fixed(comp);
    const buf = try gpa.alloc(u8, std.compress.zstd.default_window_len + std.compress.zstd.block_size_max);
    defer gpa.free(buf);
    var dec = std.compress.zstd.Decompress.init(&r, buf, .{ .verify_checksum = false });
    const out = try dec.reader.allocRemaining(gpa, .unlimited);
    defer gpa.free(out);
    try std.testing.expectEqualSlices(u8, orig, out);
}

test "zstd §storage: encode is deterministic (same input, same bytes) for pack idempotence" {
    const gpa = std.testing.allocator;
    const src = "the quick brown fox " ** 4096;
    const a = try compress(gpa, src, 19);
    defer gpa.free(a);
    const b = try compress(gpa, src, 19);
    defer gpa.free(b);
    try std.testing.expectEqualSlices(u8, a, b);
}