wasmedge_sys/instance/
global.rs1use crate::{ffi, WasmEdgeResult, WasmValue};
7use wasmedge_types::{
8 error::{GlobalError, WasmEdgeError},
9 Mutability, ValType,
10};
11
12#[derive(Debug)]
14pub struct Global {
15 pub(crate) inner: InnerGlobal,
16}
17impl Global {
18 pub fn create(ty: &wasmedge_types::GlobalType, val: WasmValue) -> WasmEdgeResult<Self> {
27 let ty: GlobalType = ty.into();
28 let ctx = unsafe { ffi::WasmEdge_GlobalInstanceCreate(ty.inner.0, val.as_raw()) };
29
30 if ctx.is_null() {
31 Err(Box::new(WasmEdgeError::Global(GlobalError::Create)))
32 } else {
33 Ok(Self {
34 inner: InnerGlobal(ctx),
35 })
36 }
37 }
38
39 pub fn ty(&self) -> WasmEdgeResult<wasmedge_types::GlobalType> {
46 let ty_ctx = unsafe { ffi::WasmEdge_GlobalInstanceGetGlobalType(self.inner.0) };
47 match ty_ctx.is_null() {
48 true => Err(Box::new(WasmEdgeError::Global(GlobalError::Type))),
49 false => {
50 let ty = std::mem::ManuallyDrop::new(GlobalType {
51 inner: InnerGlobalType(ty_ctx as *mut _),
52 });
53 Ok((&*ty).into())
54 }
55 }
56 }
57
58 pub fn get_value(&self) -> WasmValue {
60 let val = unsafe { ffi::WasmEdge_GlobalInstanceGetValue(self.inner.0) };
61 val.into()
62 }
63
64 pub fn set_value(&mut self, val: WasmValue) -> WasmEdgeResult<()> {
77 let ty = self.ty()?;
78 if ty.mutability() == Mutability::Const {
79 return Err(Box::new(WasmEdgeError::Global(GlobalError::ModifyConst)));
80 }
81 if ty.value_ty() != val.ty() {
82 return Err(Box::new(WasmEdgeError::Global(
83 GlobalError::UnmatchedValType,
84 )));
85 }
86 unsafe {
87 let result = ffi::WasmEdge_GlobalInstanceSetValue(self.inner.0, val.as_raw());
88 crate::utils::check(result)?;
89 }
90 Ok(())
91 }
92
93 pub unsafe fn as_ptr(&self) -> *const ffi::WasmEdge_GlobalInstanceContext {
97 self.inner.0 as *const _
98 }
99
100 pub unsafe fn from_raw(ptr: *mut ffi::WasmEdge_GlobalInstanceContext) -> Self {
104 Self {
105 inner: InnerGlobal(ptr),
106 }
107 }
108}
109impl Drop for Global {
110 fn drop(&mut self) {
111 unsafe { ffi::WasmEdge_GlobalInstanceDelete(self.inner.0) };
112 }
113}
114
115#[derive(Debug)]
116pub(crate) struct InnerGlobal(pub(crate) *mut ffi::WasmEdge_GlobalInstanceContext);
117unsafe impl Send for InnerGlobal {}
118unsafe impl Sync for InnerGlobal {}
119
120#[derive(Debug)]
124pub(crate) struct GlobalType {
125 pub(crate) inner: InnerGlobalType,
126}
127impl GlobalType {
128 pub(crate) fn create(val_ty: ValType, mutable: Mutability) -> WasmEdgeResult<Self> {
140 let ctx = unsafe { ffi::WasmEdge_GlobalTypeCreate(val_ty.into(), mutable.into()) };
141 match ctx.is_null() {
142 true => Err(Box::new(WasmEdgeError::GlobalTypeCreate)),
143 false => Ok(Self {
144 inner: InnerGlobalType(ctx),
145 }),
146 }
147 }
148
149 pub(crate) fn value_type(&self) -> ValType {
151 let val = unsafe { ffi::WasmEdge_GlobalTypeGetValType(self.inner.0 as *const _) };
152 val.into()
153 }
154
155 pub(crate) fn mutability(&self) -> Mutability {
157 let val = unsafe { ffi::WasmEdge_GlobalTypeGetMutability(self.inner.0) };
158 val.into()
159 }
160}
161impl Drop for GlobalType {
162 fn drop(&mut self) {
163 unsafe { ffi::WasmEdge_GlobalTypeDelete(self.inner.0) };
164 }
165}
166impl From<&wasmedge_types::GlobalType> for GlobalType {
167 fn from(ty: &wasmedge_types::GlobalType) -> Self {
168 GlobalType::create(ty.value_ty(), ty.mutability()).expect(
169 "[wasmedge-sys] Failed to convert wasmedge_types::GlobalType into wasmedge_sys::GlobalType.",
170 )
171 }
172}
173impl From<wasmedge_types::GlobalType> for GlobalType {
174 fn from(ty: wasmedge_types::GlobalType) -> Self {
175 (&ty).into()
176 }
177}
178impl From<&GlobalType> for wasmedge_types::GlobalType {
179 fn from(ty: &GlobalType) -> Self {
180 wasmedge_types::GlobalType::new(ty.value_type(), ty.mutability())
181 }
182}
183
184#[derive(Debug)]
185pub(crate) struct InnerGlobalType(pub(crate) *mut ffi::WasmEdge_GlobalTypeContext);
186unsafe impl Send for InnerGlobalType {}
187unsafe impl Sync for InnerGlobalType {}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192 use std::thread;
193 use wasmedge_types::{Mutability, ValType};
194
195 #[test]
196 #[allow(clippy::assertions_on_result_states)]
197 fn test_global_type() {
198 let result = GlobalType::create(ValType::I32, Mutability::Const);
200 assert!(result.is_ok());
201 let global_ty = result.unwrap();
202 assert!(!global_ty.inner.0.is_null());
203
204 assert_eq!(global_ty.value_type(), ValType::I32);
206 assert_eq!(global_ty.mutability(), Mutability::Const);
208 }
209
210 #[test]
211 #[allow(clippy::assertions_on_result_states)]
212 fn test_global_const_i32() {
213 let ty = wasmedge_types::GlobalType::new(ValType::I32, Mutability::Const);
215
216 let result = Global::create(&ty, WasmValue::from_i32(99));
218 assert!(result.is_ok());
219 let mut global_const = result.unwrap();
220
221 assert_eq!(global_const.get_value().to_i32(), 99);
223 let result = global_const.set_value(WasmValue::from_i32(0));
224 assert!(result.is_err());
225
226 let result = global_const.ty();
228 assert!(result.is_ok());
229 let ty = result.unwrap();
230 assert_eq!(ty.value_ty(), ValType::I32);
231 assert_eq!(ty.mutability(), Mutability::Const);
232 }
233
234 #[test]
235 #[allow(clippy::assertions_on_result_states)]
236 fn test_global_var_f32() {
237 let ty = wasmedge_types::GlobalType::new(ValType::F32, Mutability::Var);
239
240 let result = Global::create(&ty, WasmValue::from_f32(13.14));
242 assert!(result.is_ok());
243 let mut global_var = result.unwrap();
244
245 assert_eq!(global_var.get_value().to_f32(), 13.14);
247 let result = global_var.set_value(WasmValue::from_f32(1.314));
248 assert!(result.is_ok());
249 assert_eq!(global_var.get_value().to_f32(), 1.314);
250
251 let result = global_var.ty();
253 assert!(result.is_ok());
254 let ty = result.unwrap();
255 assert_eq!(ty.value_ty(), ValType::F32);
256 assert_eq!(ty.mutability(), Mutability::Var);
257 }
258
259 #[test]
260 #[allow(clippy::assertions_on_result_states)]
261 fn test_global_conflict() {
262 {
263 let ty = wasmedge_types::GlobalType::new(ValType::F32, Mutability::Var);
265
266 let result = Global::create(&ty, WasmValue::from_i32(520));
268 assert!(result.is_err());
269 }
270
271 {
272 let ty = wasmedge_types::GlobalType::new(ValType::F32, Mutability::Var);
274
275 let result = Global::create(&ty, WasmValue::from_f32(13.14));
277 assert!(result.is_ok());
278 let mut global_var = result.unwrap();
279
280 let result = global_var.set_value(WasmValue::from_i32(1314));
282 assert!(result.is_err());
283 assert_eq!(global_var.get_value().to_f32(), 13.14);
284
285 let result = global_var.set_value(WasmValue::from_f32(1.314));
287 assert!(result.is_ok());
288 assert_eq!(global_var.get_value().to_f32(), 1.314);
289 }
290 }
291
292 #[test]
293 fn test_global_send() {
294 {
295 let global_ty = wasmedge_types::GlobalType::new(ValType::I32, Mutability::Const);
297
298 let result = Global::create(&global_ty, WasmValue::from_i32(5));
300 assert!(result.is_ok());
301 let global = result.unwrap();
302
303 let handle = thread::spawn(move || {
304 assert_eq!(global.get_value().to_i32(), 5);
306 });
307
308 handle.join().unwrap()
309 }
310 }
311
312 #[test]
313 fn test_global_sync() {
314 let global_ty = wasmedge_types::GlobalType::new(ValType::I32, Mutability::Const);
316
317 let result = Global::create(&global_ty, WasmValue::from_i32(5));
319 assert!(result.is_ok());
320 let global = result.unwrap();
321 let global = &global;
322
323 std::thread::scope(|s| {
324 let _ = s
325 .spawn(move || {
326 assert_eq!(global.get_value().to_i32(), 5);
327 })
328 .join();
329 })
330 }
331}