wasm-bridge 0.4.0

Run WASM modules on desktop or on the web using wasmtime's API
Documentation
use std::borrow::Cow;

use crate::{helpers::map_js_error, *};
use anyhow::bail;
use js_sys::{Uint8Array, WebAssembly};
use wasm_bindgen_futures::JsFuture;

#[derive(Clone, Debug)]
pub struct Module {
    pub(crate) module: WebAssembly::Module,
}

impl Module {
    #[deprecated(
        since = "0.4.0",
        note = "Compiling a module synchronously can panic on the web, please use `new_safe` instead."
    )]
    pub fn new(_engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Self> {
        let bytes = Self::resolve_bytes(bytes.as_ref())?;
        Self::from_bytes(&bytes)
    }

    pub async fn new_safe(_engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Self> {
        let bytes = Self::resolve_bytes(bytes.as_ref())?;
        Self::from_bytes_async(&bytes).await
    }

    fn resolve_bytes(bytes: &[u8]) -> Result<Cow<[u8]>> {
        if bytes.is_empty() {
            bail!("Cannot create a module from empty bytes")
        }

        if let Ok(text) = std::str::from_utf8(bytes) {
            Ok(Cow::Owned(Self::parse_wat(text)?))
        } else {
            Ok(Cow::Borrowed(bytes))
        }
    }

    #[cfg(feature = "wat")]
    fn parse_wat(wat: &str) -> Result<Vec<u8>> {
        Ok(wat::parse_str(wat)?)
    }

    #[cfg(not(feature = "wat"))]
    fn parse_wat(_wat: &str) -> Result<Vec<u8>> {
        bail!("Module bytes are valid text, try enabling the 'wat' feature to parse it")
    }

    fn from_bytes(bytes: &[u8]) -> Result<Self> {
        let byte_array = Uint8Array::from(bytes);

        let module = WebAssembly::Module::new(&byte_array.into()).map_err(map_js_error(
            "Failed to synchronously compile bytes to a WASM module",
        ))?;

        Ok(Self { module })
    }

    async fn from_bytes_async(bytes: &[u8]) -> Result<Self> {
        let byte_array = Uint8Array::from(bytes);

        let promise = WebAssembly::compile(&byte_array);
        let module = JsFuture::from(promise).await.map_err(map_js_error(
            "Failed to asynchronously compile bytes to a WASM module",
        ))?;

        Ok(Self {
            module: module.into(),
        })
    }
}