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 = "v8")]
71 BackendStore::V8(_) => self.call_v8(store, $([<p_ $x>]),*),
72 #[cfg(feature = "js")]
73 BackendStore::Js(_) => self.call_js(store, $([<p_ $x>]),*),
74
75 }
76 }
77
78 #[cfg(feature = "experimental-async")]
80 #[allow(unused_mut)]
81 #[allow(clippy::too_many_arguments)]
82 pub fn call_async(
83 &self,
84 store: &impl AsStoreAsync,
85 $( $x: $x, )*
86 ) -> impl Future<Output = Result<Rets, RuntimeError>> + Sized + 'static
87 where
88 $( $x: FromToNativeWasmType + 'static, )*
89 {
90 $(
91 let [<p_ $x>] = $x;
92 )*
93 let store = store.store();
94 let func = self.func.clone();
95 async move {
96 let read_lock = store.read_lock().await;
97 match read_lock.as_store_ref().inner.store {
98 #[cfg(feature = "sys")]
99 BackendStore::Sys(_) => {
100 drop(read_lock);
101 Self::call_async_sys(func, store, $([<p_ $x>]),*).await
102 }
103 #[cfg(feature = "v8")]
104 BackendStore::V8(_) => async_backend_error(),
105 #[cfg(feature = "js")]
106 BackendStore::Js(_) => {
107 drop(read_lock);
108 Self::call_async_js(func, store, $([<p_ $x>]),*).await
109 }
110 }
111 }
112 }
113
114 #[doc(hidden)]
115 #[allow(missing_docs)]
116 #[allow(unused_mut)]
117 #[allow(clippy::too_many_arguments)]
118 pub fn call_raw(&self, store: &mut impl AsStoreMut, mut params_list: Vec<RawValue> ) -> Result<Rets, RuntimeError> {
119 match store.as_store_mut().inner.store {
120 #[cfg(feature = "sys")]
121 BackendStore::Sys(_) => self.call_raw_sys(store, params_list),
122 #[cfg(feature = "v8")]
123 BackendStore::V8(_) => self.call_raw_v8(store, params_list),
124 #[cfg(feature = "js")]
125 BackendStore::Js(_) => self.call_raw_js(store, params_list),
126 }
127 }
128 }
129 }
130 };
131}
132
133impl_native_traits!();
134impl_native_traits!(A1);
135impl_native_traits!(A1, A2);
136impl_native_traits!(A1, A2, A3);
137impl_native_traits!(A1, A2, A3, A4);
138impl_native_traits!(A1, A2, A3, A4, A5);
139impl_native_traits!(A1, A2, A3, A4, A5, A6);
140impl_native_traits!(A1, A2, A3, A4, A5, A6, A7);
141impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8);
142impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
143impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
144impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
145impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
146impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
147impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
148impl_native_traits!(
149 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15
150);
151impl_native_traits!(
152 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16
153);
154impl_native_traits!(
155 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17
156);
157impl_native_traits!(
158 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18
159);
160impl_native_traits!(
161 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19
162);
163impl_native_traits!(
164 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20
165);
166
167fn async_backend_error<Rets>() -> Result<Rets, RuntimeError> {
168 Err(RuntimeError::new(
169 "async calls are not supported with the `v8` backend",
170 ))
171}