parent
07905d0b09
commit
37af42daaa
@ -0,0 +1,89 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const utils = @import("utils.zig");
|
||||||
|
|
||||||
|
/// stores a single object of type T for each T added
|
||||||
|
pub const TypeStore = struct {
|
||||||
|
map: std.AutoHashMap(u32, []u8),
|
||||||
|
allocator: *std.mem.Allocator,
|
||||||
|
|
||||||
|
pub fn init(allocator: *std.mem.Allocator) TypeStore {
|
||||||
|
return TypeStore{
|
||||||
|
.map = std.AutoHashMap(u32, []u8).init(allocator),
|
||||||
|
.allocator = allocator,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: TypeStore) void {
|
||||||
|
var iter = self.map.iterator();
|
||||||
|
while (iter.next()) |kv| {
|
||||||
|
self.allocator.free(kv.value);
|
||||||
|
}
|
||||||
|
self.map.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// adds instance, returning a pointer to the item as it lives in the store
|
||||||
|
pub fn add(self: *TypeStore, instance: var) *@TypeOf(instance) {
|
||||||
|
var bytes = self.allocator.alloc(u8, @sizeOf(@TypeOf(instance))) catch unreachable;
|
||||||
|
var ptr = @ptrCast(*@TypeOf(instance), @alignCast(@alignOf(@TypeOf(instance)), bytes));
|
||||||
|
ptr.* = instance;
|
||||||
|
_ = self.map.put(utils.typeId(@TypeOf(instance)), bytes) catch unreachable;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(self: *TypeStore, comptime T: type) *T {
|
||||||
|
if (self.map.getValue(utils.typeId(T))) |bytes| {
|
||||||
|
return @ptrCast(*T, @alignCast(@alignOf(T), bytes));
|
||||||
|
}
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getConst(self: *TypeStore, comptime T: type) T {
|
||||||
|
return self.get(T).*;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getOrAdd(self: *TypeStore, comptime T: type) *T {
|
||||||
|
if (self.has(T)) return self.get(T);
|
||||||
|
var instance = std.mem.zeroes(T);
|
||||||
|
return self.add(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(self: *TypeStore, comptime T: type) void {
|
||||||
|
if (self.map.getValue(utils.typeId(T))) |bytes| {
|
||||||
|
self.allocator.free(bytes);
|
||||||
|
_ = self.map.remove(utils.typeId(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has(self: *TypeStore, comptime T: type) bool {
|
||||||
|
return self.map.contains(utils.typeId(T));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test "TypeStore" {
|
||||||
|
const Vector = struct { x: f32 = 0, y: f32 = 0, z: f32 = 0};
|
||||||
|
|
||||||
|
var store = TypeStore.init(std.testing.allocator);
|
||||||
|
defer store.deinit();
|
||||||
|
|
||||||
|
var orig = Vector{.x = 5, .y = 6, .z = 8};
|
||||||
|
var inserted = store.add(orig);
|
||||||
|
std.testing.expect(store.has(Vector));
|
||||||
|
std.testing.expectEqual(inserted.*, Vector{.x = 5, .y = 6, .z = 8});
|
||||||
|
|
||||||
|
var v = store.get(Vector);
|
||||||
|
std.testing.expectEqual(v.*, Vector{.x = 5, .y = 6, .z = 8});
|
||||||
|
v.*.x = 666;
|
||||||
|
|
||||||
|
var v2 = store.get(Vector);
|
||||||
|
std.testing.expectEqual(v2.*, Vector{.x = 666, .y = 6, .z = 8});
|
||||||
|
|
||||||
|
store.remove(Vector);
|
||||||
|
std.testing.expect(!store.has(Vector));
|
||||||
|
|
||||||
|
var v3 = store.getOrAdd(u32);
|
||||||
|
std.testing.expectEqual(v3.*, 0);
|
||||||
|
v3.* = 777;
|
||||||
|
|
||||||
|
var v4 = store.get(u32);
|
||||||
|
std.testing.expectEqual(v3.*, 777);
|
||||||
|
}
|
Loading…
Reference in new issue