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}