Okay, Ziguanas, is this really the best we can do for "interfaces" in #Zig?
I can't think of another way to do it.
```zig
// The interface
pub const BusDevice = struct {
ptr: *anyopaque,
min_address: u16,
max_address: u16,
readFn: *const fn (ptr: *anyopaque, addr: u16) u8,
writeFn: *const fn (ptr: *anyopaque, addr: u16, value: u8) void,
fn read(self: BusDevice, addr: u16) u8 {
return self.readFn(self.ptr, addr);
}
fn write(self: BusDevice, addr: u16, value: u8) void {
self.writeFn(self.ptr, addr, value);
}
};
// The implementation
pub const Memory = struct {
min_address: u16,
max_address: u16,
physical_memory: []u8,
pub fn new(allocator: Allocator, min_address: u16, max_address: u16) !Memory {
const phys_mem = try allocator.alloc(u8, max_address - min_address);
for (phys_mem) |*address| {
address.* = 0;
}
return Memory{
.min_address = min_address,
.max_address = max_address,
.physical_memory = phys_mem,
};
}
pub fn write(self: *Memory, address: u16, value: u8) void {
self.physical_memory[address] = value;
}
pub fn read(self: *Memory, address: u16) u8 {
return self.physical_memory[address - self.min_address];
}
pub fn busDevice(self: *Memory) BusDevice {
return BusDevice{ .ptr = self, .min_address = self.min_address, .max_address = self.max_address, .readFn = self.read, .writeFn = self.write };
}
};
```