use crate::{ bad_utf8, handle_result, wasm_engine_t, wasm_functype_t, wasm_trap_t, wasmtime_error_t, wasmtime_extern_t, wasmtime_module_t, CStoreContextMut, }; use std::ffi::c_void; use std::mem::MaybeUninit; use std::str; use wasmtime::{Func, Instance, Linker}; #[repr(C)] pub struct wasmtime_linker_t { linker: Linker, } wasmtime_c_api_macros::declare_own!(wasmtime_linker_t); #[no_mangle] pub extern "C" fn wasmtime_linker_new(engine: &wasm_engine_t) -> Box { Box::new(wasmtime_linker_t { linker: Linker::new(&engine.engine), }) } #[no_mangle] pub extern "C" fn wasmtime_linker_allow_shadowing( linker: &mut wasmtime_linker_t, allow_shadowing: bool, ) { linker.linker.allow_shadowing(allow_shadowing); } macro_rules! to_str { ($ptr:expr, $len:expr) => { match str::from_utf8(crate::slice_from_raw_parts($ptr, $len)) { Ok(s) => s, Err(_) => return bad_utf8(), } }; } #[no_mangle] pub unsafe extern "C" fn wasmtime_linker_define( linker: &mut wasmtime_linker_t, module: *const u8, module_len: usize, name: *const u8, name_len: usize, item: &wasmtime_extern_t, ) -> Option> { let linker = &mut linker.linker; let module = to_str!(module, module_len); let name = to_str!(name, name_len); let item = item.to_extern(); handle_result(linker.define(module, name, item), |_linker| ()) } #[no_mangle] pub unsafe extern "C" fn wasmtime_linker_define_func( linker: &mut wasmtime_linker_t, module: *const u8, module_len: usize, name: *const u8, name_len: usize, ty: &wasm_functype_t, callback: crate::wasmtime_func_callback_t, data: *mut c_void, finalizer: Option, ) -> Option> { let ty = ty.ty().ty.clone(); let module = to_str!(module, module_len); let name = to_str!(name, name_len); let cb = crate::func::c_callback_to_rust_fn(callback, data, finalizer); handle_result(linker.linker.func_new(module, name, ty, cb), |_linker| ()) } #[no_mangle] pub unsafe extern "C" fn wasmtime_linker_define_func_unchecked( linker: &mut wasmtime_linker_t, module: *const u8, module_len: usize, name: *const u8, name_len: usize, ty: &wasm_functype_t, callback: crate::wasmtime_func_unchecked_callback_t, data: *mut c_void, finalizer: Option, ) -> Option> { let ty = ty.ty().ty.clone(); let module = to_str!(module, module_len); let name = to_str!(name, name_len); let cb = crate::func::c_unchecked_callback_to_rust_fn(callback, data, finalizer); handle_result( linker.linker.func_new_unchecked(module, name, ty, cb), |_linker| (), ) } #[cfg(feature = "wasi")] #[no_mangle] pub extern "C" fn wasmtime_linker_define_wasi( linker: &mut wasmtime_linker_t, ) -> Option> { handle_result( wasmtime_wasi::add_to_linker(&mut linker.linker, |cx| cx.wasi.as_mut().unwrap()), |_linker| (), ) } #[no_mangle] pub unsafe extern "C" fn wasmtime_linker_define_instance( linker: &mut wasmtime_linker_t, store: CStoreContextMut<'_>, name: *const u8, name_len: usize, instance: &Instance, ) -> Option> { let linker = &mut linker.linker; let name = to_str!(name, name_len); handle_result(linker.instance(store, name, *instance), |_linker| ()) } #[no_mangle] pub extern "C" fn wasmtime_linker_instantiate( linker: &wasmtime_linker_t, store: CStoreContextMut<'_>, module: &wasmtime_module_t, instance_ptr: &mut Instance, trap_ptr: &mut *mut wasm_trap_t, ) -> Option> { let result = linker.linker.instantiate(store, &module.module); super::instance::handle_instantiate(result, instance_ptr, trap_ptr) } #[no_mangle] pub unsafe extern "C" fn wasmtime_linker_module( linker: &mut wasmtime_linker_t, store: CStoreContextMut<'_>, name: *const u8, name_len: usize, module: &wasmtime_module_t, ) -> Option> { let linker = &mut linker.linker; let name = to_str!(name, name_len); handle_result(linker.module(store, name, &module.module), |_linker| ()) } #[no_mangle] pub unsafe extern "C" fn wasmtime_linker_get_default( linker: &wasmtime_linker_t, store: CStoreContextMut<'_>, name: *const u8, name_len: usize, func: &mut Func, ) -> Option> { let linker = &linker.linker; let name = to_str!(name, name_len); handle_result(linker.get_default(store, name), |f| *func = f) } #[no_mangle] pub unsafe extern "C" fn wasmtime_linker_get( linker: &wasmtime_linker_t, store: CStoreContextMut<'_>, module: *const u8, module_len: usize, name: *const u8, name_len: usize, item_ptr: &mut MaybeUninit, ) -> bool { let linker = &linker.linker; let module = match str::from_utf8(crate::slice_from_raw_parts(module, module_len)) { Ok(s) => s, Err(_) => return false, }; let name = match str::from_utf8(crate::slice_from_raw_parts(name, name_len)) { Ok(s) => s, Err(_) => return false, }; match linker.get(store, module, name) { Some(which) => { crate::initialize(item_ptr, which.into()); true } None => false, } }