xref: /wasmtime-44.0.1/crates/c-api/src/module.rs (revision 2cd52b76)
1 use 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 };
5 use anyhow::Context;
6 use std::ffi::CStr;
7 use std::os::raw::c_char;
8 use wasmtime::{Engine, Module};
9 
10 #[derive(Clone)]
11 pub struct wasm_module_t {
12     pub(crate) module: Module,
13 }
14 
15 wasmtime_c_api_macros::declare_ref!(wasm_module_t);
16 
17 impl 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)]
25 pub struct wasm_shared_module_t {
26     module: Module,
27 }
28 
29 wasmtime_c_api_macros::declare_own!(wasm_shared_module_t);
30 
31 #[unsafe(no_mangle)]
32 #[cfg(any(feature = "cranelift", feature = "winch"))]
33 pub 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"))]
45 pub 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 
52 fn 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 
65 fn 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)]
80 pub 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)]
85 pub 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)]
90 pub 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)]
97 pub 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"))]
111 pub 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)]
118 pub 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)]
129 pub struct wasmtime_module_t {
130     pub(crate) module: Module,
131 }
132 
133 wasmtime_c_api_macros::declare_own!(wasmtime_module_t);
134 
135 #[unsafe(no_mangle)]
136 #[cfg(any(feature = "cranelift", feature = "winch"))]
137 pub 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)]
152 pub 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)]
157 pub 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)]
165 pub 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"))]
174 pub 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"))]
185 pub 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)]
193 pub 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)]
204 pub 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)]
217 pub 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 }
231