diff --git a/examples/ipfs_node/src/node/imports.rs b/examples/ipfs_node/src/node/imports.rs index bf166fe8..20f523dc 100644 --- a/examples/ipfs_node/src/node/imports.rs +++ b/examples/ipfs_node/src/node/imports.rs @@ -14,7 +14,8 @@ * limitations under the License. */ -use super::utils::get_export_func_by_name; +use crate::init_wasm_func_once; +use crate::call_wasm_func; use wasmer_core::vm::Ctx; use wasmer_core::typed_func::DynamicFunc; @@ -54,6 +55,7 @@ where use wasmer_core::Func; use std::cell::RefCell; + //#[rustfmt:skip] let allocate_func: Box>>> = Box::new(RefCell::new(None)); let set_result_ptr_func: Box>>> = Box::new(RefCell::new(None)); @@ -75,65 +77,14 @@ where }; unsafe { - if allocate_func.borrow().is_none() { - let raw_allocate_func = - match get_export_func_by_name::(ctx, ALLOCATE_FUNC_NAME) { - Ok(func) => func, - Err(_) => return vec![Value::I32(4)], - }; + init_wasm_func_once!(allocate_func, ctx, i32, i32, ALLOCATE_FUNC_NAME, 4); + init_wasm_func_once!(set_result_ptr_func, ctx, i32, (), SET_PTR_FUNC_NAME, 5); + init_wasm_func_once!(set_result_size_func, ctx, i32, (), SET_SIZE_FUNC_NAME, 6); - let raw_allocate_func = - std::mem::transmute::, Func<'static, _, _>>(raw_allocate_func); - *allocate_func.borrow_mut() = Some(raw_allocate_func); - } - - if set_result_ptr_func.borrow().is_none() { - let raw_set_result_ptr_func = - match get_export_func_by_name::(ctx, SET_PTR_FUNC_NAME) { - Ok(func) => func, - Err(_) => return vec![Value::I32(5)], - }; - - let raw_set_result_ptr_func = std::mem::transmute::< - Func<'_, _, _>, - Func<'static, _, _>, - >(raw_set_result_ptr_func); - *set_result_ptr_func.borrow_mut() = Some(raw_set_result_ptr_func); - } - - if set_result_size_func.borrow().is_none() { - let raw_set_result_size_func = - match get_export_func_by_name::(ctx, SET_SIZE_FUNC_NAME) { - Ok(func) => func, - Err(_) => return vec![Value::I32(6)], - }; - - let raw_set_result_size_func = std::mem::transmute::< - Func<'_, _, _>, - Func<'static, _, _>, - >(raw_set_result_size_func); - *set_result_size_func.borrow_mut() = Some(raw_set_result_size_func); - } - - let mem_address = allocate_func - .borrow() - .as_ref() - .unwrap() - .call(result.len() as i32) - .unwrap(); + let mem_address = call_wasm_func!(allocate_func, result.len() as i32); write_to_mem(ctx, mem_address as usize, result.as_bytes()); - set_result_ptr_func - .borrow() - .as_ref() - .unwrap() - .call(mem_address as i32) - .unwrap(); - set_result_size_func - .borrow() - .as_ref() - .unwrap() - .call(result.len() as i32) - .unwrap(); + call_wasm_func!(set_result_ptr_func, mem_address); + call_wasm_func!(set_result_size_func, result.len() as i32); vec![Value::I32(0)] } diff --git a/examples/ipfs_node/src/node/utils.rs b/examples/ipfs_node/src/node/utils.rs index 081cbaa5..f7f9ffc6 100644 --- a/examples/ipfs_node/src/node/utils.rs +++ b/examples/ipfs_node/src/node/utils.rs @@ -32,6 +32,7 @@ use wasmer_core::module::ExportIndex; use std::path::PathBuf; // based on Wasmer: https://github.com/wasmerio/wasmer/blob/081f6250e69b98b9f95a8f62ad6d8386534f3279/lib/runtime-core/src/instance.rs#L863 +/// Extract export function from Wasmer instance by name. pub(super) unsafe fn get_export_func_by_name<'a, Args, Rets>( ctx: &'a mut Ctx, name: &str, @@ -101,6 +102,7 @@ where Ok(typed_func) } +/// Make FCE config based on parsed raw config. pub(super) fn make_wasm_process_config( config: Option, ) -> Result { @@ -170,3 +172,31 @@ pub(super) fn make_wasm_process_config( Ok(wasm_module_config) } + +#[macro_export] // https://github.com/rust-lang/rust/issues/57966#issuecomment-461077932 +/// Initialize Wasm function in form of Box>>> only once. +macro_rules! init_wasm_func_once { + ($func:ident, $ctx:ident, $args:ty, $rets:ty, $func_name:ident, $ret_error_code: expr) => { + if $func.borrow().is_none() { + let raw_func = + match super::utils::get_export_func_by_name::<$args, $rets>($ctx, $func_name) { + Ok(func) => func, + Err(_) => return vec![Value::I32($ret_error_code)], + }; + + // assumed that this function will be used only in the context of closure + // linked to a corresponding Wasm import - os it is safe to make is static + let raw_func = std::mem::transmute::, Func<'static, _, _>>(raw_func); + + *$func.borrow_mut() = Some(raw_func); + } + }; +} + +#[macro_export] +/// Call Wasm function that have Box>>> type. +macro_rules! call_wasm_func { + ($func:ident, $arg:expr) => { + $func.borrow().as_ref().unwrap().call($arg).unwrap() + }; +}