Simple Rust + WASM example
Tags: rust, webassembly, webdev, javascript
Published: 2018-12-08 13:57:18

1. Install rust
```bash
$ brew install rustup
$ rustup-init
```
2. Set default toolchain as `nightly`
```bash
$ rustup default nightly
```
3. Ass `wasm` target
```bash
$ rustup target add wasm32-unknown-unknown
```
4. Install `wasm-gc` tool to remove all unneeded exports, imports, functions, and so on from the generated WebAssembly module.
```bash
$ cargo instal wasm-gc
```
5. Instal `https` to runs a web server, serving static files from the current directory
```bash
$ cargo instal https
```
6. Create rust app, and open its files with your IDE (I'm using idea)
```bash
$ cargo new --lib utils
$ cd utils
$ idea .
```
7.Define the rust CDI lib type in the `cargo.toml`:
```toml
[package]
name = "utils"
version = "0.1.0"
authors = ["Hasan Yousef <hasan.ajsf@gmail.com>"]
edition = "2018"

[dependencies]

[lib]
crate-type =["cdylib"]
```
8. Define the `extern` function:
```rust
#[no_mangle]
pub extern fn add_one(x: u32) -> u32 {
    x + 1
}
```
The `extern` keyword is needed to create an interface, so that this function can be invoked from other languages.
The `no-mangle` annotation to tell the Rust compiler not to mangle the name of this function.
9. Build the wasm file:
```bash
$ cargo build --target wasm32-unknown-unknown --release
```
10. Run the `wasm-gc` to optimize the wasm file:
```bash
$ wasm-gc target/wasm32-unknown-unknown/release/utils.wasm -o utils.gc.wasm
```
11. Create the `index.html` file, and call the `wasm` module through javascript:
```html
<!DOCTYPE html>
<html>
  <head>
    <script> 
      WebAssembly.instantiateStreaming(fetch("utils.gc.wasm"))
        .then(wasmModule => {
          const result = wasmModeult.instance.exports.add_one(3);
          const text = document.createTextNode(result);
          document.body.appendChild(text);
        });
    </script>
  <head>
  <body></body>
<html>
```
Using instantiateStreaming instead, we can stream, compile, and instantiate a WebAssembly module in one go.
12. Run the static file server:
```bash
$ http
```
13. Open your browser at: `localhost:8000`

**ADVANCE**

If you want to interact with `JavaScript` function, you need to:
1. Define these functions signature in the rust file
2. Define a bridge/wrapper in the javascript file between these functions

So, if want to call the javascript `alert` and another function, let's say, addOne, then the above `main.rs` and `index.html` files will be as below:

main.rs:
```rust
// To call a JavaScript function
// 1. Define the JS functions signatures
extern {
    fn addOne(x: u32);
    fn alert(x: u32);
}
// 2. Call the JS function using unsafe block
#[no_mangle]
pub extern fn add_one(x: u32) {
    unsafe {
        addOne(x);
        alert(x);
    }
}
```

index.html
```html
<!DOCTYPE html>
<html>
  <head>
    <script> 
  const addOne = (number) => {
    const text = document.createTextNode(number + 1);
    document.body.appendChild(text);
  }

  const importObject = {
    env: {
        addOne: addOne,
        alert: alert,
    }
  };

  WebAssembly.instantiateStreaming(fetch("utils.gc.wasm"), importObject)
  .then(wasmModule => {
       const result = wasmModule.instance.exports.add_one(5);
   })
    </script>
  <head>
  <body></body>
<html>
```

For using `bindgen`, kindly see my other [post](https://dev.to/h_ajsf/rust--wasm-using-bindgen-49b4)