Work on extraction

Created DataExtractor & DataReader
Created Lookup tables
This commit is contained in:
Caleb Gardner
2026-05-30 06:22:26 -05:00
parent 56ad79ba94
commit 578911ba67
5 changed files with 569 additions and 19 deletions
+102
View File
@@ -0,0 +1,102 @@
const std = @import("std");
const Io = std.Io;
const DecompCache = @import("../decomp_cache.zig");
const DataBlock = @import("../inode.zig").DataBlock;
const Extractor = @This();
cache: *DecompCache,
block_size: u32,
start: u64,
size: u64,
blocks: []DataBlock,
frag_data: ?[]u8 = null,
frag_offset: u32 = 0,
pub fn init(cache: *DecompCache, block_size: u32, size: u64, start: u64, blocks: []DataBlock) Extractor {
return .{
.cache = cache,
.block_size = block_size,
.start = start,
.size = size,
.blocks = blocks,
};
}
pub fn addFragment(self: *Extractor, data: []u8, offset: u32) void {
self.frag_data = data;
self.frag_offset = offset;
}
pub fn asyncExtract(self: Extractor, io: Io, fil: Io.File) Error!void {
try fil.writePositionalAll(io, &.{&.{0}}, self.size - 1);
var map = try fil.createMemoryMap(io, .{ .len = self.size, .protection = .{ .write = true } });
defer map.destroy(io);
var group: Io.Group = .init;
defer group.cancel(io);
var ret_err: ?Error = null;
var offset = self.start;
for (0..self.blocks.len) |i| {
group.async(io, blockThread, .{ self, io, map, offset, i, &ret_err });
offset += self.blocks[i].size;
}
if (self.frag_data != null)
group.async(io, fragThread, .{ self, map });
group.await(io) catch |err| return ret_err orelse err;
try map.write(io);
}
fn blockThread(self: Extractor, io: Io, map: Io.File.MemoryMap, read_offset: u64, idx: usize, ret_err: *?Error) error{Canceled}!void {
const write_pos = idx * self.block_size;
const size = if (self.frag_data == null and idx == self.block_size.len - 1)
self.size % self.block_size
else
self.block_size;
const block = self.blocks[idx];
if (block.size == 0) {
@memset(map.memory[write_pos..][0..size], 0);
return;
}
if (block.uncompressed) {
@memcpy(map[write_pos..][0..size], self.cache.map.memory[read_offset..][0..size]);
return;
}
const data = self.cache.get(io, read_offset, block.size, size) catch |err| switch (err) {
error.Canceled => {
io.recancel();
return error.Canceled;
},
else => |e| {
ret_err.* = e;
return error.Canceled;
},
};
defer self.cache.finished(io, read_offset);
if (data.len != size) {
std.debug.print("Size of decompression at {} is {} and should be {}\n", .{ read_offset, data.len, size });
return Error.BadDecompressionSize;
}
@memcpy(map[write_pos..][0..size], data);
}
fn fragThread(self: Extractor, map: Io.File.MemoryMap) error{Canceled}!void {
const write_pos = self.blocks.len * self.block_size;
const size = self.size % self.block_size;
@memcpy(map.memory[write_pos..][0..size], self.frag_data.?[self.frag_offset..][0..size]);
}
// Types
pub const Error = error{BadDecompressionSize} || Io.File.WritePositionalError || Io.File.MemoryMap.CreateError;