Files
zig-squashfs/src/meta_rdr.zig
T
Caleb J. Gardner 5c04933520 Resetting. Again.
Getting the basics re-added
2026-06-09 22:23:54 -05:00

113 lines
2.6 KiB
Zig

const std = @import("std");
const Io = std.Io;
const Reader = Io.Reader;
const Writer = Io.Writer;
const Limit = Io.Limit;
const Decomp = @import("decomp.zig");
const MetadataReader = @This();
alloc: std.mem.Allocator,
data: []u8,
decomp: Decomp.Fn,
cur_offset: u64,
block: [8192]u8 = undefined,
interface: Reader = .{
.buffer = &[0]u8{},
.end = 0,
.seek = 0,
.vtable = &.{
.stream = stream,
.discard = discard,
.readVec = readVec,
},
},
pub fn init(alloc: std.mem.Allocator, data: []u8, decomp: Decomp.Fn, offset: u64) MetadataReader {
return .{
.alloc = alloc,
.data = data,
.decomp = decomp,
.cur_offset = offset,
};
}
fn advance(self: *MetadataReader) Reader.Error!void {
self.interface.seek = 0;
errdefer self.interface.end = 0;
const hdr: Header = @intCast(std.mem.readInt(u16, self.data[self.cur_offset..][0..2], .little));
defer self.cur_offset += hdr.size;
const block = self.data[self.cur_offset + 2 ..][0..hdr.size];
if (hdr.uncompressed) {
self.interface.end = hdr.size;
self.interface.buffer = block;
return;
}
const decomp_size = self.decomp(self.alloc, block, &self.block) catch return Reader.Error.ReadFailed;
self.interface.buffer = self.block[0..decomp_size];
self.interface.end = decomp_size;
}
fn stream(r: *Reader, w: *Writer, limit: Limit) Reader.StreamError!usize {
if (r.seek >= r.end) {
const self: *MetadataReader = @fieldParentPtr("interface", r);
try self.advance();
}
if (limit == .nothing) return 0;
const to_write = @min(@intFromEnum(limit), r.end - r.seek);
const wrote = try w.write(r.buffer[r.seek..][0..to_write]);
r.seek += wrote;
return wrote;
}
fn discard(r: *Reader, limit: Limit) Reader.Error!usize {
if (r.seek >= r.end) {
const self: *MetadataReader = @fieldParentPtr("interface", r);
try self.advance();
}
if (limit == .nothing) return 0;
const to_discard = @min(@intFromEnum(limit), r.end - r.seek);
r.seek += to_discard;
return to_discard;
}
fn readVec(r: *Reader, vec: [][]u8) Reader.Error!usize {
if (r.seek >= r.end) {
const self: *MetadataReader = @fieldParentPtr("interface", r);
try self.advance();
}
var wrote: usize = 0;
for (vec) |v| {
const to_cpy = @min(v.len, r.end - r.seek);
@memcpy(v[0..to_cpy], r.buffer[r.seek..][0..to_cpy]);
wrote += to_cpy;
if (r.seek >= r.end) break;
}
return wrote;
}
// Types
const Header = packed struct(u16) {
size: u15,
uncompressed: bool,
};