linera_wasmer/
module.rs

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