pub fn init(
pointer: anytype,
comptime allocFn: fn (ptr: @TypeOf(pointer), len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) Error![]u8,
comptime resizeFn: fn (ptr: @TypeOf(pointer), buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) ?usize,
comptime freeFn: fn (ptr: @TypeOf(pointer), buf: []u8, buf_align: u29, ret_addr: usize) void,
) Allocator {
const Ptr = @TypeOf(pointer);
const ptr_info = @typeInfo(Ptr);
assert(ptr_info == .Pointer);
assert(ptr_info.Pointer.size == .One);
const alignment = ptr_info.Pointer.alignment;
const gen = struct {
fn allocImpl(ptr: *anyopaque, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) Error![]u8 {
const self = @ptrCast(Ptr, @alignCast(alignment, ptr));
return @call(.{ .modifier = .always_inline }, allocFn, .{ self, len, ptr_align, len_align, ret_addr });
}
fn resizeImpl(ptr: *anyopaque, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) ?usize {
assert(new_len != 0);
const self = @ptrCast(Ptr, @alignCast(alignment, ptr));
return @call(.{ .modifier = .always_inline }, resizeFn, .{ self, buf, buf_align, new_len, len_align, ret_addr });
}
fn freeImpl(ptr: *anyopaque, buf: []u8, buf_align: u29, ret_addr: usize) void {
const self = @ptrCast(Ptr, @alignCast(alignment, ptr));
@call(.{ .modifier = .always_inline }, freeFn, .{ self, buf, buf_align, ret_addr });
}
const vtable = VTable{
.alloc = allocImpl,
.resize = resizeImpl,
.free = freeImpl,
};
};
return .{
.ptr = pointer,
.vtable = &gen.vtable,
};
}