Files
zig-squashfs/src/decomp/zstd.zig
T
Caleb Gardner ab606bdfa5 Fished decompression (maybe)
Added the necessary skeleton functions to re-add test
2026-05-01 07:05:52 -05:00

74 lines
2.1 KiB
Zig

const std = @import("std");
const Reader = std.Io.Reader;
const zstd = std.compress.zstd;
const Node = std.SinglyLinkedList.Node;
const Decompressor = @import("../util/decompressor.zig");
const Error = Decompressor.Error;
const Self = @This();
const Buffer = struct {
node: Node,
buf: []u8,
};
interface: Decompressor = .{ .decomp_fn = decomp },
alloc: std.mem.Allocator,
block_size: u32,
buffers: std.ArrayList(Buffer),
buffer_queue: std.SinglyLinkedList,
pub fn init(alloc: std.mem.Allocator, block_size: u32) !Self {
return .{
.alloc = alloc,
.block_size = block_size,
.buffers = try .initCapacity(alloc, 5),
};
}
pub fn deinit(self: Self) void {
for (self.buffers) |buf|
self.alloc.free(buf);
self.buffers.deinit(self.alloc);
}
fn decomp(d: ?*const Decompressor, alloc: std.mem.Allocator, in: []u8, out: []u8) Error!usize {
if (d == null) {
const buf = try alloc.alloc(u8, in.len * 2);
defer alloc.free(buf);
return zstdDecomp(buf, in, out);
}
var self: Self = @fieldParentPtr("interface", d.?);
const buf_node = self.buffer_queue.popFirst();
var buf: *Buffer = undefined;
if (buf_node == null) {
const new_buf = try self.buffers.addOne(self.alloc);
new_buf.* = .{ .{}, try self.alloc.alloc(u8, self.block_size + zstd.block_size_max) };
buf = new_buf;
} else {
buf = @fieldParentPtr("node", buf_node);
}
defer self.buffer_queue.prepend(&buf.node);
return zstdDecomp(buf.buf, in, out);
}
inline fn zstdDecomp(buffer: []u8, in: []u8, out: []u8) !usize {
var rdr: Reader = .fixed(in);
var d = zstd.Decompress.init(&rdr, buffer, .{ .window_len = @truncate(in.len) });
return d.reader.readSliceShort(out);
}
// Stateless
pub const stateless_decompressor: Decompressor = .{ .decomp_fn = statelessDecomp };
fn statelessDecomp(_: ?*const Decompressor, alloc: std.mem.Allocator, in: []u8, out: []u8) Error!usize {
const buf = try alloc.alloc(u8, in.len + zstd.block_size_max);
defer alloc.free(buf);
return zstdDecomp(buf, in, out);
}