1#[cfg(feature = "experimental-async")]
11use crate::AsStoreAsync;
12use crate::{
13 AsStoreMut, BackendStore, FromToNativeWasmType, Function, NativeWasmTypeInto, RuntimeError,
14 WasmTypeList, store::AsStoreRef,
15};
16use std::future::Future;
17use std::marker::PhantomData;
18use wasmer_types::RawValue;
19
20#[derive(Clone, Debug)]
23pub struct TypedFunction<Args, Rets> {
24 pub(crate) func: Function,
25 _phantom: PhantomData<fn(Args) -> Rets>,
26}
27
28unsafe impl<Args, Rets> Send for TypedFunction<Args, Rets> {}
29unsafe impl<Args, Rets> Sync for TypedFunction<Args, Rets> {}
30
31impl<Args, Rets> TypedFunction<Args, Rets>
32where
33 Args: WasmTypeList,
34 Rets: WasmTypeList,
35{
36 #[allow(dead_code)]
37 pub(crate) fn new(_store: &impl AsStoreRef, func: Function) -> Self {
38 Self {
39 func,
40 _phantom: PhantomData,
41 }
42 }
43
44 pub(crate) fn into_function(self) -> Function {
45 self.func
46 }
47}
48
49macro_rules! impl_native_traits {
50 ( $( $x:ident ),* ) => {
51 paste::paste!{
52 #[allow(unused_parens, non_snake_case)]
53 impl<$( $x , )* Rets> TypedFunction<( $( $x ),* ), Rets>
54 where
55 $( $x: FromToNativeWasmType, )*
56 Rets: WasmTypeList,
57 {
58 #[allow(unused_mut)]
60 #[allow(clippy::too_many_arguments)]
61 pub fn call(&self, store: &mut impl AsStoreMut, $( $x: $x, )* ) -> Result<Rets, RuntimeError> where $( $x: FromToNativeWasmType, )*
62
63 {
64 $(
65 let [<p_ $x>] = $x;
66 )*
67 match store.as_store_mut().inner.store {
68 #[cfg(feature = "sys")]
69 BackendStore::Sys(_) => self.call_sys(store, $([<p_ $x>]),*),
70 #[cfg(feature = "wamr")]
71 BackendStore::Wamr(_) => self.call_wamr(store, $([<p_ $x>]),*),
72 #[cfg(feature = "wasmi")]
73 BackendStore::Wasmi(_) => self.call_wasmi(store, $([<p_ $x>]),*),
74 #[cfg(feature = "v8")]
75 BackendStore::V8(_) => self.call_v8(store, $([<p_ $x>]),*),
76 #[cfg(feature = "js")]
77 BackendStore::Js(_) => self.call_js(store, $([<p_ $x>]),*),
78 #[cfg(feature = "jsc")]
79 BackendStore::Jsc(_) => self.call_jsc(store, $([<p_ $x>]),*),
80
81 }
82 }
83
84 #[cfg(feature = "experimental-async")]
86 #[allow(unused_mut)]
87 #[allow(clippy::too_many_arguments)]
88 pub fn call_async(
89 &self,
90 store: &impl AsStoreAsync,
91 $( $x: $x, )*
92 ) -> impl Future<Output = Result<Rets, RuntimeError>> + Sized + 'static
93 where
94 $( $x: FromToNativeWasmType + 'static, )*
95 {
96 $(
97 let [<p_ $x>] = $x;
98 )*
99 let store = store.store();
100 let func = self.func.clone();
101 async move {
102 let read_lock = store.read_lock().await;
103 match read_lock.as_store_ref().inner.store {
104 #[cfg(feature = "sys")]
105 BackendStore::Sys(_) => {
106 drop(read_lock);
107 Self::call_async_sys(func, store, $([<p_ $x>]),*).await
108 }
109 #[cfg(feature = "wamr")]
110 BackendStore::Wamr(_) => async_backend_error(),
111 #[cfg(feature = "wasmi")]
112 BackendStore::Wasmi(_) => async_backend_error(),
113 #[cfg(feature = "v8")]
114 BackendStore::V8(_) => async_backend_error(),
115 #[cfg(feature = "js")]
116 BackendStore::Js(_) => async_backend_error(),
117 #[cfg(feature = "jsc")]
118 BackendStore::Jsc(_) => async_backend_error(),
119 }
120 }
121 }
122
123 #[doc(hidden)]
124 #[allow(missing_docs)]
125 #[allow(unused_mut)]
126 #[allow(clippy::too_many_arguments)]
127 pub fn call_raw(&self, store: &mut impl AsStoreMut, mut params_list: Vec<RawValue> ) -> Result<Rets, RuntimeError> {
128 match store.as_store_mut().inner.store {
129 #[cfg(feature = "sys")]
130 BackendStore::Sys(_) => self.call_raw_sys(store, params_list),
131 #[cfg(feature = "wamr")]
132 BackendStore::Wamr(_) => self.call_raw_wamr(store, params_list),
133 #[cfg(feature = "wasmi")]
134 BackendStore::Wasmi(_) => self.call_raw_wasmi(store, params_list),
135 #[cfg(feature = "v8")]
136 BackendStore::V8(_) => self.call_raw_v8(store, params_list),
137 #[cfg(feature = "js")]
138 BackendStore::Js(_) => self.call_raw_js(store, params_list),
139 #[cfg(feature = "jsc")]
140 BackendStore::Jsc(_) => self.call_raw_jsc(store, params_list),
141 }
142 }
143 }
144 }
145 };
146}
147
148impl_native_traits!();
149impl_native_traits!(A1);
150impl_native_traits!(A1, A2);
151impl_native_traits!(A1, A2, A3);
152impl_native_traits!(A1, A2, A3, A4);
153impl_native_traits!(A1, A2, A3, A4, A5);
154impl_native_traits!(A1, A2, A3, A4, A5, A6);
155impl_native_traits!(A1, A2, A3, A4, A5, A6, A7);
156impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8);
157impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
158impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
159impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
160impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
161impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
162impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
163impl_native_traits!(
164 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15
165);
166impl_native_traits!(
167 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16
168);
169impl_native_traits!(
170 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17
171);
172impl_native_traits!(
173 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18
174);
175impl_native_traits!(
176 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19
177);
178impl_native_traits!(
179 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20
180);
181
182fn async_backend_error<Rets>() -> Result<Rets, RuntimeError> {
183 Err(RuntimeError::new(
184 "async calls are only supported with the `sys` backend",
185 ))
186}