wasmer/backend/sys/entities/function/
env.rs1use std::{any::Any, fmt::Debug, marker::PhantomData};
2
3#[cfg(feature = "experimental-async")]
4use crate::{AsStoreAsync, StoreAsync, StoreAsyncReadLock, StoreAsyncWriteLock};
5use crate::{
6 Store, StoreContext, StoreInner, StoreMut, StorePtrWrapper,
7 store::{AsStoreMut, AsStoreRef, StoreRef},
8};
9
10use wasmer_vm::{StoreHandle, StoreId, StoreObject, StoreObjects, VMFunctionEnvironment};
11
12#[derive(Debug)]
13#[repr(transparent)]
14pub struct FunctionEnv<T> {
17 pub(crate) handle: StoreHandle<VMFunctionEnvironment>,
18 marker: PhantomData<T>,
19}
20
21impl<T: Any + Send + 'static + Sized> FunctionEnv<T> {
22 pub fn new(store: &mut impl AsStoreMut, value: T) -> Self {
24 Self {
25 handle: StoreHandle::new(
26 store.as_store_mut().objects_mut().as_sys_mut(),
27 VMFunctionEnvironment::new(value),
28 ),
29 marker: PhantomData,
30 }
31 }
32
33 #[allow(dead_code)] pub(crate) fn from_handle(handle: StoreHandle<VMFunctionEnvironment>) -> Self {
35 Self {
36 handle,
37 marker: PhantomData,
38 }
39 }
40
41 pub fn into_mut(self, store: &mut impl AsStoreMut) -> FunctionEnvMut<'_, T> {
43 FunctionEnvMut {
44 store_mut: store.as_store_mut(),
45 func_env: self,
46 }
47 }
48}
49
50impl<T: Any + 'static + Sized> FunctionEnv<T> {
51 pub fn as_ref<'a>(&self, store: &'a impl AsStoreRef) -> &'a T {
53 self.handle
54 .get(store.as_store_ref().objects().as_sys())
55 .as_ref()
56 .downcast_ref::<T>()
57 .unwrap()
58 }
59
60 pub fn as_mut<'a>(&self, store: &'a mut impl AsStoreMut) -> &'a mut T {
62 self.handle
63 .get_mut(store.objects_mut().as_sys_mut())
64 .as_mut()
65 .downcast_mut::<T>()
66 .unwrap()
67 }
68}
69
70impl<T> crate::FunctionEnv<T> {
71 pub fn into_sys(self) -> FunctionEnv<T> {
73 match self.0 {
74 crate::BackendFunctionEnv::Sys(s) => s,
75 _ => panic!("Not a `sys` function env!"),
76 }
77 }
78
79 pub fn as_sys(&self) -> &FunctionEnv<T> {
81 match self.0 {
82 crate::BackendFunctionEnv::Sys(ref s) => s,
83 _ => panic!("Not a `sys` function env!"),
84 }
85 }
86
87 pub fn as_sys_mut(&mut self) -> &mut FunctionEnv<T> {
89 match self.0 {
90 crate::BackendFunctionEnv::Sys(ref mut s) => s,
91 _ => panic!("Not a `sys` function env!"),
92 }
93 }
94}
95
96impl<T> PartialEq for FunctionEnv<T> {
97 fn eq(&self, other: &Self) -> bool {
98 self.handle == other.handle
99 }
100}
101
102impl<T> Eq for FunctionEnv<T> {}
103
104impl<T> std::hash::Hash for FunctionEnv<T> {
105 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
106 self.handle.hash(state);
107 self.marker.hash(state);
108 }
109}
110
111impl<T> Clone for FunctionEnv<T> {
112 fn clone(&self) -> Self {
113 Self {
114 handle: self.handle.clone(),
115 marker: self.marker,
116 }
117 }
118}
119
120pub struct FunctionEnvMut<'a, T: 'a> {
122 pub(crate) store_mut: StoreMut<'a>,
123 pub(crate) func_env: FunctionEnv<T>,
124}
125
126impl<T> Debug for FunctionEnvMut<'_, T>
127where
128 T: Send + Debug + 'static,
129{
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 self.func_env.as_ref(&self.store_mut).fmt(f)
132 }
133}
134
135impl<T: Send + 'static> FunctionEnvMut<'_, T> {
136 pub fn data(&self) -> &T {
138 self.func_env.as_ref(&self.store_mut)
139 }
140
141 pub fn data_mut(&mut self) -> &mut T {
143 self.func_env.as_mut(&mut self.store_mut)
144 }
145
146 pub fn as_ref(&self) -> FunctionEnv<T> {
148 self.func_env.clone()
149 }
150
151 pub fn as_mut(&mut self) -> FunctionEnvMut<'_, T> {
153 FunctionEnvMut {
154 store_mut: self.store_mut.as_store_mut(),
155 func_env: self.func_env.clone(),
156 }
157 }
158
159 pub fn data_and_store_mut(&mut self) -> (&mut T, StoreMut<'_>) {
161 let data = self.func_env.as_mut(&mut self.store_mut) as *mut T;
162 let data = unsafe { &mut *data };
167 (data, self.store_mut.as_store_mut())
168 }
169
170 #[cfg(feature = "experimental-async")]
176 pub fn as_store_async(&self) -> Option<impl AsStoreAsync + 'static> {
177 self.store_mut.as_store_async()
178 }
179}
180
181impl<T> AsStoreRef for FunctionEnvMut<'_, T> {
182 fn as_store_ref(&self) -> StoreRef<'_> {
183 StoreRef {
184 inner: self.store_mut.inner,
185 }
186 }
187}
188
189impl<T> AsStoreMut for FunctionEnvMut<'_, T> {
190 fn as_store_mut(&mut self) -> StoreMut<'_> {
191 StoreMut {
192 inner: self.store_mut.inner,
193 }
194 }
195
196 fn objects_mut(&mut self) -> &mut crate::StoreObjects {
197 self.store_mut.objects_mut()
198 }
199}
200
201impl<'a, T> From<FunctionEnvMut<'a, T>> for crate::FunctionEnvMut<'a, T> {
202 fn from(value: FunctionEnvMut<'a, T>) -> Self {
203 crate::FunctionEnvMut(crate::BackendFunctionEnvMut::Sys(value))
204 }
205}
206
207impl<T> From<FunctionEnv<T>> for crate::FunctionEnv<T> {
208 fn from(value: FunctionEnv<T>) -> Self {
209 Self(crate::BackendFunctionEnv::Sys(value))
210 }
211}
212
213#[cfg(feature = "experimental-async")]
216pub struct AsyncFunctionEnvMut<T> {
217 pub(crate) store: AsyncFunctionEnvMutStore,
218 pub(crate) func_env: FunctionEnv<T>,
219}
220
221#[cfg(feature = "experimental-async")]
226pub(crate) enum AsyncFunctionEnvMutStore {
227 Async(StoreAsync),
228 Sync(StorePtrWrapper),
229}
230
231#[cfg(feature = "experimental-async")]
233pub struct AsyncFunctionEnvHandle<T> {
234 read_lock: StoreAsyncReadLock,
235 pub(crate) func_env: FunctionEnv<T>,
236}
237
238#[cfg(feature = "experimental-async")]
240pub struct AsyncFunctionEnvHandleMut<T> {
241 write_lock: StoreAsyncWriteLock,
242 pub(crate) func_env: FunctionEnv<T>,
243}
244
245#[cfg(feature = "experimental-async")]
246impl<T> Debug for AsyncFunctionEnvMut<T>
247where
248 T: Send + Debug + 'static,
249{
250 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
251 match &self.store {
252 AsyncFunctionEnvMutStore::Sync(ptr) => self.func_env.as_ref(&ptr.as_ref()).fmt(f),
253 AsyncFunctionEnvMutStore::Async(store) => match store.inner.try_read() {
254 Some(read_lock) => self.func_env.as_ref(&read_lock).fmt(f),
255 None => write!(f, "AsyncFunctionEnvMut {{ <STORE LOCKED> }}"),
256 },
257 }
258 }
259}
260
261#[cfg(feature = "experimental-async")]
262impl<T: 'static> AsyncFunctionEnvMut<T> {
263 pub(crate) fn store_id(&self) -> StoreId {
264 match &self.store {
265 AsyncFunctionEnvMutStore::Sync(ptr) => ptr.as_ref().objects().id(),
266 AsyncFunctionEnvMutStore::Async(store) => store.id,
267 }
268 }
269
270 pub async fn read(&self) -> AsyncFunctionEnvHandle<T> {
273 let read_lock = match &self.store {
274 AsyncFunctionEnvMutStore::Async(store) => store.read_lock().await,
275
276 AsyncFunctionEnvMutStore::Sync(_) => futures::future::pending().await,
278 };
279
280 AsyncFunctionEnvHandle {
281 read_lock,
282 func_env: self.func_env.clone(),
283 }
284 }
285
286 pub async fn write(&self) -> AsyncFunctionEnvHandleMut<T> {
289 let write_lock = match &self.store {
290 AsyncFunctionEnvMutStore::Async(store) => store.write_lock().await,
291
292 AsyncFunctionEnvMutStore::Sync(_) => futures::future::pending().await,
294 };
295
296 AsyncFunctionEnvHandleMut {
297 write_lock,
298 func_env: self.func_env.clone(),
299 }
300 }
301
302 pub fn as_ref(&self) -> FunctionEnv<T> {
304 self.func_env.clone()
305 }
306
307 pub fn as_mut(&mut self) -> Self {
309 self.clone()
310 }
311
312 pub fn as_store_async(&self) -> impl AsStoreAsync + 'static {
314 match &self.store {
315 AsyncFunctionEnvMutStore::Sync(_) => {
316 panic!("Cannot build a StoreAsync within a sync context")
317 }
318 AsyncFunctionEnvMutStore::Async(store) => StoreAsync {
319 id: store.id,
320 inner: store.inner.clone(),
321 },
322 }
323 }
324}
325
326#[cfg(feature = "experimental-async")]
327impl<T> Clone for AsyncFunctionEnvMut<T> {
328 fn clone(&self) -> Self {
329 Self {
330 store: self.store.clone(),
331 func_env: self.func_env.clone(),
332 }
333 }
334}
335
336#[cfg(feature = "experimental-async")]
337impl Clone for AsyncFunctionEnvMutStore {
338 fn clone(&self) -> Self {
339 match self {
340 Self::Async(store) => Self::Async(StoreAsync {
341 id: store.id,
342 inner: store.inner.clone(),
343 }),
344 Self::Sync(ptr) => Self::Sync(ptr.clone()),
345 }
346 }
347}
348
349#[cfg(feature = "experimental-async")]
350impl<T: 'static> AsyncFunctionEnvHandle<T> {
351 pub fn data(&self) -> &T {
353 self.func_env.as_ref(&self.read_lock)
354 }
355
356 pub fn data_and_store(&self) -> (&T, &impl AsStoreRef) {
358 (self.data(), &self.read_lock)
359 }
360}
361
362#[cfg(feature = "experimental-async")]
363impl<T: 'static> AsStoreRef for AsyncFunctionEnvHandle<T> {
364 fn as_store_ref(&self) -> StoreRef<'_> {
365 AsStoreRef::as_store_ref(&self.read_lock)
366 }
367}
368
369#[cfg(feature = "experimental-async")]
370impl<T: 'static> AsyncFunctionEnvHandleMut<T> {
371 pub fn data_mut(&mut self) -> &mut T {
373 self.func_env.as_mut(&mut self.write_lock)
374 }
375
376 pub fn data_and_store_mut(&mut self) -> (&mut T, &mut impl AsStoreMut) {
378 let data = self.data_mut() as *mut T;
379 let data = unsafe { &mut *data };
385 (data, &mut self.write_lock)
386 }
387
388 pub fn as_function_env_mut(&mut self) -> FunctionEnvMut<'_, T> {
390 FunctionEnvMut {
391 store_mut: self.write_lock.as_store_mut(),
392 func_env: self.func_env.clone(),
393 }
394 }
395}
396
397#[cfg(feature = "experimental-async")]
398impl<T: 'static> AsStoreRef for AsyncFunctionEnvHandleMut<T> {
399 fn as_store_ref(&self) -> StoreRef<'_> {
400 AsStoreRef::as_store_ref(&self.write_lock)
401 }
402}
403
404#[cfg(feature = "experimental-async")]
405impl<T: 'static> AsStoreMut for AsyncFunctionEnvHandleMut<T> {
406 fn as_store_mut(&mut self) -> StoreMut<'_> {
407 AsStoreMut::as_store_mut(&mut self.write_lock)
408 }
409
410 fn objects_mut(&mut self) -> &mut crate::StoreObjects {
411 AsStoreMut::objects_mut(&mut self.write_lock)
412 }
413}