Skip to main content

wasmer/entities/function/env/
inner.rs

1#[cfg(feature = "experimental-async")]
2use crate::AsStoreAsync;
3use crate::{
4    AsStoreMut, AsStoreRef, FunctionEnv, FunctionEnvMut, StoreMut, StoreRef,
5    macros::backend::match_rt,
6};
7use std::{any::Any, marker::PhantomData};
8
9#[derive(Debug, derive_more::From)]
10/// An opaque reference to a function environment.
11/// The function environment data is owned by the `Store`.
12pub enum BackendFunctionEnv<T> {
13    #[cfg(feature = "sys")]
14    /// The function environment for the `sys` runtime.
15    Sys(crate::backend::sys::function::env::FunctionEnv<T>),
16    #[cfg(feature = "v8")]
17    /// The function environment for the `v8` runtime.
18    V8(crate::backend::v8::function::env::FunctionEnv<T>),
19    #[cfg(feature = "js")]
20    /// The function environment for the `js` runtime.
21    Js(crate::backend::js::function::env::FunctionEnv<T>),
22}
23
24impl<T> Clone for BackendFunctionEnv<T> {
25    fn clone(&self) -> Self {
26        match self {
27            #[cfg(feature = "sys")]
28            Self::Sys(s) => Self::Sys(s.clone()),
29            #[cfg(feature = "v8")]
30            Self::V8(s) => Self::V8(s.clone()),
31            #[cfg(feature = "js")]
32            Self::Js(s) => Self::Js(s.clone()),
33        }
34    }
35}
36
37impl<T> BackendFunctionEnv<T> {
38    /// Make a new FunctionEnv
39    pub fn new(store: &mut impl AsStoreMut, value: T) -> Self
40    where
41        T: Any + Send + 'static + Sized,
42    {
43        match store.as_store_mut().inner.store {
44            #[cfg(feature = "sys")]
45            crate::BackendStore::Sys(_) => Self::Sys(
46                crate::backend::sys::function::env::FunctionEnv::new(store, value),
47            ),
48
49            #[cfg(feature = "v8")]
50            crate::BackendStore::V8(_) => Self::V8(
51                crate::backend::v8::function::env::FunctionEnv::new(store, value),
52            ),
53
54            #[cfg(feature = "js")]
55            crate::BackendStore::Js(_) => Self::Js(
56                crate::backend::js::function::env::FunctionEnv::new(store, value),
57            ),
58        }
59    }
60
61    /// Get the data as reference
62    pub fn as_ref<'a>(&self, store: &'a impl AsStoreRef) -> &'a T
63    where
64        T: Any + Send + 'static + Sized,
65    {
66        match_rt!(on self => f {
67            f.as_ref(store)
68        })
69    }
70
71    /// Get the data as mutable
72    pub fn as_mut<'a>(&self, store: &'a mut impl AsStoreMut) -> &'a mut T
73    where
74        T: Any + Send + 'static + Sized,
75    {
76        match_rt!(on self => s {
77            s.as_mut(store)
78        })
79    }
80
81    /// Convert it into a `FunctionEnvMut`
82    pub fn into_mut(self, store: &mut impl AsStoreMut) -> FunctionEnvMut<'_, T>
83    where
84        T: Any + Send + 'static + Sized,
85    {
86        match_rt!(on self => f {
87            f.into_mut(store).into()
88        })
89    }
90}
91
92/// A temporary handle to a [`FunctionEnv`].
93#[derive(derive_more::From)]
94pub enum BackendFunctionEnvMut<'a, T: 'a> {
95    #[cfg(feature = "sys")]
96    /// The function environment for the `sys` runtime.
97    Sys(crate::backend::sys::function::env::FunctionEnvMut<'a, T>),
98
99    #[cfg(feature = "v8")]
100    /// The function environment for the `v8` runtime.
101    V8(crate::backend::v8::function::env::FunctionEnvMut<'a, T>),
102
103    #[cfg(feature = "js")]
104    /// The function environment for the `js` runtime.
105    Js(crate::backend::js::function::env::FunctionEnvMut<'a, T>),
106}
107
108impl<T: Send + 'static> BackendFunctionEnvMut<'_, T> {
109    /// Returns a reference to the host state in this function environment.
110    pub fn data(&self) -> &T {
111        match_rt!(on self => f {
112            f.data()
113        })
114    }
115
116    /// Returns a mutable- reference to the host state in this function environment.
117    pub fn data_mut(&mut self) -> &mut T {
118        match_rt!(on self => f {
119            f.data_mut()
120        })
121    }
122
123    /// Borrows a new immmutable reference
124    pub fn as_ref(&self) -> FunctionEnv<T> {
125        match self {
126            #[cfg(feature = "sys")]
127            Self::Sys(f) => BackendFunctionEnv::Sys(f.as_ref()).into(),
128            #[cfg(feature = "v8")]
129            Self::V8(f) => BackendFunctionEnv::V8(f.as_ref()).into(),
130            #[cfg(feature = "js")]
131            Self::Js(f) => BackendFunctionEnv::Js(f.as_ref()).into(),
132        }
133    }
134
135    /// Borrows a new mutable reference
136    pub fn as_mut(&mut self) -> FunctionEnvMut<'_, T> {
137        match self {
138            #[cfg(feature = "sys")]
139            Self::Sys(f) => BackendFunctionEnvMut::Sys(f.as_mut()).into(),
140            #[cfg(feature = "v8")]
141            Self::V8(f) => BackendFunctionEnvMut::V8(f.as_mut()).into(),
142            #[cfg(feature = "js")]
143            Self::Js(f) => BackendFunctionEnvMut::Js(f.as_mut()).into(),
144        }
145    }
146
147    /// Borrows a new mutable reference of both the attached Store and host state
148    pub fn data_and_store_mut(&mut self) -> (&mut T, StoreMut<'_>) {
149        match_rt!(on self => f {
150            f.data_and_store_mut()
151        })
152    }
153
154    /// Creates an [`AsStoreAsync`] from this [`BackendFunctionEnvMut`] if the current
155    /// context is async.
156    #[cfg(feature = "experimental-async")]
157    pub fn as_store_async(&self) -> Option<impl AsStoreAsync + 'static> {
158        let id = self.as_store_ref().inner.objects.id();
159        crate::StoreAsync::from_context(id)
160    }
161}
162
163impl<T> AsStoreRef for BackendFunctionEnvMut<'_, T> {
164    fn as_store_ref(&self) -> StoreRef<'_> {
165        match_rt!(on self => s {
166            s.as_store_ref()
167        })
168    }
169}
170
171impl<T> AsStoreMut for BackendFunctionEnvMut<'_, T> {
172    fn as_store_mut(&mut self) -> StoreMut<'_> {
173        match_rt!(on self => s {
174            s.as_store_mut()
175        })
176    }
177
178    fn objects_mut(&mut self) -> &mut crate::StoreObjects {
179        match_rt!(on self => s {
180            s.objects_mut()
181        })
182    }
183}
184
185impl<T> std::fmt::Debug for BackendFunctionEnvMut<'_, T>
186where
187    T: Send + std::fmt::Debug + 'static,
188{
189    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190        match_rt!(on self => s {
191            write!(f, "{s:?}")
192        })
193    }
194}
195
196/// A shared handle to a [`FunctionEnv`], suitable for use
197/// in async imports.
198#[derive(derive_more::From)]
199#[cfg(feature = "experimental-async")]
200pub enum BackendAsyncFunctionEnvMut<T> {
201    #[cfg(feature = "sys")]
202    /// The function environment for the `sys` runtime.
203    Sys(crate::backend::sys::function::env::AsyncFunctionEnvMut<T>),
204    #[cfg(feature = "js")]
205    /// The function environment for the `js` runtime.
206    Js(crate::backend::js::function::env::AsyncFunctionEnvMut<T>),
207    #[cfg(feature = "v8")]
208    /// Placeholder for unsupported backends.
209    Unsupported(PhantomData<T>),
210}
211
212/// A read-only handle to the [`FunctionEnv`] in an [`BackendAsyncFunctionEnvMut`].
213#[cfg(feature = "experimental-async")]
214pub enum BackendAsyncFunctionEnvHandle<T> {
215    #[cfg(feature = "sys")]
216    /// The function environment handle for the `sys` runtime.
217    Sys(crate::backend::sys::function::env::AsyncFunctionEnvHandle<T>),
218    #[cfg(feature = "js")]
219    /// The function environment handle for the `js` runtime.
220    Js(crate::backend::js::function::env::AsyncFunctionEnvHandle<T>),
221    #[cfg(feature = "v8")]
222    /// Placeholder for unsupported backends.
223    Unsupported(PhantomData<T>),
224}
225
226/// A mutable handle to the [`FunctionEnv`] in an [`BackendAsyncFunctionEnvMut`].
227#[cfg(feature = "experimental-async")]
228pub enum BackendAsyncFunctionEnvHandleMut<T> {
229    #[cfg(feature = "sys")]
230    /// The function environment handle for the `sys` runtime.
231    Sys(crate::backend::sys::function::env::AsyncFunctionEnvHandleMut<T>),
232    #[cfg(feature = "js")]
233    /// The function environment handle for the `js` runtime.
234    Js(crate::backend::js::function::env::AsyncFunctionEnvHandleMut<T>),
235    #[cfg(feature = "v8")]
236    /// Placeholder for unsupported backends.
237    Unsupported(PhantomData<T>),
238}
239
240#[cfg(feature = "experimental-async")]
241impl<T: 'static> BackendAsyncFunctionEnvMut<T> {
242    /// Waits for a store lock and returns a read-only handle to the
243    /// function environment.
244    pub async fn read(&self) -> BackendAsyncFunctionEnvHandle<T> {
245        match self {
246            #[cfg(feature = "sys")]
247            Self::Sys(f) => BackendAsyncFunctionEnvHandle::Sys(f.read().await),
248            #[cfg(feature = "js")]
249            Self::Js(f) => BackendAsyncFunctionEnvHandle::Js(f.read().await),
250            #[cfg(feature = "v8")]
251            _ => unsupported_async_backend(),
252        }
253    }
254
255    /// Waits for a store lock and returns a mutable handle to the
256    /// function environment.
257    pub async fn write(&self) -> BackendAsyncFunctionEnvHandleMut<T> {
258        match self {
259            #[cfg(feature = "sys")]
260            Self::Sys(f) => BackendAsyncFunctionEnvHandleMut::Sys(f.write().await),
261            #[cfg(feature = "js")]
262            Self::Js(f) => BackendAsyncFunctionEnvHandleMut::Js(f.write().await),
263            #[cfg(feature = "v8")]
264            _ => unsupported_async_backend(),
265        }
266    }
267
268    /// Borrows a new immutable reference
269    pub fn as_ref(&self) -> BackendFunctionEnv<T> {
270        match self {
271            #[cfg(feature = "sys")]
272            Self::Sys(f) => BackendFunctionEnv::Sys(f.as_ref()),
273            #[cfg(feature = "js")]
274            Self::Js(f) => BackendFunctionEnv::Js(f.as_ref()),
275            #[cfg(feature = "v8")]
276            _ => unsupported_async_backend(),
277        }
278    }
279
280    /// Borrows a new mutable reference
281    pub fn as_mut(&mut self) -> Self {
282        match self {
283            #[cfg(feature = "sys")]
284            Self::Sys(f) => Self::Sys(f.as_mut()),
285            #[cfg(feature = "js")]
286            Self::Js(f) => Self::Js(f.as_mut()),
287            #[cfg(feature = "v8")]
288            _ => unsupported_async_backend(),
289        }
290    }
291
292    /// Creates an [`AsStoreAsync`] from this [`BackendAsyncFunctionEnvMut`].
293    pub fn as_store_async(&self) -> impl AsStoreAsync + 'static {
294        match self {
295            #[cfg(feature = "sys")]
296            Self::Sys(f) => f.as_store_async(),
297            #[cfg(feature = "js")]
298            Self::Js(f) => f.as_store_async(),
299            #[cfg(all(feature = "sys", feature = "v8"))]
300            _ => unsupported_async_backend(),
301            #[cfg(all(not(feature = "sys"), feature = "v8"))]
302            _ => unsupported_async_backend::<crate::StoreAsync>(),
303        }
304    }
305}
306
307#[cfg(feature = "experimental-async")]
308impl<T: 'static> BackendAsyncFunctionEnvHandle<T> {
309    /// Returns a reference to the host state in this function environment.
310    pub fn data(&self) -> &T {
311        match self {
312            #[cfg(feature = "sys")]
313            Self::Sys(f) => f.data(),
314            #[cfg(feature = "js")]
315            Self::Js(f) => f.data(),
316            #[cfg(feature = "v8")]
317            _ => unsupported_async_backend(),
318        }
319    }
320
321    /// Returns both the host state and the attached StoreRef
322    pub fn data_and_store(&self) -> (&T, &impl AsStoreRef) {
323        match self {
324            #[cfg(feature = "sys")]
325            Self::Sys(f) => f.data_and_store(),
326            #[cfg(feature = "js")]
327            Self::Js(f) => f.data_and_store(),
328            #[cfg(all(feature = "sys", feature = "v8"))]
329            _ => unsupported_async_backend(),
330            #[cfg(all(not(feature = "sys"), feature = "v8"))]
331            _ => unsupported_async_backend::<(&T, &StoreRef)>(),
332        }
333    }
334}
335
336#[cfg(feature = "experimental-async")]
337impl<T: 'static> AsStoreRef for BackendAsyncFunctionEnvHandle<T> {
338    fn as_store_ref(&self) -> StoreRef<'_> {
339        match self {
340            #[cfg(feature = "sys")]
341            Self::Sys(f) => AsStoreRef::as_store_ref(f),
342            #[cfg(feature = "js")]
343            Self::Js(f) => AsStoreRef::as_store_ref(f),
344            #[cfg(feature = "v8")]
345            _ => unsupported_async_backend(),
346        }
347    }
348}
349
350#[cfg(feature = "experimental-async")]
351impl<T: 'static> BackendAsyncFunctionEnvHandleMut<T> {
352    /// Returns a mutable reference to the host state in this function environment.
353    pub fn data_mut(&mut self) -> &mut T {
354        match self {
355            #[cfg(feature = "sys")]
356            Self::Sys(f) => f.data_mut(),
357            #[cfg(feature = "js")]
358            Self::Js(f) => f.data_mut(),
359            #[cfg(feature = "v8")]
360            _ => unsupported_async_backend(),
361        }
362    }
363
364    /// Returns both the host state and the attached StoreMut
365    pub fn data_and_store_mut(&mut self) -> (&mut T, &mut impl AsStoreMut) {
366        match self {
367            #[cfg(feature = "sys")]
368            Self::Sys(f) => f.data_and_store_mut(),
369            #[cfg(feature = "js")]
370            Self::Js(f) => f.data_and_store_mut(),
371            #[cfg(all(feature = "sys", feature = "v8"))]
372            _ => unsupported_async_backend(),
373            #[cfg(all(not(feature = "sys"), feature = "v8"))]
374            _ => unsupported_async_backend::<(&mut T, &mut crate::StoreMut)>(),
375        }
376    }
377
378    /// Borrows a new [`BackendFunctionEnvMut`] from this
379    /// [`BackendAsyncFunctionEnvHandleMut`].
380    pub fn as_function_env_mut(&mut self) -> BackendFunctionEnvMut<'_, T> {
381        match self {
382            #[cfg(feature = "sys")]
383            Self::Sys(f) => BackendFunctionEnvMut::Sys(f.as_function_env_mut()),
384            #[cfg(feature = "js")]
385            Self::Js(f) => BackendFunctionEnvMut::Js(f.as_function_env_mut()),
386            #[cfg(feature = "v8")]
387            _ => unsupported_async_backend(),
388        }
389    }
390}
391
392#[cfg(feature = "experimental-async")]
393impl<T: 'static> AsStoreRef for BackendAsyncFunctionEnvHandleMut<T> {
394    fn as_store_ref(&self) -> StoreRef<'_> {
395        match self {
396            #[cfg(feature = "sys")]
397            Self::Sys(f) => AsStoreRef::as_store_ref(f),
398            #[cfg(feature = "js")]
399            Self::Js(f) => AsStoreRef::as_store_ref(f),
400            #[cfg(feature = "v8")]
401            _ => unsupported_async_backend(),
402        }
403    }
404}
405
406#[cfg(feature = "experimental-async")]
407impl<T: 'static> AsStoreMut for BackendAsyncFunctionEnvHandleMut<T> {
408    fn as_store_mut(&mut self) -> StoreMut<'_> {
409        match self {
410            #[cfg(feature = "sys")]
411            Self::Sys(f) => AsStoreMut::as_store_mut(f),
412            #[cfg(feature = "js")]
413            Self::Js(f) => AsStoreMut::as_store_mut(f),
414            #[cfg(feature = "v8")]
415            _ => unsupported_async_backend(),
416        }
417    }
418
419    fn objects_mut(&mut self) -> &mut crate::StoreObjects {
420        match self {
421            #[cfg(feature = "sys")]
422            Self::Sys(f) => AsStoreMut::objects_mut(f),
423            #[cfg(feature = "js")]
424            Self::Js(f) => AsStoreMut::objects_mut(f),
425            #[cfg(feature = "v8")]
426            _ => unsupported_async_backend(),
427        }
428    }
429}
430
431#[cfg(feature = "experimental-async")]
432fn unsupported_async_backend<T>() -> T {
433    panic!("async functions are only supported with the `sys` backend");
434}