wasmer/entities/global/
mod.rs

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