#ifndef WASMTIME_LINKER_HH
#define WASMTIME_LINKER_HH
#include <wasmtime/engine.hh>
#include <wasmtime/error.hh>
#include <wasmtime/extern.hh>
#include <wasmtime/helpers.hh>
#include <wasmtime/instance.hh>
#include <wasmtime/linker.h>
#include <wasmtime/store.hh>
#include <wasmtime/trap.hh>
namespace wasmtime {
class Linker {
WASMTIME_OWN_WRAPPER(Linker, wasmtime_linker);
explicit Linker(Engine &engine) : ptr(wasmtime_linker_new(engine.capi())) {}
void allow_shadowing(bool allow) {
wasmtime_linker_allow_shadowing(ptr.get(), allow);
}
Result<std::monostate> define(Store::Context cx, std::string_view module,
std::string_view name, const Extern &item) {
wasmtime_extern_t raw;
detail::cvt_extern(item, raw);
auto *error =
wasmtime_linker_define(ptr.get(), cx.ptr, module.data(), module.size(),
name.data(), name.size(), &raw);
if (error != nullptr) {
return Error(error);
}
return std::monostate();
}
#ifdef WASMTIME_FEATURE_WASI
Result<std::monostate> define_wasi() {
auto *error = wasmtime_linker_define_wasi(ptr.get());
if (error != nullptr) {
return Error(error);
}
return std::monostate();
}
#endif
Result<std::monostate>
define_instance(Store::Context cx, std::string_view name, Instance instance) {
auto *error = wasmtime_linker_define_instance(
ptr.get(), cx.ptr, name.data(), name.size(), &instance.instance);
if (error != nullptr) {
return Error(error);
}
return std::monostate();
}
TrapResult<Instance> instantiate(Store::Context cx, const Module &m) {
wasmtime_instance_t instance;
wasm_trap_t *trap = nullptr;
auto *error = wasmtime_linker_instantiate(ptr.get(), cx.ptr, m.capi(),
&instance, &trap);
if (error != nullptr) {
return TrapError(Error(error));
}
if (trap != nullptr) {
return TrapError(Trap(trap));
}
return Instance(instance);
}
Result<std::monostate> module(Store::Context cx, std::string_view name,
const Module &m) {
auto *error = wasmtime_linker_module(ptr.get(), cx.ptr, name.data(),
name.size(), m.capi());
if (error != nullptr) {
return Error(error);
}
return std::monostate();
}
[[nodiscard]] std::optional<Extern>
get(Store::Context cx, std::string_view module, std::string_view name) {
wasmtime_extern_t item;
if (wasmtime_linker_get(ptr.get(), cx.ptr, module.data(), module.size(),
name.data(), name.size(), &item)) {
return detail::cvt_extern(item);
}
return std::nullopt;
}
template <typename F,
std::enable_if_t<
std::is_invocable_r_v<Result<std::monostate, Trap>, F, Caller,
Span<const Val>, Span<Val>>,
bool> = true>
Result<std::monostate> func_new(std::string_view module,
std::string_view name, const FuncType &ty,
F &&f) {
auto *error = wasmtime_linker_define_func(
ptr.get(), module.data(), module.length(), name.data(), name.length(),
ty.ptr.get(), Func::raw_callback<std::remove_reference_t<F>>,
std::make_unique<std::remove_reference_t<F>>(std::forward<F>(f))
.release(),
Func::raw_finalize<std::remove_reference_t<F>>);
if (error != nullptr) {
return Error(error);
}
return std::monostate();
}
template <typename F,
std::enable_if_t<WasmHostFunc<F>::Params::valid, bool> = true,
std::enable_if_t<WasmHostFunc<F>::Results::valid, bool> = true>
Result<std::monostate> func_wrap(std::string_view module,
std::string_view name, F &&f) {
using HostFunc = WasmHostFunc<F>;
auto params = HostFunc::Params::types();
auto results = HostFunc::Results::types();
auto ty = FuncType::from_iters(params, results);
auto *error = wasmtime_linker_define_func_unchecked(
ptr.get(), module.data(), module.length(), name.data(), name.length(),
ty.ptr.get(), Func::raw_callback_unchecked<std::remove_reference_t<F>>,
std::make_unique<std::remove_reference_t<F>>(std::forward<F>(f))
.release(),
Func::raw_finalize<std::remove_reference_t<F>>);
if (error != nullptr) {
return Error(error);
}
return std::monostate();
}
Result<Func> get_default(Store::Context cx, std::string_view name) {
wasmtime_func_t item;
auto *error = wasmtime_linker_get_default(ptr.get(), cx.ptr, name.data(),
name.size(), &item);
if (error != nullptr) {
return Error(error);
}
return Func(item);
}
Result<std::monostate> define_unknown_imports_as_traps(Module &module) {
auto *error = wasmtime_linker_define_unknown_imports_as_traps(
ptr.get(), module.capi());
if (error != nullptr) {
return Error(error);
}
return std::monostate();
}
Result<std::monostate>
define_unknown_imports_as_default_values(Store::Context cx, Module &module) {
auto *error = wasmtime_linker_define_unknown_imports_as_default_values(
ptr.get(), cx.ptr, module.capi());
if (error != nullptr) {
return Error(error);
}
return std::monostate();
}
};
}
#endif