Skip to main content

wasmi_c_api/
global.rs

1use crate::{wasm_extern_t, wasm_globaltype_t, wasm_store_t, wasm_val_t};
2use alloc::boxed::Box;
3use core::{hint, mem::MaybeUninit};
4use wasmi::{Extern, Global};
5
6/// A Wasm global variable.
7///
8/// Wraps [`Global`].
9#[derive(Clone)]
10#[repr(transparent)]
11pub struct wasm_global_t {
12    inner: wasm_extern_t,
13}
14
15wasmi_c_api_macros::declare_ref!(wasm_global_t);
16
17impl wasm_global_t {
18    pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_global_t> {
19        match &e.which {
20            Extern::Global(_) => Some(unsafe { &*(e as *const _ as *const _) }),
21            _ => None,
22        }
23    }
24
25    pub(crate) fn try_from_mut(e: &mut wasm_extern_t) -> Option<&mut wasm_global_t> {
26        match &mut e.which {
27            Extern::Global(_) => Some(unsafe { &mut *(e as *mut _ as *mut _) }),
28            _ => None,
29        }
30    }
31
32    /// Returns the underlying [`Global`] of the [`wasm_global_t`].
33    fn global(&self) -> Global {
34        match self.inner.which {
35            Extern::Global(g) => g,
36            _ => unsafe { hint::unreachable_unchecked() },
37        }
38    }
39}
40
41/// Creates a new [`wasm_global_t`] from the given [`wasm_globaltype_t`] and [`wasm_val_t`].
42///
43/// Returns a `null` pointer if `ty` and `val` does not match.
44///
45/// Wraps [`Global::new`].
46///
47/// # Safety
48///
49/// It is the caller's responsibility not to alias the [`wasm_global_t`]
50/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
51#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
52#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
53pub unsafe extern "C" fn wasm_global_new(
54    store: &mut wasm_store_t,
55    ty: &wasm_globaltype_t,
56    val: &wasm_val_t,
57) -> Option<Box<wasm_global_t>> {
58    unsafe {
59        let val = val.to_val();
60        let ty = ty.ty().ty;
61        if val.ty() != ty.content() {
62            return None;
63        }
64        let global = Global::new(store.inner.context_mut(), val, ty.mutability());
65        Some(Box::new(wasm_global_t {
66            inner: wasm_extern_t {
67                store: store.inner.clone(),
68                which: global.into(),
69            },
70        }))
71    }
72}
73
74/// Returns the [`wasm_global_t`] as mutable reference to [`wasm_extern_t`].
75#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
76#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
77pub extern "C" fn wasm_global_as_extern(g: &mut wasm_global_t) -> &mut wasm_extern_t {
78    &mut g.inner
79}
80
81/// Returns the [`wasm_global_t`] as shared reference to [`wasm_extern_t`].
82#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
83#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
84pub extern "C" fn wasm_global_as_extern_const(g: &wasm_global_t) -> &wasm_extern_t {
85    &g.inner
86}
87
88/// Returns the [`wasm_globaltype_t`] of the [`wasm_global_t`].
89///
90/// Wraps [`Global::ty`].
91///
92/// # Safety
93///
94/// It is the caller's responsibility not to alias the [`wasm_global_t`]
95/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
96#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
97#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
98pub unsafe extern "C" fn wasm_global_type(g: &wasm_global_t) -> Box<wasm_globaltype_t> {
99    unsafe {
100        let globaltype = g.global().ty(g.inner.store.context());
101        Box::new(wasm_globaltype_t::new(globaltype))
102    }
103}
104
105/// Returns the current value of the [`wasm_global_t`].
106///
107/// Wraps [`Global::get`].
108///
109/// # Safety
110///
111/// It is the caller's responsibility not to alias the [`wasm_global_t`]
112/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
113#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
114#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
115pub unsafe extern "C" fn wasm_global_get(g: &mut wasm_global_t, out: &mut MaybeUninit<wasm_val_t>) {
116    unsafe {
117        let global = g.global();
118        crate::initialize(
119            out,
120            wasm_val_t::from(global.get(g.inner.store.context_mut())),
121        );
122    }
123}
124
125/// Sets the current value of the [`wasm_global_t`].
126///
127/// Wraps [`Global::set`].
128///
129/// # Safety
130///
131/// - It is the caller's responsibility that `val` matches the type of `g`.
132/// - It is the caller's responsibility not to alias the [`wasm_global_t`]
133///   with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
134#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
135#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
136pub unsafe extern "C" fn wasm_global_set(g: &mut wasm_global_t, val: &wasm_val_t) {
137    unsafe {
138        let global = g.global();
139        drop(global.set(g.inner.store.context_mut(), val.to_val()));
140    }
141}