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}