Wasmtime bindings for Zig
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
7.0 KiB

const Store = @import("./store.zig").Store;
const Func = @import("./func.zig").Func;
const FuncType = @import("./func.zig").FuncType;
const Memory = @import("./memory.zig").Memory;
const MemoryType = @import("./memory.zig").MemoryType;
/// Representation of a table in Wasmtime.
pub const Table = extern struct {
store_id: u64,
index: usize,
};
/// Representation of a global in Wasmtime.
pub const Global = extern struct {
store_id: u64,
index: usize,
};
pub const ExternKind = enum(u8) {
func = 0,
global = 1,
table = 2,
memory = 3,
};
/// Container for different kinds of extern items.
///
/// Note that this structure may contain an owned value, namely `Module`,
/// depending on the context in which this is used. APIs which consume an
/// `Extern` do not take ownership, but APIs that return `Extern` require that
/// `deinit` is called to deallocate the value.
pub const Extern = extern struct {
kind: ExternKind,
of: extern union {
func: Func,
global: Global,
table: Table,
memory: Memory,
},
pub fn deinit(self: *Extern) void {
wasmtime_extern_delete(self);
}
pub fn getType(self: *const Extern, context: *const Store.Context) *ExternType {
return wasmtime_extern_type(context, self);
}
pub fn from(value: anytype) Extern {
return switch (@TypeOf(value)) {
Extern => value, // Convenience no-op for use with generic functions.
Func => .{ .kind = .func, .of = .{ .func = value } },
Global => .{ .kind = .global, .of = .{ .global = value } },
Table => .{ .kind = .table, .of = .{ .table = value } },
Memory => .{ .kind = .memory, .of = .{ .memory = value } },
else => @compileError("Expected one of 'Extern', 'Func', 'Global', 'Table' or 'Memory', but found '" ++ @typeName(@TypeOf(value)) ++ "'"),
};
}
pub fn as(self: Extern, comptime T: type) !T {
return switch (T) {
Extern => self, // Convenience no-op for use with generic functions.
Func => if (self.kind == .func) self.of.func else error.IncorrectType,
Global => if (self.kind == .global) self.of.global else error.IncorrectType,
Table => if (self.kind == .table) self.of.table else error.IncorrectType,
Memory => if (self.kind == .memory) self.of.memory else error.IncorrectType,
else => @compileError("Expected one of 'Extern', 'Func', 'Global', 'Table' or 'Memory', but found '" ++ @typeName(T) ++ "'"),
};
}
extern "c" fn wasmtime_extern_delete(*Extern) void;
extern "c" fn wasmtime_extern_type(*const Store.Context, *const Extern) *ExternType;
};
test Extern {
const std = @import("std");
const expect = std.testing.expect;
const wasm = @import("./main.zig");
const wat_bytes =
\\(module
\\ (func (export "some_function"))
\\ (global (export "some_global") (mut i32) (i32.const 0))
\\ (memory (export "some_memory") 1)
\\)
;
// If an error *does* occur, settings up Diagnostics with debug_print will
// make sure that the error will actually be visible in the test log.
var diag = try wasm.Diagnostics.init(std.testing.allocator, true);
defer diag.deinit();
var engine = try wasm.Engine.initDefault();
defer engine.deinit();
var module = try wasm.Module.initFromWat(engine, wat_bytes, diag);
defer module.deinit();
var store = wasm.Store.init(engine);
defer store.deinit();
var context = store.getContext();
var instance = try wasm.Instance.init(context, module, &.{}, null);
const some_function = try instance.getByIndex(context, 0, wasm.Func);
const some_global = try instance.getByIndex(context, 1, wasm.Global);
const some_memory = try instance.getByIndex(context, 2, wasm.Memory);
try expect(std.mem.eql(u8, some_function.name, "some_function"));
try expect(std.mem.eql(u8, some_global.name, "some_global"));
try expect(std.mem.eql(u8, some_memory.name, "some_memory"));
try expect(instance.getByIndex(context, 3, wasm.Func) == error.ExportNotFound);
try expect(instance.get(context, "no_such_func", wasm.Func) == error.ExportNotFound);
try expect(instance.get(context, "some_function", wasm.Global) == error.IncorrectType);
}
pub const ExternType = opaque {
pub fn copy(self: *const ExternType) *ExternType {
return wasm_externtype_copy(self);
}
pub fn deinit(self: *ExternType) void {
wasm_externtype_delete(self);
}
pub fn getKind(self: *const ExternType) ExternKind {
return wasm_externtype_kind(self);
}
pub fn from(value: anytype) @TypeOf(value) {
return switch (@TypeOf(value)) {
*ExternType => value, // Convenience no-op for use with generic functions.
*FuncType => wasm_functype_as_externtype(value),
*MemoryType => wasm_memorytype_as_externtype(value),
else => @compileError("Expected one of '*ExternType', '*FuncType' or '*MemoryType', but found '" ++ @typeName(@TypeOf(value)) ++ "'"),
};
}
pub fn as(self: *ExternType, comptime T: type) !T {
return switch (T) {
*ExternType => self, // Convenience no-op for use with generic functions.
*FuncType => wasm_externtype_as_functype(self) orelse error.IncorrectType,
*MemoryType => wasm_externtype_as_memorytype(self) orelse error.IncorrectType,
else => @compileError("Expected one of '*ExternType', '*FuncType' or '*MemoryType', but found '" ++ @typeName(T) ++ "'"),
};
}
extern "c" fn wasm_externtype_copy(*const ExternType) *ExternType;
extern "c" fn wasm_externtype_delete(*ExternType) void;
extern "c" fn wasm_externtype_kind(*const ExternType) ExternKind;
extern "c" fn wasm_functype_as_externtype(*FuncType) *ExternType;
// extern "c" fn wasm_tabletype_as_externtype(*TableType) *ExternType;
// extern "c" fn wasm_globaltype_as_externtype(*GlobalType) *ExternType;
extern "c" fn wasm_memorytype_as_externtype(*MemoryType) *ExternType;
extern "c" fn wasm_functype_as_externtype_const(*const FuncType) *const ExternType;
// extern "c" fn wasm_tabletype_as_externtype_const(*const TableType) *const ExternType;
// extern "c" fn wasm_globaltype_as_externtype_const(*const GlobalType) *const ExternType;
extern "c" fn wasm_memorytype_as_externtype_const(*const MemoryType) *const ExternType;
extern "c" fn wasm_externtype_as_functype(*ExternType) ?*FuncType;
// extern "c" fn wasm_externtype_as_tabletype(*ExternType) ?*TableType;
// extern "c" fn wasm_externtype_as_globaltype(*ExternType) ?*GlobalType;
extern "c" fn wasm_externtype_as_memorytype(*ExternType) ?*MemoryType;
extern "c" fn wasm_externtype_as_functype_const(*const ExternType) ?*const FuncType;
// extern "c" fn wasm_externtype_as_tabletype_const(*const ExternType) ?*const TableType;
// extern "c" fn wasm_externtype_as_globaltype_const(*const ExternType) ?*const GlobalType;
extern "c" fn wasm_externtype_as_memorytype_const(*const ExternType) ?*const MemoryType;
};