Rust + WASM using bindgen
Tags: rust, webassembly, javascript, bindgen
Published: 2018-12-08 12:00:40


This is an advance topic using `bindgen`, as second step to my previouse [post](https://dev.to/h_ajsf/simple-rust--wasm-example-5b1m)

1. Create project folder `utils2`
2. cd to this folder
3. from this folder create your lib:
```bash
// install rust if not yet done
// curl https://sh.rustup.rs -sSf | sh
mkdir utils2
cd utils 2
cargo init --lib

// Or it can be created in one line as:
cargo new utils2 --lib
cd utils2
```
4. make the default toolchain as `nightly` as `wasm` is only supported in nightly now:
```bash
rustup override set nightly
// Add was32 target if not yet installed
rustup target add wasm32-unknown-unknown --toolchain nightly
```
note:
Platforms are defined by their `Target Triplet` that is: `machine-vendor-operatingsystem`:
1. Machine / the name of the CPU family/model: wasm32,
2. The vendor: no specific, so it is unknown,
3. The operating system name: no specific, so it is unknown.

5. Create `npm` package file by running:
```bash
npm init
```
the above will create `package.json`.

6. Install `webpack` npm requirements, the `node_modules` folder will be created:
```bash
// brew install node
npm install -D webpack webpack-cli webpack-dev-server
```

the above will alter the `package.json` and make it loos something like::
```json
{
  "name": "utils2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.27.1",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^3.1.10"
  }
}
```

6. Create `domUtils.js`, `index.html`, `index.js` and `webpack.config.js` files, so that the structure be as below:
```bash
// if you need to install tree, it can be done by
// brew install tree
$ tree .
.
├── Cargo.lock
├── Cargo.toml
├── domUtils.js
├── index.html
├── index.js
├── package.json
├── src
│   └── lib.rs
└── webpack.config.js
```

7. Open the folder files in your idea, and update them, as shown in point #11
```bash
$ idea .
```

8. Build the rust wasm lib using `wasm-pack` as:
```bash
// cargo install wasm-pack
wasm-pack build
// this will create the standard target folder, and additional folder called pkg
// the pkg folder tree is:
├── pkg
│   ├── utils2.d.ts
│   ├── utils2.js
│   ├── utils2_bg.d.ts
│   └── utils2_bg.wasm
```

10. Run the server as:
```bash
npx webpack-dev-server
```

11. The files:

Cargo.toml
```toml
[package]
name = "utils2"
version = "0.1.0"
authors = ["Hasan Yousef"]
edition = "2018"

[dependencies]
wasm-bindgen = "0.2.29"

[lib]
crate-type = ["cdylib"]

```

domUtils.js
```javascript
export const appendStringToBody = (value) => {
  const text = document.createTextNode(value);
  document.body.appendChild(text);
}
```

libs.rs:
```rust
use wasm_bindgen::prelude::*;

// Define the JS function signature
#[wasm_bindgen(module = "../domUtils")]
extern {
    fn appendStringToBody(s: &str);
}

#[wasm_bindgen]
pub fn run(my_text :&str) {
    // Call the JavaScript function
    #[allow(unused_unsafe)]
    unsafe {
        appendStringToBody(my_text);
    }
}
```

webpack.config.js
```javascript
const path = require("path");

module.exports = {
  entry: "./index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "index.js",
  },
  mode: "development"
};
```

index.js
```javascript
import("./pkg/my_app").then(wasmModule => {
  wasmModule.run("hi there");
});
```

index.html
```html
<!DOCTYPE html>
<html>
<head>
    <script src="./index.js"></script>
    <head>
<body></body>
<html>
```