linera_wasmer/externals/
global.rs

1use crate::exports::{ExportError, Exportable};
2use crate::store::{AsStoreMut, AsStoreRef};
3use crate::value::Value;
4use crate::vm::VMExtern;
5use crate::vm::VMExternGlobal;
6use crate::Extern;
7use crate::GlobalType;
8use crate::Mutability;
9use crate::RuntimeError;
10
11#[cfg(feature = "js")]
12use crate::js::externals::global as global_impl;
13#[cfg(feature = "jsc")]
14use crate::jsc::externals::global as global_impl;
15#[cfg(feature = "sys")]
16use crate::sys::externals::global as global_impl;
17
18/// A WebAssembly `global` instance.
19///
20/// A global instance is the runtime representation of a global variable.
21/// It consists of an individual value and a flag indicating whether it is mutable.
22///
23/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#global-instances>
24#[derive(Debug, Clone, PartialEq)]
25#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
26pub struct Global(pub(crate) global_impl::Global);
27
28impl Global {
29    /// Create a new `Global` with the initial value [`Value`].
30    ///
31    /// # Example
32    ///
33    /// ```
34    /// # use wasmer::{Global, Mutability, Store, Value};
35    /// # let mut store = Store::default();
36    /// #
37    /// let g = Global::new(&mut store, Value::I32(1));
38    ///
39    /// assert_eq!(g.get(&mut store), Value::I32(1));
40    /// assert_eq!(g.ty(&mut store).mutability, Mutability::Const);
41    /// ```
42    pub fn new(store: &mut impl AsStoreMut, val: Value) -> Self {
43        Self::from_value(store, val, Mutability::Const).unwrap()
44    }
45
46    /// Create a mutable `Global` with the initial value [`Value`].
47    ///
48    /// # Example
49    ///
50    /// ```
51    /// # use wasmer::{Global, Mutability, Store, Value};
52    /// # let mut store = Store::default();
53    /// #
54    /// let g = Global::new_mut(&mut store, Value::I32(1));
55    ///
56    /// assert_eq!(g.get(&mut store), Value::I32(1));
57    /// assert_eq!(g.ty(&mut store).mutability, Mutability::Var);
58    /// ```
59    pub fn new_mut(store: &mut impl AsStoreMut, val: Value) -> Self {
60        Self::from_value(store, val, Mutability::Var).unwrap()
61    }
62
63    /// Create a `Global` with the initial value [`Value`] and the provided [`Mutability`].
64    fn from_value(
65        store: &mut impl AsStoreMut,
66        val: Value,
67        mutability: Mutability,
68    ) -> Result<Self, RuntimeError> {
69        Ok(Self(global_impl::Global::from_value(
70            store, val, mutability,
71        )?))
72    }
73
74    /// Returns the [`GlobalType`] of the `Global`.
75    ///
76    /// # Example
77    ///
78    /// ```
79    /// # use wasmer::{Global, Mutability, Store, Type, Value, GlobalType};
80    /// # let mut store = Store::default();
81    /// #
82    /// let c = Global::new(&mut store, Value::I32(1));
83    /// let v = Global::new_mut(&mut store, Value::I64(1));
84    ///
85    /// assert_eq!(c.ty(&mut store), GlobalType::new(Type::I32, Mutability::Const));
86    /// assert_eq!(v.ty(&mut store), GlobalType::new(Type::I64, Mutability::Var));
87    /// ```
88    pub fn ty(&self, store: &impl AsStoreRef) -> GlobalType {
89        self.0.ty(store)
90    }
91
92    /// Retrieves the current value [`Value`] that the Global has.
93    ///
94    /// # Example
95    ///
96    /// ```
97    /// # use wasmer::{Global, Store, Value};
98    /// # let mut store = Store::default();
99    /// #
100    /// let g = Global::new(&mut store, Value::I32(1));
101    ///
102    /// assert_eq!(g.get(&mut store), Value::I32(1));
103    /// ```
104    pub fn get(&self, store: &mut impl AsStoreMut) -> Value {
105        self.0.get(store)
106    }
107
108    /// Sets a custom value [`Value`] to the runtime Global.
109    ///
110    /// # Example
111    ///
112    /// ```
113    /// # use wasmer::{Global, Store, Value};
114    /// # let mut store = Store::default();
115    /// #
116    /// let g = Global::new_mut(&mut store, Value::I32(1));
117    ///
118    /// assert_eq!(g.get(&mut store), Value::I32(1));
119    ///
120    /// g.set(&mut store, Value::I32(2));
121    ///
122    /// assert_eq!(g.get(&mut store), Value::I32(2));
123    /// ```
124    ///
125    /// # Errors
126    ///
127    /// Trying to mutate a immutable global will raise an error:
128    ///
129    /// ```should_panic
130    /// # use wasmer::{Global, Store, Value};
131    /// # let mut store = Store::default();
132    /// #
133    /// let g = Global::new(&mut store, Value::I32(1));
134    ///
135    /// g.set(&mut store, Value::I32(2)).unwrap();
136    /// ```
137    ///
138    /// Trying to set a value of a incompatible type will raise an error:
139    ///
140    /// ```should_panic
141    /// # use wasmer::{Global, Store, Value};
142    /// # let mut store = Store::default();
143    /// #
144    /// let g = Global::new(&mut store, Value::I32(1));
145    ///
146    /// // This results in an error: `RuntimeError`.
147    /// g.set(&mut store, Value::I64(2)).unwrap();
148    /// ```
149    pub fn set(&self, store: &mut impl AsStoreMut, val: Value) -> Result<(), RuntimeError> {
150        self.0.set(store, val)
151    }
152
153    pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, vm_extern: VMExternGlobal) -> Self {
154        Self(global_impl::Global::from_vm_extern(store, vm_extern))
155    }
156
157    /// Checks whether this `Global` can be used with the given context.
158    pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
159        self.0.is_from_store(store)
160    }
161
162    pub(crate) fn to_vm_extern(&self) -> VMExtern {
163        self.0.to_vm_extern()
164    }
165}
166
167impl std::cmp::Eq for Global {}
168
169impl<'a> Exportable<'a> for Global {
170    fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
171        match _extern {
172            Extern::Global(global) => Ok(global),
173            _ => Err(ExportError::IncompatibleType),
174        }
175    }
176}