Backlog/lib/packer/src/PackedFileEntry.zig

138 lines
4.5 KiB
Zig

const std = @import("std");
const p2 = @import("p2");
const constants = @import("constants.zig");
const PackedFileEntry = @This();
fileOffset: u64,
fileLen: u64,
fileNameLen: u32,
typeLen: u32,
fileName: [128]u8 = std.mem.zeroes([128]u8), // 128 bytes, zero-init because zeros are written to file for padding
typeName: [32]u8 = std.mem.zeroes([32]u8), // 32 bytes, zero-init because zeros are written to file for padding
//
pub fn init(typeName: []const u8, fileName: []const u8, fileOffset: u64, fileLen: u64) !@This() {
var self = @This(){
.fileLen = fileLen,
.fileOffset = fileOffset,
.fileNameLen = @intCast(fileName.len),
.typeLen = @intCast(typeName.len),
};
_ = try std.fmt.bufPrint(&self.fileName, "{s}", .{fileName});
_ = try std.fmt.bufPrint(&self.typeName, "{s}", .{typeName});
return self;
}
// todo make this a comptime, when i land and I am able to
// find out how comptime allocator interface looks.
pub fn calculateHeaderLen() usize {
// TODO
return 184;
}
pub fn loadFromReader(self: *@This(), reader: *std.Io.Reader) !void {
var bytesRead: usize = 0;
bytesRead += try reader.readSliceShort(p2.u64_to_slice(&self.fileOffset));
bytesRead += try reader.readSliceShort(p2.u64_to_slice(&self.fileLen));
bytesRead += try reader.readSliceShort(p2.u32_to_slice(&self.fileNameLen));
bytesRead += try reader.readSliceShort(p2.u32_to_slice(&self.typeLen));
bytesRead += try reader.readSliceShort(&self.fileName);
bytesRead += try reader.readSliceShort(&self.typeName);
std.debug.assert(bytesRead == calculateHeaderLen());
std.debug.print("header deserialized {s} type: {s} fileOffset:{d} \n", .{ self.getFileName(), self.getTypeName(), self.fileOffset });
}
// returns bytes written, not a true serialize function,
// writes out it's contents as it's meant to be read back to the writer.
pub fn writeHeader(self: @This(), writer: *std.Io.Writer, elementsCount: u32) !usize {
_ = elementsCount;
var bytesWritten: usize = 0;
bytesWritten += try writer.write(&@as([8]u8, @bitCast(self.fileOffset)));
bytesWritten += try writer.write(&@as([8]u8, @bitCast(self.fileLen)));
bytesWritten += try writer.write(&@as([4]u8, @bitCast(self.fileNameLen)));
bytesWritten += try writer.write(&@as([4]u8, @bitCast(self.typeLen)));
bytesWritten += try writer.write(&self.fileName);
bytesWritten += try writer.write(&self.typeName);
std.debug.assert(bytesWritten % 8 == 0);
std.debug.print("{s} serialized {d} bytes\n", .{ self.getFileName(), bytesWritten });
return bytesWritten;
}
pub fn getTypeName(self: *const @This()) []const u8 {
var slice: []const u8 = undefined;
slice.ptr = @ptrCast(&self.typeName);
slice.len = self.typeLen;
return slice;
}
pub fn getFileName(self: *const @This()) []const u8 {
var slice: []const u8 = undefined;
slice.ptr = @ptrCast(&self.fileName);
slice.len = self.fileNameLen;
return slice;
}
pub const ReaderIterator = struct {
totalCount: u32,
readCount: u32 = 0,
bytesRead: u64,
finished: bool = false,
// this iterator becomes invalidated if anythign else modifies
// the iterator is finished
pub fn init(reader: *std.Io.Reader) !@This() {
var bytesRead: usize = 0;
// read and verify magic
var magic: [4]u8 align(4) = undefined;
try p2.assert(try reader.readSliceShort(&magic) == 4);
try p2.assert(p2.arrayTo_u32(magic) == constants.PackerMagic);
bytesRead += 4;
// read the number of header entries
var entriesCount_read: [4]u8 align(4) = undefined;
try p2.assert(try reader.readSliceShort(&entriesCount_read) == 4);
const entriesCount = p2.arrayTo_u32(entriesCount_read);
std.debug.print("entriesCount = {d}\n", .{entriesCount});
bytesRead += 4;
return .{
.bytesRead = bytesRead,
.totalCount = entriesCount,
};
}
pub fn next(self: *@This(), reader: *std.Io.Reader) !?PackedFileEntry {
std.debug.print("readCount = {d}\n", .{self.readCount});
if (self.readCount == self.totalCount)
return null;
var newEntry: PackedFileEntry = undefined;
try newEntry.loadFromReader(reader);
self.bytesRead += PackedFileEntry.calculateHeaderLen();
self.readCount += 1;
return newEntry;
}
};