142 lines
4.4 KiB
Rust
142 lines
4.4 KiB
Rust
use crate::script_implementations::wasm::script_resolver::{WebAssemblyEnv, WebAssemblyEnvironmentData};
|
|
use anyhow::Error;
|
|
use std::ffi::{c_char, CString};
|
|
use std::sync::Arc;
|
|
use wasmer::{FromToNativeWasmType, FunctionEnvMut};
|
|
|
|
/// A result type that can be given to, or returned from WASM.
|
|
pub type WasmResult<T> = (u32, T);
|
|
|
|
/// A result type that can be given to, or returned from WASM, but does not contain a value.
|
|
pub type WasmVoidResult = u32;
|
|
|
|
pub(crate) trait WasmVoidResultExtension {
|
|
fn into_result(self, env: FunctionEnvMut<WebAssemblyEnv>) -> anyhow_ext::Result<()>;
|
|
fn into_result_env(self, env: &Arc<WebAssemblyEnvironmentData>) -> anyhow_ext::Result<()>;
|
|
fn from_result(res: anyhow_ext::Result<()>, env: &FunctionEnvMut<WebAssemblyEnv>) -> Self;
|
|
fn ok() -> Self;
|
|
fn err(err: anyhow::Error, env: &FunctionEnvMut<WebAssemblyEnv>) -> Self;
|
|
}
|
|
|
|
pub(super) fn wasm_ok<T>(value: T) -> WasmResult<T>
|
|
where
|
|
T: FromToNativeWasmType,
|
|
<T as FromToNativeWasmType>::Native: Default,
|
|
{
|
|
(0, value)
|
|
}
|
|
|
|
pub(super) fn wasm_err<T>(err: Error, env: &FunctionEnvMut<WebAssemblyEnv>) -> WasmResult<T>
|
|
where
|
|
T: FromToNativeWasmType + Default,
|
|
{
|
|
let s = CString::new(err.to_string()).unwrap();
|
|
let ptr = env.data().data().copy_value_vec_to_wasm(s.as_bytes()).unwrap();
|
|
(ptr, <T as Default>::default())
|
|
}
|
|
|
|
impl WasmVoidResultExtension for WasmVoidResult {
|
|
fn into_result(self, env: FunctionEnvMut<WebAssemblyEnv>) -> anyhow::Result<()> {
|
|
Self::into_result_env(self, &env.data().data())
|
|
}
|
|
|
|
fn into_result_env(self, env: &Arc<WebAssemblyEnvironmentData>) -> anyhow::Result<()> {
|
|
if self == 0 {
|
|
Ok(())
|
|
} else {
|
|
unsafe {
|
|
let ptr = self;
|
|
let mem: *mut c_char = env.get_raw_pointer(ptr as u32);
|
|
let string = std::ffi::CStr::from_ptr(mem);
|
|
let e = anyhow_ext::anyhow!("{}", string.to_str().unwrap());
|
|
env.script_function_cache().dealloc_cstring(&env, ptr as u32).unwrap();
|
|
Err(e)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn from_result(res: anyhow::Result<()>, env: &FunctionEnvMut<WebAssemblyEnv>) -> Self {
|
|
match res {
|
|
Ok(_) => 0,
|
|
Err(e) => {
|
|
let s = CString::new(e.to_string()).unwrap();
|
|
let ptr = env.data().data().copy_value_vec_to_wasm(s.as_bytes()).unwrap();
|
|
ptr as u32
|
|
}
|
|
}
|
|
}
|
|
|
|
fn ok() -> Self {
|
|
0
|
|
}
|
|
|
|
fn err(err: Error, env: &FunctionEnvMut<WebAssemblyEnv>) -> Self {
|
|
let s = CString::new(err.to_string()).unwrap();
|
|
let ptr = env.data().data().copy_value_vec_to_wasm(s.as_bytes()).unwrap();
|
|
ptr as u32
|
|
}
|
|
}
|
|
|
|
macro_rules! try_wasm {
|
|
($e:expr, $env:expr) => {
|
|
match $e.with_context(|| format!("WASM function {}", stdext::function_name!())) {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
return crate::script_implementations::wasm::export_registry::wasm_err(e.into(), &$env);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! try_wasm_void {
|
|
($e:expr, $env:expr) => {
|
|
match $e.with_context(|| format!("WASM function {}", stdext::function_name!())) {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
return WasmVoidResult::from_result(Err(e.into()), &$env);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
pub(super) use try_wasm;
|
|
pub(super) use try_wasm_void;
|
|
|
|
macro_rules! get_value {
|
|
($e:expr, $env:expr) => {
|
|
crate::script_implementations::wasm::export_registry::try_wasm!($e.value_func(&$env), $env)
|
|
};
|
|
}
|
|
|
|
macro_rules! get_value_arc {
|
|
($e:expr, $env:expr) => {
|
|
crate::script_implementations::wasm::export_registry::try_wasm!($e.value_func_arc(&$env), $env)
|
|
};
|
|
}
|
|
|
|
macro_rules! get_value_void {
|
|
($e:expr, $env:expr) => {
|
|
crate::script_implementations::wasm::export_registry::try_wasm_void!($e.value_func(&$env), $env)
|
|
};
|
|
}
|
|
|
|
macro_rules! get_value_arc_void {
|
|
($e:expr, $env:expr) => {
|
|
crate::script_implementations::wasm::export_registry::try_wasm_void!($e.value_func_arc(&$env), $env)
|
|
};
|
|
}
|
|
|
|
pub(super) use get_value;
|
|
pub(super) use get_value_arc;
|
|
pub(super) use get_value_arc_void;
|
|
pub(super) use get_value_void;
|
|
|
|
macro_rules! get_value_call_getter {
|
|
($e:ident.$func:ident(), $env:expr) => {{
|
|
let _value = crate::script_implementations::wasm::export_registry::try_wasm!($e.value_func(&$env), $env);
|
|
_value.$func()
|
|
}};
|
|
}
|
|
|
|
pub(super) use get_value_call_getter;
|