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