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