Skip to main content

wasmi_c_api/
table.rs

1use crate::{wasm_extern_t, wasm_ref_t, wasm_store_t, wasm_tabletype_t};
2use alloc::boxed::Box;
3use core::hint;
4use wasmi::{Extern, ExternRef, Func, Nullable, Ref, Table, TableType};
5
6/// A Wasm table.
7///
8/// Wraps [`Table`].
9#[derive(Clone)]
10#[repr(transparent)]
11pub struct wasm_table_t {
12    inner: wasm_extern_t,
13}
14
15wasmi_c_api_macros::declare_ref!(wasm_table_t);
16
17/// Type specifying the number of cells of a Wasm table.
18pub type wasm_table_size_t = u32;
19
20impl wasm_table_t {
21    pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_table_t> {
22        match &e.which {
23            Extern::Table(_) => Some(unsafe { &*(e as *const _ as *const _) }),
24            _ => None,
25        }
26    }
27
28    pub(crate) fn try_from_mut(e: &mut wasm_extern_t) -> Option<&mut wasm_table_t> {
29        match &mut e.which {
30            Extern::Table(_) => Some(unsafe { &mut *(e as *mut _ as *mut _) }),
31            _ => None,
32        }
33    }
34
35    /// Returns the underlying [`Table`] of the [`wasm_table_t`].
36    fn table(&self) -> Table {
37        match self.inner.which {
38            Extern::Table(t) => t,
39            _ => unsafe { hint::unreachable_unchecked() },
40        }
41    }
42}
43
44/// Returns the [`Ref`] respective to the optional [`wasm_ref_t`].
45///
46/// Returns a `null` [`Ref`] if [`wasm_ref_t`] is `None`.
47fn option_wasm_ref_t_to_ref(r: Option<&wasm_ref_t>, table_ty: &TableType) -> Ref {
48    r.map(|r| r.inner)
49        .unwrap_or_else(|| match table_ty.element() {
50            wasmi::RefType::Func => Ref::Func(<Nullable<Func>>::Null),
51            wasmi::RefType::Extern => Ref::Extern(<Nullable<ExternRef>>::Null),
52        })
53}
54
55/// Creates a new [`wasm_table_t`] from the given [`wasm_tabletype_t`].
56///
57/// Wraps [`Table::new`].
58///
59/// # Safety
60///
61/// It is the caller's responsibility not to alias the [`wasm_table_t`]
62/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
63#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
64#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
65pub unsafe extern "C" fn wasm_table_new(
66    store: &mut wasm_store_t,
67    tt: &wasm_tabletype_t,
68    init: Option<&wasm_ref_t>,
69) -> Option<Box<wasm_table_t>> {
70    unsafe {
71        let tt = tt.ty().ty;
72        let init = option_wasm_ref_t_to_ref(init, &tt);
73        let table = Table::new(store.inner.context_mut(), tt, init).ok()?;
74        Some(Box::new(wasm_table_t {
75            inner: wasm_extern_t {
76                store: store.inner.clone(),
77                which: table.into(),
78            },
79        }))
80    }
81}
82
83/// Returns the [`wasm_tabletype_t`] of the [`wasm_table_t`].
84///
85/// Wraps [`Table::ty`].
86///
87/// # Safety
88///
89/// It is the caller's responsibility not to alias the [`wasm_table_t`]
90/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
91#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
92#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
93pub unsafe extern "C" fn wasm_table_type(t: &wasm_table_t) -> Box<wasm_tabletype_t> {
94    unsafe {
95        let table = t.table();
96        let store = t.inner.store.context();
97        Box::new(wasm_tabletype_t::new(table.ty(store)))
98    }
99}
100
101/// Returns the element at `index` of [`wasm_table_t`] `t`.
102///
103/// Wraps [`Table::get`].
104///
105/// # Safety
106///
107/// It is the caller's responsibility not to alias the [`wasm_table_t`]
108/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
109#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
110#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
111pub unsafe extern "C" fn wasm_table_get(
112    t: &mut wasm_table_t,
113    index: wasm_table_size_t,
114) -> Option<Box<wasm_ref_t>> {
115    unsafe {
116        let table = t.table();
117        let value = table.get(t.inner.store.context_mut(), u64::from(index))?;
118        wasm_ref_t::new(value)
119    }
120}
121
122/// Sets the value of the element at `index` of [`wasm_table_t`] to `new_value`.
123///
124/// Wraps [`Table::set`].
125///
126/// # Safety
127///
128/// It is the caller's responsibility not to alias the [`wasm_table_t`]
129/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
130#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
131#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
132pub unsafe extern "C" fn wasm_table_set(
133    t: &mut wasm_table_t,
134    index: wasm_table_size_t,
135    new_value: Option<&wasm_ref_t>,
136) -> bool {
137    unsafe {
138        let table = t.table();
139        let new_value = option_wasm_ref_t_to_ref(new_value, &table.ty(t.inner.store.context()));
140        table
141            .set(t.inner.store.context_mut(), u64::from(index), new_value)
142            .is_ok()
143    }
144}
145
146/// Returns the number of cells of the [`wasm_table_t`].
147///
148/// Wraps [`Table::size`].
149///
150/// # Safety
151///
152/// It is the caller's responsibility not to alias the [`wasm_table_t`]
153/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
154#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
155#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
156pub unsafe extern "C" fn wasm_table_size(t: &wasm_table_t) -> wasm_table_size_t {
157    unsafe {
158        let table = t.table();
159        let store = t.inner.store.context();
160        let size = table.size(store);
161        u32::try_from(size).unwrap()
162    }
163}
164/// Grows the number of cells of the [`wasm_table_t`] by `delta`.
165///
166/// Returns `true` if the operation was successful.
167///
168/// Wraps [`Table::grow`].
169///
170/// # Safety
171///
172/// It is the caller's responsibility not to alias the [`wasm_table_t`]
173/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
174#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
175#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
176pub unsafe extern "C" fn wasm_table_grow(
177    t: &mut wasm_table_t,
178    delta: wasm_table_size_t,
179    init: Option<&wasm_ref_t>,
180) -> bool {
181    unsafe {
182        let table = t.table();
183        let init = option_wasm_ref_t_to_ref(init, &table.ty(t.inner.store.context()));
184        table
185            .grow(t.inner.store.context_mut(), u64::from(delta), init)
186            .is_ok()
187    }
188}
189
190/// Returns the [`wasm_table_t`] as mutable reference to [`wasm_extern_t`].
191#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
192#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
193pub extern "C" fn wasm_table_as_extern(t: &mut wasm_table_t) -> &mut wasm_extern_t {
194    &mut t.inner
195}
196
197/// Returns the [`wasm_table_t`] as shared reference to [`wasm_extern_t`].
198#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
199#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
200pub extern "C" fn wasm_table_as_extern_const(t: &wasm_table_t) -> &wasm_extern_t {
201    &t.inner
202}