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}