xref: /wasmtime-44.0.1/crates/c-api/src/module.rs (revision ca5a9db0)
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,
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 #[no_mangle]
32 pub unsafe extern "C" fn wasm_module_new(
33     store: &mut wasm_store_t,
34     binary: &wasm_byte_vec_t,
35 ) -> Option<Box<wasm_module_t>> {
36     match Module::from_binary(store.store.context().engine(), binary.as_slice()) {
37         Ok(module) => Some(Box::new(wasm_module_t::new(module))),
38         Err(_) => None,
39     }
40 }
41 
42 #[no_mangle]
43 pub unsafe extern "C" fn wasm_module_validate(
44     store: &mut wasm_store_t,
45     binary: &wasm_byte_vec_t,
46 ) -> bool {
47     Module::validate(store.store.context().engine(), binary.as_slice()).is_ok()
48 }
49 
50 fn fill_exports(module: &Module, out: &mut wasm_exporttype_vec_t) {
51     let exports = module
52         .exports()
53         .map(|e| {
54             Some(Box::new(wasm_exporttype_t::new(
55                 e.name().to_owned(),
56                 e.ty(),
57             )))
58         })
59         .collect::<Vec<_>>();
60     out.set_buffer(exports);
61 }
62 
63 fn fill_imports(module: &Module, out: &mut wasm_importtype_vec_t) {
64     let imports = module
65         .imports()
66         .map(|i| {
67             Some(Box::new(wasm_importtype_t::new(
68                 i.module().to_owned(),
69                 i.name().to_owned(),
70                 i.ty(),
71             )))
72         })
73         .collect::<Vec<_>>();
74     out.set_buffer(imports);
75 }
76 
77 #[no_mangle]
78 pub extern "C" fn wasm_module_exports(module: &wasm_module_t, out: &mut wasm_exporttype_vec_t) {
79     fill_exports(&module.module, out);
80 }
81 
82 #[no_mangle]
83 pub extern "C" fn wasm_module_imports(module: &wasm_module_t, out: &mut wasm_importtype_vec_t) {
84     fill_imports(&module.module, out);
85 }
86 
87 #[no_mangle]
88 pub extern "C" fn wasm_module_share(module: &wasm_module_t) -> Box<wasm_shared_module_t> {
89     Box::new(wasm_shared_module_t {
90         module: module.module.clone(),
91     })
92 }
93 
94 #[no_mangle]
95 pub unsafe extern "C" fn wasm_module_obtain(
96     store: &mut wasm_store_t,
97     shared_module: &wasm_shared_module_t,
98 ) -> Option<Box<wasm_module_t>> {
99     let module = shared_module.module.clone();
100     if Engine::same(store.store.context().engine(), module.engine()) {
101         Some(Box::new(wasm_module_t::new(module)))
102     } else {
103         None
104     }
105 }
106 
107 #[no_mangle]
108 pub extern "C" fn wasm_module_serialize(module: &wasm_module_t, ret: &mut wasm_byte_vec_t) {
109     if let Ok(buf) = module.module.serialize() {
110         ret.set_buffer(buf);
111     }
112 }
113 
114 #[no_mangle]
115 pub unsafe extern "C" fn wasm_module_deserialize(
116     store: &mut wasm_store_t,
117     binary: &wasm_byte_vec_t,
118 ) -> Option<Box<wasm_module_t>> {
119     match Module::deserialize(store.store.context().engine(), binary.as_slice()) {
120         Ok(module) => Some(Box::new(wasm_module_t::new(module))),
121         Err(_) => None,
122     }
123 }
124 
125 #[derive(Clone)]
126 pub struct wasmtime_module_t {
127     pub(crate) module: Module,
128 }
129 
130 wasmtime_c_api_macros::declare_own!(wasmtime_module_t);
131 
132 #[no_mangle]
133 pub unsafe extern "C" fn wasmtime_module_new(
134     engine: &wasm_engine_t,
135     wasm: *const u8,
136     len: usize,
137     out: &mut *mut wasmtime_module_t,
138 ) -> Option<Box<wasmtime_error_t>> {
139     handle_result(
140         Module::from_binary(&engine.engine, crate::slice_from_raw_parts(wasm, len)),
141         |module| {
142             *out = Box::into_raw(Box::new(wasmtime_module_t { module }));
143         },
144     )
145 }
146 
147 #[no_mangle]
148 pub extern "C" fn wasmtime_module_clone(module: &wasmtime_module_t) -> Box<wasmtime_module_t> {
149     Box::new(module.clone())
150 }
151 
152 #[no_mangle]
153 pub extern "C" fn wasmtime_module_exports(
154     module: &wasmtime_module_t,
155     out: &mut wasm_exporttype_vec_t,
156 ) {
157     fill_exports(&module.module, out);
158 }
159 
160 #[no_mangle]
161 pub extern "C" fn wasmtime_module_imports(
162     module: &wasmtime_module_t,
163     out: &mut wasm_importtype_vec_t,
164 ) {
165     fill_imports(&module.module, out);
166 }
167 
168 #[no_mangle]
169 pub unsafe extern "C" fn wasmtime_module_validate(
170     engine: &wasm_engine_t,
171     wasm: *const u8,
172     len: usize,
173 ) -> Option<Box<wasmtime_error_t>> {
174     let binary = crate::slice_from_raw_parts(wasm, len);
175     handle_result(Module::validate(&engine.engine, binary), |()| {})
176 }
177 
178 #[no_mangle]
179 pub extern "C" fn wasmtime_module_serialize(
180     module: &wasmtime_module_t,
181     ret: &mut wasm_byte_vec_t,
182 ) -> Option<Box<wasmtime_error_t>> {
183     handle_result(module.module.serialize(), |buf| ret.set_buffer(buf))
184 }
185 
186 #[no_mangle]
187 pub unsafe extern "C" fn wasmtime_module_deserialize(
188     engine: &wasm_engine_t,
189     bytes: *const u8,
190     len: usize,
191     out: &mut *mut wasmtime_module_t,
192 ) -> Option<Box<wasmtime_error_t>> {
193     let bytes = crate::slice_from_raw_parts(bytes, len);
194     handle_result(Module::deserialize(&engine.engine, bytes), |module| {
195         *out = Box::into_raw(Box::new(wasmtime_module_t { module }));
196     })
197 }
198 
199 #[no_mangle]
200 pub unsafe extern "C" fn wasmtime_module_deserialize_file(
201     engine: &wasm_engine_t,
202     path: *const c_char,
203     out: &mut *mut wasmtime_module_t,
204 ) -> Option<Box<wasmtime_error_t>> {
205     let path = CStr::from_ptr(path);
206     let result = path
207         .to_str()
208         .context("input path is not valid utf-8")
209         .and_then(|path| Module::deserialize_file(&engine.engine, path));
210     handle_result(result, |module| {
211         *out = Box::into_raw(Box::new(wasmtime_module_t { module }));
212     })
213 }
214