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, }; }