linera_wasmer/
function_env.rs

1use std::{any::Any, fmt::Debug, marker::PhantomData};
2
3use crate::vm::VMFunctionEnvironment;
4
5use crate::store::{AsStoreMut, AsStoreRef, StoreHandle, StoreMut, StoreObjects, StoreRef};
6
7#[derive(Debug)]
8#[repr(transparent)]
9/// An opaque reference to a function environment.
10/// The function environment data is owned by the `Store`.
11pub struct FunctionEnv<T> {
12    pub(crate) handle: StoreHandle<VMFunctionEnvironment>,
13    marker: PhantomData<T>,
14}
15
16impl<T: Any> FunctionEnv<T> {
17    /// Make a new FunctionEnv
18    pub fn new(store: &mut impl AsStoreMut, value: T) -> Self {
19        Self {
20            handle: StoreHandle::new(
21                store.as_store_mut().objects_mut(),
22                VMFunctionEnvironment::new(value),
23            ),
24            marker: PhantomData,
25        }
26    }
27
28    /// Get the data as reference
29    pub fn as_ref<'a>(&self, store: &'a impl AsStoreRef) -> &'a T {
30        self.handle
31            .get(store.as_store_ref().objects())
32            .as_ref()
33            .downcast_ref::<T>()
34            .unwrap()
35    }
36
37    #[allow(dead_code)] // This function is only used in js
38    pub(crate) fn from_handle(handle: StoreHandle<VMFunctionEnvironment>) -> Self {
39        Self {
40            handle,
41            marker: PhantomData,
42        }
43    }
44
45    /// Get the data as mutable
46    pub fn as_mut<'a>(&self, store: &'a mut impl AsStoreMut) -> &'a mut T {
47        self.handle
48            .get_mut(store.objects_mut())
49            .as_mut()
50            .downcast_mut::<T>()
51            .unwrap()
52    }
53
54    /// Convert it into a `FunctionEnvMut`
55    pub fn into_mut(self, store: &mut impl AsStoreMut) -> FunctionEnvMut<T> {
56        FunctionEnvMut {
57            store_mut: store.as_store_mut(),
58            func_env: self,
59        }
60    }
61}
62
63impl<T> PartialEq for FunctionEnv<T> {
64    fn eq(&self, other: &Self) -> bool {
65        self.handle == other.handle
66    }
67}
68
69impl<T> Eq for FunctionEnv<T> {}
70
71impl<T> std::hash::Hash for FunctionEnv<T> {
72    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
73        self.handle.hash(state);
74        self.marker.hash(state);
75    }
76}
77
78impl<T> Clone for FunctionEnv<T> {
79    fn clone(&self) -> Self {
80        Self {
81            handle: self.handle.clone(),
82            marker: self.marker,
83        }
84    }
85}
86
87/// A temporary handle to a [`FunctionEnv`].
88pub struct FunctionEnvMut<'a, T: 'a> {
89    pub(crate) store_mut: StoreMut<'a>,
90    pub(crate) func_env: FunctionEnv<T>,
91}
92
93impl<'a, T: Debug + 'static> Debug for FunctionEnvMut<'a, T> {
94    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95        self.func_env.as_ref(&self.store_mut).fmt(f)
96    }
97}
98
99impl<T: 'static> FunctionEnvMut<'_, T> {
100    /// Returns a reference to the host state in this function environement.
101    pub fn data(&self) -> &T {
102        self.func_env.as_ref(&self.store_mut)
103    }
104
105    /// Returns a mutable- reference to the host state in this function environement.
106    pub fn data_mut(&mut self) -> &mut T {
107        self.func_env.as_mut(&mut self.store_mut)
108    }
109
110    /// Borrows a new immmutable reference
111    pub fn as_ref(&self) -> FunctionEnv<T> {
112        self.func_env.clone()
113    }
114
115    /// Borrows a new mutable reference
116    pub fn as_mut(&mut self) -> FunctionEnvMut<'_, T> {
117        FunctionEnvMut {
118            store_mut: self.store_mut.as_store_mut(),
119            func_env: self.func_env.clone(),
120        }
121    }
122
123    /// Borrows a new mutable reference of both the attached Store and host state
124    pub fn data_and_store_mut(&mut self) -> (&mut T, StoreMut) {
125        let data = self.func_env.as_mut(&mut self.store_mut) as *mut T;
126        // telling the borrow check to close his eyes here
127        // this is still relatively safe to do as func_env are
128        // stored in a specific vec of Store, separate from the other objects
129        // and not really directly accessible with the StoreMut
130        let data = unsafe { &mut *data };
131        (data, self.store_mut.as_store_mut())
132    }
133}
134
135impl<T> AsStoreRef for FunctionEnvMut<'_, T> {
136    fn as_store_ref(&self) -> StoreRef<'_> {
137        StoreRef {
138            inner: self.store_mut.inner,
139        }
140    }
141}
142
143impl<T> AsStoreMut for FunctionEnvMut<'_, T> {
144    fn as_store_mut(&mut self) -> StoreMut<'_> {
145        StoreMut {
146            inner: self.store_mut.inner,
147        }
148    }
149    #[inline]
150    fn objects_mut(&mut self) -> &mut StoreObjects {
151        &mut self.store_mut.inner.objects
152    }
153}