wasmer/entities/module/mod.rs
1//! Defines the [`Module`] data type and various useful traits and data types to interact with a
2//! module.
3
4pub(crate) mod inner;
5pub(crate) use inner::*;
6
7use std::{fs, path::Path};
8
9use bytes::Bytes;
10use thiserror::Error;
11#[cfg(feature = "wat")]
12use wasmer_types::WasmError;
13use wasmer_types::{
14 CompilationProgress, CompilationProgressCallback, CompileError, DeserializeError, ExportType,
15 ExportsIterator, ImportType, ImportsIterator, ModuleInfo, SerializeError, UserAbort,
16};
17
18use crate::{AsEngineRef, macros::backend::match_rt, utils::IntoBytes};
19
20/// IO errors that can happen while compiling a [`Module`].
21#[derive(Error, Debug)]
22pub enum IoCompileError {
23 /// An IO error
24 #[error(transparent)]
25 Io(#[from] std::io::Error),
26 /// A compilation error
27 #[error(transparent)]
28 Compile(#[from] CompileError),
29}
30
31/// A WebAssembly Module contains stateless WebAssembly
32/// code that has already been compiled and can be instantiated
33/// multiple times.
34///
35/// ## Cloning a module
36///
37/// Cloning a module is cheap: it does a shallow copy of the compiled
38/// contents rather than a deep copy.
39#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
40#[derive(Clone, PartialEq, Eq, derive_more::From)]
41pub struct Module(pub(crate) BackendModule);
42
43impl Module {
44 /// Creates a new WebAssembly Module given the configuration
45 /// in the store.
46 ///
47 /// If the provided bytes are not WebAssembly-like (start with `b"\0asm"`),
48 /// and the "wat" feature is enabled for this crate, this function will try to
49 /// to convert the bytes assuming they correspond to the WebAssembly text
50 /// format.
51 ///
52 /// ## Security
53 ///
54 /// Before the code is compiled, it will be validated using the store
55 /// features.
56 ///
57 /// ## Errors
58 ///
59 /// Creating a WebAssembly module from bytecode can result in a
60 /// [`CompileError`] since this operation requires to transform the Wasm
61 /// bytecode into code the machine can easily execute.
62 ///
63 /// ## Example
64 ///
65 /// Reading from a WAT file.
66 ///
67 /// ```
68 /// use wasmer::*;
69 /// # fn main() -> anyhow::Result<()> {
70 /// # let mut store = Store::default();
71 /// let wat = "(module)";
72 /// let module = Module::new(&store, wat)?;
73 /// # Ok(())
74 /// # }
75 /// ```
76 ///
77 /// Reading from bytes:
78 ///
79 /// ```
80 /// use wasmer::*;
81 /// # fn main() -> anyhow::Result<()> {
82 /// # let mut store = Store::default();
83 /// // The following is the same as:
84 /// // (module
85 /// // (type $t0 (func (param i32) (result i32)))
86 /// // (func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
87 /// // get_local $p0
88 /// // i32.const 1
89 /// // i32.add)
90 /// // )
91 /// let bytes: Vec<u8> = vec![
92 /// 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
93 /// 0x01, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x0b, 0x01, 0x07,
94 /// 0x61, 0x64, 0x64, 0x5f, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x0a, 0x09, 0x01,
95 /// 0x07, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x0b, 0x00, 0x1a, 0x04, 0x6e,
96 /// 0x61, 0x6d, 0x65, 0x01, 0x0a, 0x01, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f,
97 /// 0x6f, 0x6e, 0x65, 0x02, 0x07, 0x01, 0x00, 0x01, 0x00, 0x02, 0x70, 0x30,
98 /// ];
99 /// let module = Module::new(&store, bytes)?;
100 /// # Ok(())
101 /// # }
102 /// ```
103 /// # Example of loading a module using just an `Engine` and no `Store`
104 ///
105 /// ```
106 /// # use wasmer::*;
107 /// #
108 /// # let engine: Engine = Engine::default().into();
109 ///
110 /// let module = Module::from_file(&engine, "path/to/foo.wasm");
111 /// ```
112 pub fn new(engine: &impl AsEngineRef, bytes: impl AsRef<[u8]>) -> Result<Self, CompileError> {
113 BackendModule::new(engine, bytes).map(Self)
114 }
115
116 /// Creates a new WebAssembly module from a file path.
117 pub fn from_file(
118 engine: &impl AsEngineRef,
119 file: impl AsRef<Path>,
120 ) -> Result<Self, IoCompileError> {
121 BackendModule::from_file(engine, file).map(Self)
122 }
123
124 /// Creates a new WebAssembly module from a Wasm binary.
125 ///
126 /// Opposed to [`Module::new`], this function is not compatible with
127 /// the WebAssembly text format (if the "wat" feature is enabled for
128 /// this crate).
129 pub fn from_binary(engine: &impl AsEngineRef, binary: &[u8]) -> Result<Self, CompileError> {
130 BackendModule::from_binary(engine, binary).map(Self)
131 }
132
133 /// Creates a new WebAssembly module from a Wasm binary,
134 /// skipping any kind of validation on the WebAssembly file.
135 ///
136 /// # Safety
137 ///
138 /// This can speed up compilation time a bit, but it should be only used
139 /// in environments where the WebAssembly modules are trusted and validated
140 /// beforehand.
141 pub unsafe fn from_binary_unchecked(
142 engine: &impl AsEngineRef,
143 binary: &[u8],
144 ) -> Result<Self, CompileError> {
145 unsafe { BackendModule::from_binary_unchecked(engine, binary) }.map(Self)
146 }
147
148 /// Validates a new WebAssembly Module given the configuration
149 /// in the Store.
150 ///
151 /// This validation is normally pretty fast and checks the enabled
152 /// WebAssembly features in the Store Engine to assure deterministic
153 /// validation of the Module.
154 pub fn validate(engine: &impl AsEngineRef, binary: &[u8]) -> Result<(), CompileError> {
155 BackendModule::validate(engine, binary)?;
156 Ok(())
157 }
158
159 /// Serializes a module into a binary representation that the `Engine`
160 /// can later process via [`Module::deserialize`].
161 ///
162 /// # Important
163 ///
164 /// This function will return a custom binary format that will be different than
165 /// the `wasm` binary format, but faster to load in Native hosts.
166 ///
167 /// # Usage
168 ///
169 /// ```ignore
170 /// # use wasmer::*;
171 /// # fn main() -> anyhow::Result<()> {
172 /// # let mut store = Store::default();
173 /// # let module = Module::from_file(&store, "path/to/foo.wasm")?;
174 /// let serialized = module.serialize()?;
175 /// # Ok(())
176 /// # }
177 /// ```
178 pub fn serialize(&self) -> Result<Bytes, SerializeError> {
179 self.0.serialize()
180 }
181
182 /// Serializes a module into a file that the `Engine`
183 /// can later process via [`Module::deserialize_from_file`].
184 ///
185 /// # Usage
186 ///
187 /// ```ignore
188 /// # use wasmer::*;
189 /// # fn main() -> anyhow::Result<()> {
190 /// # let mut store = Store::default();
191 /// # let module = Module::from_file(&store, "path/to/foo.wasm")?;
192 /// module.serialize_to_file("path/to/foo.so")?;
193 /// # Ok(())
194 /// # }
195 /// ```
196 pub fn serialize_to_file(&self, path: impl AsRef<Path>) -> Result<(), SerializeError> {
197 let serialized = self.serialize()?;
198 fs::write(path, serialized)?;
199 Ok(())
200 }
201
202 /// Deserializes a serialized module binary into a `Module`.
203 ///
204 /// Note: You should usually prefer the safer [`Module::deserialize`].
205 ///
206 /// # Important
207 ///
208 /// This function only accepts a custom binary format, which will be different
209 /// than the `wasm` binary format and may change among Wasmer versions.
210 /// (it should be the result of the serialization of a Module via the
211 /// `Module::serialize` method.).
212 ///
213 /// # Safety
214 ///
215 /// This function is inherently **unsafe** as the provided bytes:
216 /// 1. Are going to be deserialized directly into Rust objects.
217 /// 2. Contains the function assembly bodies and, if intercepted,
218 /// a malicious actor could inject code into executable
219 /// memory.
220 ///
221 /// And as such, the `deserialize_unchecked` method is unsafe.
222 ///
223 /// # Usage
224 ///
225 /// ```ignore
226 /// # use wasmer::*;
227 /// # fn main() -> anyhow::Result<()> {
228 /// # let mut store = Store::default();
229 /// let module = Module::deserialize_unchecked(&store, serialized_data)?;
230 /// # Ok(())
231 /// # }
232 /// ```
233 pub unsafe fn deserialize_unchecked(
234 engine: &impl AsEngineRef,
235 bytes: impl IntoBytes,
236 ) -> Result<Self, DeserializeError> {
237 unsafe { BackendModule::deserialize_unchecked(engine, bytes) }.map(Self)
238 }
239
240 /// Deserializes a serialized Module binary into a `Module`.
241 ///
242 /// # Important
243 ///
244 /// This function only accepts a custom binary format, which will be different
245 /// than the `wasm` binary format and may change among Wasmer versions.
246 /// (it should be the result of the serialization of a Module via the
247 /// `Module::serialize` method.).
248 ///
249 /// # Usage
250 ///
251 /// ```ignore
252 /// # use wasmer::*;
253 /// # fn main() -> anyhow::Result<()> {
254 /// # let mut store = Store::default();
255 /// let module = Module::deserialize(&store, serialized_data)?;
256 /// # Ok(())
257 /// # }
258 /// ```
259 ///
260 /// # Safety
261 /// This function is inherently **unsafe**, because it loads executable code
262 /// into memory.
263 /// The loaded bytes must be trusted to contain a valid artifact previously
264 /// built with [`Self::serialize`].
265 pub unsafe fn deserialize(
266 engine: &impl AsEngineRef,
267 bytes: impl IntoBytes,
268 ) -> Result<Self, DeserializeError> {
269 unsafe { BackendModule::deserialize_unchecked(engine, bytes) }.map(Self)
270 }
271
272 /// Deserializes a serialized Module located in a `Path` into a `Module`.
273 /// > Note: the module has to be serialized before with the `serialize` method.
274 ///
275 /// # Usage
276 ///
277 /// ```ignore
278 /// # use wasmer::*;
279 /// # fn main() -> anyhow::Result<()> {
280 /// # let mut store = Store::default();
281 /// let module = Module::deserialize_from_file(&store, path)?;
282 /// # Ok(())
283 /// # }
284 /// ```
285 ///
286 /// # Safety
287 ///
288 /// See [`Self::deserialize`].
289 pub unsafe fn deserialize_from_file(
290 engine: &impl AsEngineRef,
291 path: impl AsRef<Path>,
292 ) -> Result<Self, DeserializeError> {
293 unsafe { BackendModule::deserialize_from_file(engine, path) }.map(Self)
294 }
295
296 /// Deserializes a serialized Module located in a `Path` into a `Module`.
297 /// > Note: the module has to be serialized before with the `serialize` method.
298 ///
299 /// You should usually prefer the safer [`Module::deserialize_from_file`].
300 ///
301 /// # Safety
302 ///
303 /// Please check [`Module::deserialize_unchecked`].
304 ///
305 /// # Usage
306 ///
307 /// ```ignore
308 /// # use wasmer::*;
309 /// # fn main() -> anyhow::Result<()> {
310 /// # let mut store = Store::default();
311 /// let module = Module::deserialize_from_file_unchecked(&store, path)?;
312 /// # Ok(())
313 /// # }
314 /// ```
315 pub unsafe fn deserialize_from_file_unchecked(
316 engine: &impl AsEngineRef,
317 path: impl AsRef<Path>,
318 ) -> Result<Self, DeserializeError> {
319 unsafe { BackendModule::deserialize_from_file_unchecked(engine, path) }.map(Self)
320 }
321
322 /// Returns the name of the current module.
323 ///
324 /// This name is normally set in the WebAssembly bytecode by some
325 /// compilers, but can be also overwritten using the [`Module::set_name`] method.
326 ///
327 /// # Example
328 ///
329 /// ```
330 /// # use wasmer::*;
331 /// # fn main() -> anyhow::Result<()> {
332 /// # let mut store = Store::default();
333 /// let wat = "(module $moduleName)";
334 /// let module = Module::new(&store, wat)?;
335 /// assert_eq!(module.name(), Some("moduleName"));
336 /// # Ok(())
337 /// # }
338 /// ```
339 pub fn name(&self) -> Option<&str> {
340 self.0.name()
341 }
342
343 /// Sets the name of the current module.
344 /// This is normally useful for stacktraces and debugging.
345 ///
346 /// It will return `true` if the module name was changed successfully,
347 /// and return `false` otherwise (in case the module is cloned or
348 /// already instantiated).
349 ///
350 /// # Example
351 ///
352 /// ```
353 /// # use wasmer::*;
354 /// # fn main() -> anyhow::Result<()> {
355 /// # let mut store = Store::default();
356 /// let wat = "(module)";
357 /// let mut module = Module::new(&store, wat)?;
358 /// assert_eq!(module.name(), None);
359 /// module.set_name("foo");
360 /// assert_eq!(module.name(), Some("foo"));
361 /// # Ok(())
362 /// # }
363 /// ```
364 pub fn set_name(&mut self, name: &str) -> bool {
365 self.0.set_name(name)
366 }
367
368 /// Returns an iterator over the imported types in the Module.
369 ///
370 /// The order of the imports is guaranteed to be the same as in the
371 /// WebAssembly bytecode.
372 ///
373 /// # Example
374 ///
375 /// ```
376 /// # use wasmer::*;
377 /// # fn main() -> anyhow::Result<()> {
378 /// # let mut store = Store::default();
379 /// let wat = r#"(module
380 /// (import "host" "func1" (func))
381 /// (import "host" "func2" (func))
382 /// )"#;
383 /// let module = Module::new(&store, wat)?;
384 /// for import in module.imports() {
385 /// assert_eq!(import.module(), "host");
386 /// assert!(import.name().contains("func"));
387 /// import.ty();
388 /// }
389 /// # Ok(())
390 /// # }
391 /// ```
392 pub fn imports(&self) -> ImportsIterator<Box<dyn Iterator<Item = ImportType> + '_>> {
393 self.0.imports()
394 }
395
396 /// Returns an iterator over the exported types in the Module.
397 ///
398 /// The order of the exports is guaranteed to be the same as in the
399 /// WebAssembly bytecode.
400 ///
401 /// # Example
402 ///
403 /// ```
404 /// # use wasmer::*;
405 /// # fn main() -> anyhow::Result<()> {
406 /// # let mut store = Store::default();
407 /// let wat = r#"(module
408 /// (func (export "namedfunc"))
409 /// (memory (export "namedmemory") 1)
410 /// )"#;
411 /// let module = Module::new(&store, wat)?;
412 /// for export_ in module.exports() {
413 /// assert!(export_.name().contains("named"));
414 /// export_.ty();
415 /// }
416 /// # Ok(())
417 /// # }
418 /// ```
419 pub fn exports(&self) -> ExportsIterator<Box<dyn Iterator<Item = ExportType> + '_>> {
420 self.0.exports()
421 }
422
423 /// Get the custom sections of the module given a `name`.
424 ///
425 /// # Important
426 ///
427 /// Following the WebAssembly spec, one name can have multiple
428 /// custom sections. That's why an iterator (rather than one element)
429 /// is returned.
430 pub fn custom_sections<'a>(&'a self, name: &'a str) -> impl Iterator<Item = Box<[u8]>> + 'a {
431 self.0.custom_sections(name)
432 }
433
434 /// The ABI of the [`ModuleInfo`] is very unstable, we refactor it very often.
435 /// This function is public because in some cases it can be useful to get some
436 /// extra information from the module.
437 ///
438 /// However, the usage is highly discouraged.
439 #[doc(hidden)]
440 pub fn info(&self) -> &ModuleInfo {
441 self.0.info()
442 }
443}
444
445impl std::fmt::Debug for Module {
446 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
447 f.debug_struct("Module")
448 .field("name", &self.name())
449 .finish()
450 }
451}
452
453#[cfg(feature = "js")]
454impl From<Module> for wasm_bindgen::JsValue {
455 fn from(value: Module) -> Self {
456 match value.0 {
457 BackendModule::Js(module) => Self::from(module),
458 _ => unreachable!(),
459 }
460 }
461}