wasm_bridge_js/no_bindgen/
module.rs1use std::borrow::Cow;
2
3use crate::{helpers::map_js_error, *};
4use anyhow::bail;
5use js_sys::{Uint8Array, WebAssembly};
6use wasm_bindgen_futures::JsFuture;
7
8#[derive(Clone, Debug)]
9pub struct Module {
10 pub(crate) module: WebAssembly::Module,
11}
12
13impl Module {
14 pub fn new(_engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Self> {
15 let bytes = Self::resolve_bytes(bytes.as_ref())?;
16 Self::from_bytes(&bytes)
17 }
18
19 pub async fn new_async(_engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Self> {
20 let bytes = Self::resolve_bytes(bytes.as_ref())?;
21 Self::from_bytes_async(&bytes).await
22 }
23
24 fn resolve_bytes(bytes: &[u8]) -> Result<Cow<[u8]>> {
25 if bytes.is_empty() {
26 bail!("Cannot create a module from empty bytes")
27 }
28
29 if let Ok(text) = std::str::from_utf8(bytes) {
30 Ok(Cow::Owned(Self::parse_wat(text)?))
31 } else {
32 Ok(Cow::Borrowed(bytes))
33 }
34 }
35
36 #[cfg(feature = "wat")]
37 fn parse_wat(wat: &str) -> Result<Vec<u8>> {
38 Ok(wat::parse_str(wat)?)
39 }
40
41 #[cfg(not(feature = "wat"))]
42 fn parse_wat(_wat: &str) -> Result<Vec<u8>> {
43 bail!("Module bytes are valid text, try enabling the 'wat' feature to parse it")
44 }
45
46 fn from_bytes(bytes: &[u8]) -> Result<Self> {
47 let byte_array = Uint8Array::from(bytes);
50
51 let module = WebAssembly::Module::new(&byte_array.into())
52 .map_err(map_js_error("Failed to compile bytes to a WASM module"))?;
53
54 Ok(Self { module })
55 }
56
57 async fn from_bytes_async(bytes: &[u8]) -> Result<Self> {
58 let byte_array = Uint8Array::from(bytes);
59 let promise = WebAssembly::compile(&byte_array);
60
61 let module = JsFuture::from(promise)
62 .await
63 .map_err(map_js_error("Failed to compile bytes to a WASM module"))?;
64
65 Ok(Self {
66 module: module.into(),
67 })
68 }
69}
70
71pub async fn new_module_async(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Module> {
72 Module::new_async(engine, bytes).await
73}