Further work on making everything work

Directory table reading
Finished MetadataReader
This commit is contained in:
Caleb J. Gardner
2026-08-29 06:40:34 -05:00
parent e0b697dd0b
commit c5d75d3839
8 changed files with 545 additions and 63 deletions
+101
View File
@@ -1,8 +1,109 @@
const std = @import("std");
const Io = std.Io;
const util = @import("util.zig");
const Decomp = @import("../decomp.zig");
const MetadataReader = @This();
alloc: std.mem.Allocator,
data: []u8,
decomp: Decomp.Fn,
decomp_block: [8192]u8 = undefined,
interface: Io.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) MetadataReader {
return .{
.alloc = alloc,
.data = data,
.decomp = decomp,
};
}
fn advance(self: *MetadataReader) Io.Reader.Error!void {
self.interface.seek = 0;
errdefer self.interface.end = 0;
const hdr = util.readValue(Header, self.data[0..2]);
const block = self.data[2..][0..hdr.size];
self.data = self.data[hdr.size + 2 ..];
if (hdr.uncompressed) {
self.interface.end = hdr.size;
self.interface.buffer = block;
return;
}
self.interface.end = self.decomp(self.alloc, block, &self.decomp_block) catch return error.ReadFailed;
self.interface.buffer = self.decomp_block[0..self.interface.end];
}
fn stream(rdr: *Io.Reader, wrt: *Io.Writer, limit: Io.Limit) Io.Reader.StreamError!usize {
if (rdr.seek >= rdr.end) {
var meta: *MetadataReader = @fieldParentPtr("interface", rdr);
try meta.advance();
}
if (limit == .nothing) return 0;
const size = @min(@intFromEnum(limit), rdr.end - rdr.seek);
const wrote = try wrt.write(rdr.buffer[rdr.seek..][0..size]);
rdr.seek += wrote;
return wrote;
}
fn discard(rdr: *Io.Reader, limit: Io.Limit) Io.Reader.Error!usize {
if (rdr.seek >= rdr.end) {
var meta: *MetadataReader = @fieldParentPtr("interface", rdr);
try meta.advance();
}
if (limit == .nothing) return 0;
const size = @min(@intFromEnum(limit), rdr.end - rdr.seek);
rdr.seek += size;
return size;
}
fn readVec(rdr: *Io.Reader, vec: [][]u8) Io.Reader.Error!usize {
if (rdr.seek >= rdr.end) {
var meta: *MetadataReader = @fieldParentPtr("interface", rdr);
try meta.advance();
}
var wrote: usize = 0;
for (vec) |s| {
const size = @min(rdr.end - rdr.seek, s.len);
@memcpy(s[0..size], rdr.buffer[rdr.seek..][0..size]);
wrote += size;
rdr.seek += size;
if (rdr.seek >= rdr.end) break;
}
return wrote;
}
// Types
const Header = packed struct(u16) {
size: u15,
uncompressed: bool,
};