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