zig-std 0.1.1

Bindings to Zig `std`, with optional Rust `std` features
Documentation
const util = @import("util.zig");
const ReprCSlice = util.ReprCSlice;
const std_mem = @import("std").mem;

pub const Alignment = enum(u8) {
	a1 = 0,
	a2 = 1,
	a4 = 2,
	a8 = 3,
	a16 = 4,
	a32 = 5,
	a64 = 6,
	_,

	inline fn from_std(alignment: std_mem.Alignment) @This() {
		return switch (alignment) {
			.@"1" => .a1,
			.@"2" => .a2,
			.@"4" => .a4,
			.@"8" => .a8,
			.@"16" => .a16,
			.@"32" => .a32,
			.@"64" => .a64,
			_ => unreachable
		};
	}

	inline fn to_std(self: @This()) std_mem.Alignment {
		return switch (self) {
			.a1 => .@"1",
			.a2 => .@"2",
			.a4 => .@"4",
			.a8 => .@"8",
			.a16 => .@"16",
			.a32 => .@"32",
			.a64 => .@"64",
			_ => unreachable
		};
	}
};

pub const Allocator = extern struct {
	ptr: *anyopaque,
	vtable: VTable,

	inline fn from_std(allocator: std_mem.Allocator) @This() {
		return .{
			.ptr = allocator.ptr,
			.vtable = VTable.from_std_ptr(allocator.vtable)
		};
	}

	inline fn to_std(self: @This()) std_mem.Allocator {
		return .{
			.ptr = self.ptr,
			.vtable = self.vtable.to_std_ptr()
		};
	}
};

pub const VTable = extern struct {
	vtable_zig: *const anyopaque,

	alloc_c: *const fn (
		vtable_zig: *const anyopaque,
		allocator: *anyopaque,
		len: usize,
		alignment: Alignment,
		ret_addr: usize
	) callconv(.c) ReprCSlice(u8),
	resize_c: *const fn (
		vtable_zig: *const anyopaque,
		allocator: *anyopaque,
		memory: ReprCSlice(u8),
		alignment: Alignment,
		new_len: usize,
		ret_addr: usize
	) callconv(.c) bool,
	remap_c: *const fn (
		vtable_zig: *const anyopaque,
		allocator: *anyopaque,
		memory: ReprCSlice(u8),
		alignment: Alignment,
		new_len: usize,
		ret_addr: usize
	) callconv(.c) ReprCSlice(u8),
	free_c: *const fn (
		vtable_zig: *const anyopaque,
		allocator: *anyopaque,
		memory: ReprCSlice(u8),
		alignment: Alignment,
		ret_addr: usize
	) callconv(.c) void,

	inline fn from_std_ptr(vtable: *const std_mem.Allocator.VTable) @This() {
		return .{
			.vtable_zig = vtable,
			.alloc_c = alloc_c,
			.resize_c = resize_c,
			.remap_c = remap_c,
			.free_c = free_c
		};
	}

	inline fn to_std_ptr(self: @This()) *const std_mem.Allocator.VTable {
		return @ptrCast(@alignCast(self.vtable_zig));
	}
};

fn alloc_c(
	vtable_zig: *const anyopaque,
	allocator: *anyopaque,
	len: usize,
	alignment: Alignment,
	ret_addr: usize
) callconv(.c) ReprCSlice(u8) {
	const vtable: *const std_mem.Allocator.VTable = @ptrCast(@alignCast(vtable_zig));
	const ptr = vtable.alloc(allocator, len, alignment.to_std(), ret_addr);
	return ReprCSlice(u8).from_ptr_len(ptr, len);
}

fn resize_c(
	vtable_zig: *const anyopaque,
	allocator: *anyopaque,
	memory: ReprCSlice(u8),
	alignment: Alignment,
	new_len: usize,
	ret_addr: usize
) callconv(.c) bool {
	const vtable: *const std_mem.Allocator.VTable = @ptrCast(@alignCast(vtable_zig));
	return vtable.resize(allocator, memory.to_slice().?, alignment.to_std(), new_len, ret_addr);
}

fn remap_c(
	vtable_zig: *const anyopaque,
	allocator: *anyopaque,
	memory: ReprCSlice(u8),
	alignment: Alignment,
	new_len: usize,
	ret_addr: usize
) callconv(.c) ReprCSlice(u8) {
	const vtable: *const std_mem.Allocator.VTable = @ptrCast(@alignCast(vtable_zig));
	const slice = vtable.remap(allocator, memory.to_slice().?, alignment.to_std(), new_len, ret_addr);
	return ReprCSlice(u8).from_ptr_len(slice, new_len);
}

fn free_c(
	vtable_zig: *const anyopaque,
	allocator: *anyopaque,
	memory: ReprCSlice(u8),
	alignment: Alignment,
	ret_addr: usize
) callconv(.c) void {
	const vtable: *const std_mem.Allocator.VTable = @ptrCast(@alignCast(vtable_zig));
	vtable.free(allocator, memory.to_slice().?, alignment.to_std(), ret_addr);
}

comptime {
	const assert = @import("std").debug.assert;

	// smoke tests
	_ = Alignment.from_std(Alignment.a8.to_std());
	const allocator = @import("std").heap.page_allocator;
	_ = Allocator.from_std(allocator).to_std();
	_ = VTable.from_std_ptr(allocator.vtable).to_std_ptr();

	// size/align assertions
	assert(@sizeOf(Alignment) == 1);
	assert(@alignOf(Alignment) == 1);
	assert(@sizeOf(Allocator) == 6 * @sizeOf(usize));
	assert(@alignOf(Allocator) == @alignOf(usize));
	assert(@sizeOf(VTable) == 5 * @sizeOf(usize));
	assert(@alignOf(VTable) == @alignOf(usize));
}