wasmtime_c_api/
module.rs

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