const std = @import("std");
const mem = std.mem;

extern fn __haku2_alloc(size: usize, alignment: usize) ?[*]u8;
extern fn __haku2_realloc(ptr: [*]u8, size: usize, alignment: usize, new_size: usize) ?[*]u8;
extern fn __haku2_dealloc(ptr: [*]u8, size: usize, alignment: usize) void;

fn hostAlloc(_: *anyopaque, len: usize, alignment: mem.Alignment, _: usize) ?[*]u8 {
    return __haku2_alloc(len, alignment.toByteUnits());
}

fn hostResize(_: *anyopaque, memory: []u8, alignment: mem.Alignment, new_len: usize, _: usize) bool {
    // Rust doesn't have an API for resizing memory in place.
    // Callers will have to call remap instead.
    _ = memory;
    _ = alignment;
    _ = new_len;
    return false;
}

fn hostRemap(_: *anyopaque, memory: []u8, alignment: mem.Alignment, new_len: usize, _: usize) ?[*]u8 {
    return __haku2_realloc(memory.ptr, memory.len, alignment.toByteUnits(), new_len);
}

fn hostFree(_: *anyopaque, memory: []u8, alignment: mem.Alignment, _: usize) void {
    __haku2_dealloc(memory.ptr, memory.len, alignment.toByteUnits());
}

pub const hostAllocator = mem.Allocator{
    .ptr = undefined,
    .vtable = &mem.Allocator.VTable{
        .alloc = hostAlloc,
        .resize = hostResize,
        .remap = hostRemap,
        .free = hostFree,
    },
};
