69 lines
1.5 KiB
Zig
69 lines
1.5 KiB
Zig
|
const coral = @import("./coral.zig");
|
||
|
|
||
|
const std = @import("std");
|
||
|
|
||
|
delete: *const fn (*anyopaque) void,
|
||
|
erased: *anyopaque,
|
||
|
|
||
|
fn Layout(comptime Type: type) type {
|
||
|
return struct {
|
||
|
allocator: std.mem.Allocator,
|
||
|
value: Type,
|
||
|
|
||
|
const TypeLayout = @This();
|
||
|
|
||
|
fn delete(erased: *anyopaque) void {
|
||
|
const layout: *TypeLayout = @ptrCast(@alignCast(erased));
|
||
|
|
||
|
if (@hasDecl(Type, "deinit")) {
|
||
|
layout.value.deinit();
|
||
|
}
|
||
|
|
||
|
layout.allocator.destroy(layout);
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
const Self = @This();
|
||
|
|
||
|
pub fn deinit(self: *Self) void {
|
||
|
self.delete(self.erased);
|
||
|
|
||
|
self.* = undefined;
|
||
|
}
|
||
|
|
||
|
pub fn has(self: Self, comptime Type: type) ?*Type {
|
||
|
const ValueLayout = Layout(Type);
|
||
|
|
||
|
if (self.delete == ValueLayout.delete) {
|
||
|
const layout: *ValueLayout = @ptrCast(@alignCast(self.erased));
|
||
|
|
||
|
return &layout.value;
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
pub fn init(value: anytype) std.mem.Allocator.Error!Self {
|
||
|
return initWithAllocator(coral.heap.allocator, value);
|
||
|
}
|
||
|
|
||
|
pub fn initWithAllocator(allocator: std.mem.Allocator, value: anytype) std.mem.Allocator.Error!Self {
|
||
|
const ValueLayout = Layout(@TypeOf(value));
|
||
|
const value_layout = try allocator.create(ValueLayout);
|
||
|
|
||
|
errdefer {
|
||
|
allocator.destroy(value_layout);
|
||
|
}
|
||
|
|
||
|
value_layout.* = .{
|
||
|
.allocator = allocator,
|
||
|
.value = value,
|
||
|
};
|
||
|
|
||
|
return .{
|
||
|
.erased = @ptrCast(value_layout),
|
||
|
.delete = ValueLayout.delete,
|
||
|
};
|
||
|
}
|