Further work on making everything work
Directory table reading Finished MetadataReader
This commit is contained in:
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user