Skip to main content

wasmi_c_api/
module.rs

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