wasmi_c_api/
module.rs

1use crate::{
2    wasm_byte_vec_t,
3    wasm_exporttype_t,
4    wasm_exporttype_vec_t,
5    wasm_importtype_t,
6    wasm_importtype_vec_t,
7    wasm_store_t,
8    CExternType,
9};
10use alloc::{boxed::Box, string::String};
11use wasmi::{Engine, Module};
12
13/// A Wasm module.
14///
15/// Wraps [`Module`].
16#[derive(Clone)]
17pub struct wasm_module_t {
18    pub(crate) inner: Module,
19}
20
21wasmi_c_api_macros::declare_ref!(wasm_module_t);
22
23impl wasm_module_t {
24    pub(crate) fn new(module: Module) -> wasm_module_t {
25        wasm_module_t { inner: module }
26    }
27}
28
29/// A shared Wasm module.
30///
31/// This is mostly used to satisfy the Wasm C-API for Wasm module copying.
32///
33/// Wraps [`Module`] in a shared state.
34#[repr(C)]
35#[derive(Clone)]
36pub struct wasm_shared_module_t {
37    inner: Module,
38}
39
40wasmi_c_api_macros::declare_own!(wasm_shared_module_t);
41
42/// Creates a new [`wasm_module_t`] for `store` from the given Wasm `binary`.
43///
44/// Returns `None` if creation of the [`wasm_module_t`] failed.
45///
46/// Wraps [`Module::new`].
47///
48/// # Safety
49///
50/// It is the caller's responsibility not to alias the [`wasm_module_t`]
51/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
52#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
53#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
54pub unsafe extern "C" fn wasm_module_new(
55    store: &mut wasm_store_t,
56    binary: &wasm_byte_vec_t,
57) -> Option<Box<wasm_module_t>> {
58    match Module::new(store.inner.context().engine(), binary.as_slice()) {
59        Ok(module) => Some(Box::new(wasm_module_t::new(module))),
60        Err(_) => None,
61    }
62}
63
64/// Returns `true` if the Wasm `binary` successfully validates.
65///
66/// Wraps [`Module::validate`].
67///
68/// # Safety
69///
70/// It is the caller's responsibility not to alias the [`wasm_module_t`]
71/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
72#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
73#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
74pub unsafe extern "C" fn wasm_module_validate(
75    store: &mut wasm_store_t,
76    binary: &wasm_byte_vec_t,
77) -> bool {
78    Module::validate(store.inner.context().engine(), binary.as_slice()).is_ok()
79}
80
81/// Fills `out` with the exports of the [`Module`].
82fn fill_exports(module: &Module, out: &mut wasm_exporttype_vec_t) {
83    let exports = module
84        .exports()
85        .map(|e| {
86            Some(Box::new(wasm_exporttype_t::new(
87                String::from(e.name()),
88                CExternType::new(e.ty().clone()),
89            )))
90        })
91        .collect::<Box<[_]>>();
92    out.set_buffer(exports);
93}
94
95/// Queries the module exports of the [`wasm_module_t`].
96///
97/// Stores the queried module exports in `out`.
98///
99/// Wraps [`Module::exports`].
100#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
101#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
102pub extern "C" fn wasm_module_exports(module: &wasm_module_t, out: &mut wasm_exporttype_vec_t) {
103    fill_exports(&module.inner, out);
104}
105
106/// Fills `out` with the imports of the [`Module`].
107fn fill_imports(module: &Module, out: &mut wasm_importtype_vec_t) {
108    let imports = module
109        .imports()
110        .map(|i| {
111            Some(Box::new(wasm_importtype_t::new(
112                String::from(i.module()),
113                String::from(i.name()),
114                CExternType::new(i.ty().clone()),
115            )))
116        })
117        .collect::<Box<[_]>>();
118    out.set_buffer(imports);
119}
120
121/// Queries the module imports of the [`wasm_module_t`].
122///
123/// Stores the queried module imports in `out`.
124///
125/// Wraps [`Module::imports`].
126#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
127#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
128pub extern "C" fn wasm_module_imports(module: &wasm_module_t, out: &mut wasm_importtype_vec_t) {
129    fill_imports(&module.inner, out);
130}
131
132/// Shares the `module` and returns a shared image as [`wasm_shared_module_t`].
133///
134/// - This has similar effects to shallow-cloning a [`wasm_module_t`].
135/// - Obtain the original [`wasm_module_t`] via a call to [`wasm_module_obtain`].
136///
137/// Wraps [`Module::clone`] (kinda).
138#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
139#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
140pub extern "C" fn wasm_module_share(module: &wasm_module_t) -> Box<wasm_shared_module_t> {
141    Box::new(wasm_shared_module_t {
142        inner: module.inner.clone(),
143    })
144}
145
146/// Obtains the [`wasm_module_t`] from the [`wasm_shared_module_t`].
147///
148/// Returns `None` if the underlying `engine` of `store` and `shared_module` does not match.
149///
150/// # Safety
151///
152/// It is the caller's responsibility not to alias the [`wasm_module_t`]
153/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
154///
155/// Wraps [`Module::clone`] (kinda).
156#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
157#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
158pub unsafe extern "C" fn wasm_module_obtain(
159    store: &mut wasm_store_t,
160    shared_module: &wasm_shared_module_t,
161) -> Option<Box<wasm_module_t>> {
162    let module = shared_module.inner.clone();
163    if Engine::same(store.inner.context().engine(), module.engine()) {
164        Some(Box::new(wasm_module_t::new(module)))
165    } else {
166        None
167    }
168}
169
170/// Serializes the [`wasm_module_t`] into a binary.
171///
172/// The returned serialized binary can be deserialized using [`wasm_module_deserialize`].
173///
174/// # Note
175///
176/// This API is unsupported and will panic upon use.
177#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
178#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
179pub extern "C" fn wasm_module_serialize(_module: &wasm_module_t, _ret: &mut wasm_byte_vec_t) {
180    unimplemented!("wasm_module_serialize")
181}
182
183/// Deserializes the binary as a [`wasm_module_t`].
184///
185/// The input binary must be resulting from a call to [`wasm_module_serialize`].
186///
187/// Returns `None` if deserialization failed.
188///
189/// # Note
190///
191/// This API is unsupported and will panic upon use.
192///
193/// # Safety
194///
195/// It is the caller's responsibility not to alias the [`wasm_module_t`]
196/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
197#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
198#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
199pub unsafe extern "C" fn wasm_module_deserialize(
200    _store: &mut wasm_store_t,
201    _binary: &wasm_byte_vec_t,
202) -> Option<Box<wasm_module_t>> {
203    unimplemented!("wasm_module_deserialize")
204}