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}