ona/src/coral/Box.zig

69 lines
1.5 KiB
Zig
Raw Normal View History

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