wasmtime_c_api/
module.rs

1use crate::{
2    handle_result, wasm_byte_vec_t, wasm_engine_t, wasm_exporttype_t, wasm_exporttype_vec_t,
3    wasm_importtype_t, wasm_importtype_vec_t, wasm_store_t, wasmtime_error_t, CExternType,
4};
5use anyhow::Context;
6use std::ffi::CStr;
7use std::os::raw::c_char;
8use wasmtime::{Engine, Module};
9
10#[derive(Clone)]
11pub struct wasm_module_t {
12    pub(crate) module: Module,
13}
14
15wasmtime_c_api_macros::declare_ref!(wasm_module_t);
16
17impl wasm_module_t {
18    pub(crate) fn new(module: Module) -> wasm_module_t {
19        wasm_module_t { module }
20    }
21}
22
23#[repr(C)]
24#[derive(Clone)]
25pub struct wasm_shared_module_t {
26    module: Module,
27}
28
29wasmtime_c_api_macros::declare_own!(wasm_shared_module_t);
30
31#[unsafe(no_mangle)]
32#[cfg(any(feature = "cranelift", feature = "winch"))]
33pub unsafe extern "C" fn wasm_module_new(
34    store: &mut wasm_store_t,
35    binary: &wasm_byte_vec_t,
36) -> Option<Box<wasm_module_t>> {
37    match Module::from_binary(store.store.context().engine(), binary.as_slice()) {
38        Ok(module) => Some(Box::new(wasm_module_t::new(module))),
39        Err(_) => None,
40    }
41}
42
43#[unsafe(no_mangle)]
44#[cfg(any(feature = "cranelift", feature = "winch"))]
45pub unsafe extern "C" fn wasm_module_validate(
46    store: &mut wasm_store_t,
47    binary: &wasm_byte_vec_t,
48) -> bool {
49    Module::validate(store.store.context().engine(), binary.as_slice()).is_ok()
50}
51
52fn fill_exports(module: &Module, out: &mut wasm_exporttype_vec_t) {
53    let exports = module
54        .exports()
55        .map(|e| {
56            Some(Box::new(wasm_exporttype_t::new(
57                e.name().to_owned(),
58                CExternType::new(e.ty()),
59            )))
60        })
61        .collect::<Vec<_>>();
62    out.set_buffer(exports);
63}
64
65fn fill_imports(module: &Module, out: &mut wasm_importtype_vec_t) {
66    let imports = module
67        .imports()
68        .map(|i| {
69            Some(Box::new(wasm_importtype_t::new(
70                i.module().to_owned(),
71                i.name().to_owned(),
72                CExternType::new(i.ty()),
73            )))
74        })
75        .collect::<Vec<_>>();
76    out.set_buffer(imports);
77}
78
79#[unsafe(no_mangle)]
80pub extern "C" fn wasm_module_exports(module: &wasm_module_t, out: &mut wasm_exporttype_vec_t) {
81    fill_exports(&module.module, out);
82}
83
84#[unsafe(no_mangle)]
85pub extern "C" fn wasm_module_imports(module: &wasm_module_t, out: &mut wasm_importtype_vec_t) {
86    fill_imports(&module.module, out);
87}
88
89#[unsafe(no_mangle)]
90pub extern "C" fn wasm_module_share(module: &wasm_module_t) -> Box<wasm_shared_module_t> {
91    Box::new(wasm_shared_module_t {
92        module: module.module.clone(),
93    })
94}
95
96#[unsafe(no_mangle)]
97pub unsafe extern "C" fn wasm_module_obtain(
98    store: &mut wasm_store_t,
99    shared_module: &wasm_shared_module_t,
100) -> Option<Box<wasm_module_t>> {
101    let module = shared_module.module.clone();
102    if Engine::same(store.store.context().engine(), module.engine()) {
103        Some(Box::new(wasm_module_t::new(module)))
104    } else {
105        None
106    }
107}
108
109#[unsafe(no_mangle)]
110#[cfg(any(feature = "cranelift", feature = "winch"))]
111pub extern "C" fn wasm_module_serialize(module: &wasm_module_t, ret: &mut wasm_byte_vec_t) {
112    if let Ok(buf) = module.module.serialize() {
113        ret.set_buffer(buf);
114    }
115}
116
117#[unsafe(no_mangle)]
118pub unsafe extern "C" fn wasm_module_deserialize(
119    store: &mut wasm_store_t,
120    binary: &wasm_byte_vec_t,
121) -> Option<Box<wasm_module_t>> {
122    match Module::deserialize(store.store.context().engine(), binary.as_slice()) {
123        Ok(module) => Some(Box::new(wasm_module_t::new(module))),
124        Err(_) => None,
125    }
126}
127
128#[derive(Clone)]
129pub struct wasmtime_module_t {
130    pub(crate) module: Module,
131}
132
133wasmtime_c_api_macros::declare_own!(wasmtime_module_t);
134
135#[unsafe(no_mangle)]
136#[cfg(any(feature = "cranelift", feature = "winch"))]
137pub unsafe extern "C" fn wasmtime_module_new(
138    engine: &wasm_engine_t,
139    wasm: *const u8,
140    len: usize,
141    out: &mut *mut wasmtime_module_t,
142) -> Option<Box<wasmtime_error_t>> {
143    handle_result(
144        Module::from_binary(&engine.engine, crate::slice_from_raw_parts(wasm, len)),
145        |module| {
146            *out = Box::into_raw(Box::new(wasmtime_module_t { module }));
147        },
148    )
149}
150
151#[unsafe(no_mangle)]
152pub extern "C" fn wasmtime_module_clone(module: &wasmtime_module_t) -> Box<wasmtime_module_t> {
153    Box::new(module.clone())
154}
155
156#[unsafe(no_mangle)]
157pub extern "C" fn wasmtime_module_exports(
158    module: &wasmtime_module_t,
159    out: &mut wasm_exporttype_vec_t,
160) {
161    fill_exports(&module.module, out);
162}
163
164#[unsafe(no_mangle)]
165pub extern "C" fn wasmtime_module_imports(
166    module: &wasmtime_module_t,
167    out: &mut wasm_importtype_vec_t,
168) {
169    fill_imports(&module.module, out);
170}
171
172#[unsafe(no_mangle)]
173#[cfg(any(feature = "cranelift", feature = "winch"))]
174pub unsafe extern "C" fn wasmtime_module_validate(
175    engine: &wasm_engine_t,
176    wasm: *const u8,
177    len: usize,
178) -> Option<Box<wasmtime_error_t>> {
179    let binary = crate::slice_from_raw_parts(wasm, len);
180    handle_result(Module::validate(&engine.engine, binary), |()| {})
181}
182
183#[unsafe(no_mangle)]
184#[cfg(any(feature = "cranelift", feature = "winch"))]
185pub extern "C" fn wasmtime_module_serialize(
186    module: &wasmtime_module_t,
187    ret: &mut wasm_byte_vec_t,
188) -> Option<Box<wasmtime_error_t>> {
189    handle_result(module.module.serialize(), |buf| ret.set_buffer(buf))
190}
191
192#[unsafe(no_mangle)]
193pub extern "C" fn wasmtime_module_image_range(
194    module: &wasmtime_module_t,
195    start: &mut *const u8,
196    end: &mut *const u8,
197) {
198    let range = module.module.image_range();
199    *start = range.start;
200    *end = range.end;
201}
202
203#[unsafe(no_mangle)]
204pub unsafe extern "C" fn wasmtime_module_deserialize(
205    engine: &wasm_engine_t,
206    bytes: *const u8,
207    len: usize,
208    out: &mut *mut wasmtime_module_t,
209) -> Option<Box<wasmtime_error_t>> {
210    let bytes = crate::slice_from_raw_parts(bytes, len);
211    handle_result(Module::deserialize(&engine.engine, bytes), |module| {
212        *out = Box::into_raw(Box::new(wasmtime_module_t { module }));
213    })
214}
215
216#[unsafe(no_mangle)]
217pub unsafe extern "C" fn wasmtime_module_deserialize_file(
218    engine: &wasm_engine_t,
219    path: *const c_char,
220    out: &mut *mut wasmtime_module_t,
221) -> Option<Box<wasmtime_error_t>> {
222    let path = CStr::from_ptr(path);
223    let result = path
224        .to_str()
225        .context("input path is not valid utf-8")
226        .and_then(|path| Module::deserialize_file(&engine.engine, path));
227    handle_result(result, |module| {
228        *out = Box::into_raw(Box::new(wasmtime_module_t { module }));
229    })
230}