marine_wasm_backend_traits/
function.rs1use crate::AsContextMut;
18use crate::FuncSig;
19use crate::impl_for_each_function_signature;
20use crate::RuntimeResult;
21use crate::WasmBackend;
22use crate::WValue;
23
24use futures::future::BoxFuture;
25
26pub trait HostFunction<WB: WasmBackend>: Send + Sync + Clone {
29 fn new<F>(store: &mut impl AsContextMut<WB>, sig: FuncSig, func: F) -> Self
32 where
33 F: for<'c> Fn(&[WValue]) -> anyhow::Result<Vec<WValue>> + Sync + Send + 'static;
34
35 fn new_with_caller<F>(store: &mut impl AsContextMut<WB>, sig: FuncSig, func: F) -> Self
37 where
38 F: for<'c> Fn(
39 <WB as WasmBackend>::ImportCallContext<'c>,
40 &[WValue],
41 ) -> anyhow::Result<Vec<WValue>>
42 + Sync
43 + Send
44 + 'static;
45
46 fn new_with_caller_async<F>(store: &mut impl AsContextMut<WB>, sig: FuncSig, func: F) -> Self
48 where
49 F: for<'c> Fn(
50 <WB as WasmBackend>::ImportCallContext<'c>,
51 &'c [WValue],
52 ) -> BoxFuture<'c, anyhow::Result<Vec<WValue>>>
53 + Sync
54 + Send
55 + 'static;
56
57 fn new_async<F>(store: &mut impl AsContextMut<WB>, sig: FuncSig, func: F) -> Self
59 where
60 F: for<'c> Fn(&'c [WValue]) -> BoxFuture<'c, anyhow::Result<Vec<WValue>>>
61 + Sync
62 + Send
63 + 'static;
64
65 fn new_typed<Params, Results, Env>(
68 store: &mut impl AsContextMut<WB>,
69 func: impl IntoFunc<WB, Params, Results, Env>,
70 ) -> Self;
71
72 fn signature(&self, store: &mut impl AsContextMut<WB>) -> FuncSig;
76}
77
78pub trait ExportFunction<WB: WasmBackend>: Send + Sync + Clone {
81 fn signature(&self, store: &mut impl AsContextMut<WB>) -> FuncSig;
85
86 fn call_async<'args>(
92 &'args self,
93 store: &'args mut impl AsContextMut<WB>,
94 args: &'args [WValue],
95 ) -> BoxFuture<'args, RuntimeResult<Vec<WValue>>>;
96}
97
98pub trait IntoFunc<WB: WasmBackend, Params, Results, Env> {
106 fn into_func(self, ctx: &mut impl AsContextMut<WB>) -> <WB as WasmBackend>::HostFunction;
107}
108
109pub struct WithEnv {}
111
112pub struct WithoutEnv {}
114
115#[macro_export]
116macro_rules! replace_with {
117 ($from:ident -> $to:ident) => {
118 $to
119 };
120}
121
122macro_rules! impl_into_func {
123 ($num:tt $($args:ident)*) => (paste::paste!{
124 #[allow(non_snake_case)]
125 impl<WB, F> IntoFunc<WB, ($(replace_with!($args -> i32),)*), (), WithoutEnv> for F
126 where
127 WB: WasmBackend,
128 F: Fn($(replace_with!($args -> i32),)*) + Send + Sync + 'static,
129 {
130 fn into_func(self, ctx: &mut impl AsContextMut<WB>) -> <WB as WasmBackend>::HostFunction {
131 <WB as WasmBackend>::HostFunction:: [< new_typed_ $num >] (ctx.as_context_mut(), self)
132 }
133 }
134
135 #[allow(non_snake_case)]
136 impl<WB, F> IntoFunc<WB, ($(replace_with!($args -> i32),)*), (), WithEnv> for F
137 where
138 WB: WasmBackend,
139 F: Fn(<WB as WasmBackend>::ImportCallContext<'_>, $(replace_with!($args -> i32),)*) + Send + Sync + 'static,
140 {
141 fn into_func(self, ctx: &mut impl AsContextMut<WB>) -> <WB as WasmBackend>::HostFunction {
142 <WB as WasmBackend>::HostFunction:: [< new_typed_with_env_ $num >] (ctx.as_context_mut(), self)
143 }
144 }
145
146 #[allow(non_snake_case)]
147 impl<WB, F> IntoFunc<WB, ($(replace_with!($args -> i32),)*), i32, WithoutEnv> for F
148 where
149 WB: WasmBackend,
150 F: Fn($(replace_with!($args -> i32),)*) -> i32 + Send + Sync + 'static,
151 {
152 fn into_func(self, ctx: &mut impl AsContextMut<WB>) -> <WB as WasmBackend>::HostFunction {
153 <WB as WasmBackend>::HostFunction:: [< new_typed_ $num _r >] (ctx.as_context_mut(), self)
154 }
155 }
156
157 #[allow(non_snake_case)]
158 impl<WB, F> IntoFunc<WB, ($(replace_with!($args -> i32),)*), i32, WithEnv> for F
159 where
160 WB: WasmBackend,
161 F: Fn(<WB as WasmBackend>::ImportCallContext<'_>, $(replace_with!($args -> i32),)*) -> i32 + Send + Sync + 'static,
162 {
163 fn into_func(self, ctx: &mut impl AsContextMut<WB>) -> <WB as WasmBackend>::HostFunction {
164 <WB as WasmBackend>::HostFunction:: [< new_typed_with_env_ $num _r >] (ctx.as_context_mut(), self)
165 }
166 }
167 });
168}
169
170impl_for_each_function_signature!(impl_into_func);
171
172macro_rules! declare_func_construction {
173 ($num:tt $($args:ident)*) => (paste::paste!{
174 #[allow(non_snake_case)]
175 fn [< new_typed_ $num >]<F>(ctx: <WB as WasmBackend>::ContextMut<'_>, func: F) -> <WB as WasmBackend>::HostFunction
176 where F: Fn($(replace_with!($args -> i32),)*) + Send + Sync + 'static
177 {
178 let func = move |_: <WB as WasmBackend>::ImportCallContext<'_>, $($args,)*| { func($($args,)*)};
179 Self:: [< new_typed_with_env_ $num >] (ctx, func)
180 }
181
182 #[allow(non_snake_case)]
183 fn [< new_typed_with_env_ $num >]<F>(ctx: <WB as WasmBackend>::ContextMut<'_>, func: F) -> <WB as WasmBackend>::HostFunction
184 where F: Fn(<WB as WasmBackend>::ImportCallContext<'_>, $(replace_with!($args -> i32),)*) + Send + Sync + 'static;
185
186 #[allow(non_snake_case)]
187 fn [< new_typed_ $num _r>]<F>(ctx: <WB as WasmBackend>::ContextMut<'_>, func: F) -> <WB as WasmBackend>::HostFunction
188 where F: Fn($(replace_with!($args -> i32),)*) -> i32 + Send + Sync + 'static
189 {
190 let func = move |_: <WB as WasmBackend>::ImportCallContext<'_>, $($args,)*| -> i32 { func($($args,)*)};
191 Self:: [< new_typed_with_env_ $num _r >] (ctx, func)
192 }
193
194 #[allow(non_snake_case)]
195 fn [< new_typed_with_env_ $num _r>]<F>(ctx: <WB as WasmBackend>::ContextMut<'_>, func: F) -> <WB as WasmBackend>::HostFunction
196 where F: Fn(<WB as WasmBackend>::ImportCallContext<'_>, $(replace_with!($args -> i32),)*) -> i32 + Send + Sync + 'static;
197 });
198}
199
200pub trait FuncConstructor<WB: WasmBackend> {
201 impl_for_each_function_signature!(declare_func_construction);
202}