1use super::{into_func::WasmTyList, Func};
2use crate::{
3 core::UntypedVal,
4 engine::{CallParams, CallResults},
5 AsContext,
6 AsContextMut,
7 Error,
8 TypedResumableCall,
9};
10use core::{fmt, fmt::Debug, marker::PhantomData};
11
12#[repr(transparent)]
22pub struct TypedFunc<Params, Results> {
23 signature: PhantomData<fn(Params) -> Results>,
25 func: Func,
27}
28
29impl<Params, Results> Debug for TypedFunc<Params, Results> {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 f.debug_struct("TypedFunc")
32 .field("signature", &self.signature)
33 .field("func", &self.func)
34 .finish()
35 }
36}
37
38impl<Params, Results> Copy for TypedFunc<Params, Results> {}
39
40impl<Params, Results> Clone for TypedFunc<Params, Results> {
41 fn clone(&self) -> TypedFunc<Params, Results> {
42 *self
43 }
44}
45
46impl<Params, Results> TypedFunc<Params, Results> {
47 pub fn func(&self) -> &Func {
53 &self.func
54 }
55}
56
57impl<Params, Results> TypedFunc<Params, Results>
58where
59 Params: WasmParams,
60 Results: WasmResults,
61{
62 pub(crate) fn new(ctx: impl AsContext, func: Func) -> Result<Self, Error> {
69 let func_type = func.ty(&ctx);
70 let (actual_params, actual_results) = (
71 <Params as WasmTyList>::types(),
72 <Results as WasmTyList>::types(),
73 );
74 func_type.match_params(actual_params.as_ref())?;
75 func_type.match_results(actual_results.as_ref(), true)?;
76 Ok(Self {
77 signature: PhantomData,
78 func,
79 })
80 }
81
82 pub fn call(&self, mut ctx: impl AsContextMut, params: Params) -> Result<Results, Error> {
97 ctx.as_context().store.engine().clone().execute_func(
99 ctx.as_context_mut(),
100 &self.func,
101 params,
102 <CallResultsTuple<Results>>::default(),
103 )
104 }
105
106 pub fn call_resumable(
122 &self,
123 mut ctx: impl AsContextMut,
124 params: Params,
125 ) -> Result<TypedResumableCall<Results>, Error> {
126 ctx.as_context()
128 .store
129 .engine()
130 .clone()
131 .execute_func_resumable(
132 ctx.as_context_mut(),
133 &self.func,
134 params,
135 <CallResultsTuple<Results>>::default(),
136 )
137 .map(TypedResumableCall::new)
138 }
139}
140
141impl<Params> CallParams for Params
142where
143 Params: WasmParams,
144{
145 type Params = <Params as WasmTyList>::ValuesIter;
146
147 #[inline]
148 fn call_params(self) -> Self::Params {
149 <Params as WasmTyList>::values(self).into_iter()
150 }
151}
152
153pub struct CallResultsTuple<Results> {
163 _marker: PhantomData<fn() -> Results>,
164}
165
166impl<Results> Default for CallResultsTuple<Results> {
167 fn default() -> Self {
168 Self {
169 _marker: PhantomData,
170 }
171 }
172}
173impl<Results> Copy for CallResultsTuple<Results> {}
174impl<Results> Clone for CallResultsTuple<Results> {
175 fn clone(&self) -> Self {
176 *self
177 }
178}
179
180impl<Results> CallResults for CallResultsTuple<Results>
181where
182 Results: WasmResults,
183{
184 type Results = Results;
185
186 fn len_results(&self) -> usize {
187 <Results as WasmTyList>::LEN
188 }
189
190 fn call_results(self, results: &[UntypedVal]) -> Self::Results {
191 <Results as WasmTyList>::from_values(results)
192 .expect("unable to construct typed results from call results")
193 }
194}
195
196pub trait WasmParams: WasmTyList {}
198impl<T> WasmParams for T where T: WasmTyList {}
199
200pub trait WasmResults: WasmTyList {}
202impl<T> WasmResults for T where T: WasmTyList {}