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}