I wanted to know whether it is better to use a VFTable (like allocators) or tagged union in this case.
pub const MemoryAccessorType = enum {
DirectMemoryAccessor,
};
pub const MemoryAccessor = union(MemoryAccessorType) {
DirectMemoryAccessor: DirectMemoryAccessor,
const Self = @This();
pub fn read(this: Self, T: anytype, address: *anyopaque) if(@typeInfo(T) == .Optional) T else ?T {
return switch (this) {
.DirectMemoryAccessor => |dma| dma.read(T, address),
};
}
pub fn readSlice(this: Self, T: anytype, buffer: []T, address: *anyopaque) bool {
return switch (this) {
.DirectMemoryAccessor => |dma| dma.readSlice(T, buffer, address),
};
}
};
pub const DirectMemoryAccessor = struct {
processHandle: win32.HANDLE,
const Self = @This();
pub fn read(this: Self, T: anytype, address: *anyopaque) if(@typeInfo(T) == .Optional) T else ?T {
var buf: T = undefined;
var bytesRead: u32 = undefined;
if(NtReadVirtualMemory(this.processHandle, address, @ptrCast(&buf), @sizeOf(T), &bytesRead) != win.NTSTATUS.SUCCESS or bytesRead != @sizeOf(T))
return null;
return buf;
}
pub fn readSlice(this: Self, T: anytype, buffer: []T, address: *anyopaque) bool {
var bytesRead: u32 = undefined;
if(NtReadVirtualMemory(this.processHandle, address, @ptrCast(buffer.ptr), @truncate(buffer.len*@sizeOf(T)), &bytesRead) != win.NTSTATUS.SUCCESS or bytesRead != buffer.len*@sizeOf(T))
return true;
return false;
}
};
I'll add more Memory Accessors in the future but I still want to be able to call different accessors using the same MemoryAccessor type.