Introduction to WebAssembly(Wasm) with Rust for Beginners

Introduction to WebAssembly(Wasm) with Rust for Beginners

Practical Introduction of WebAssembly/Wasm to Beginners with Rust Programming using wasm-pack and wasm-bindgen crates.

ยท

5 min read

Introduction

WebAssemly also known as WASM, is a technology that enables developers to run a set of code on a web browser with native-like performance. It is low-level assembly-like code that runs in the browser alongside JavaScript to achieve performance.

As we all know in terms of performance lower level languages are the fastest like Binary, Assembly language, Higher level languages like C, C++, JavaScript, Python, Java, Ruby, Rust, Swift, and all that most of us use for daily purpose programming. Because these are more human-friendly than machines. There are a set of tools like interpreters, compilers, assemblers and others which convert these languages into machine code to make this understandable to real hardware.

There are programming languages in which we can write our code and ship WebAssembly or Binary(WASM) files. Majorly used ones are Rust, TinyGo(Go), Emscripten(C/C++), and AssemblyScript. All of these languages are known for better performance and memory optimization.

We will use Rust language as a compilation target for our demo of programming.

Demo

Installation

cargo install wasm-pack

In this cargo is a Rust package manager just like npm in node. In Rust, libraries are known as crates like packages in Node. Here above command will install (wasm-pack)[github.com/rustwasm/wasm-pack] crate/lib in our system.

Initialization

Create a new directory and go to that directory.

mkdir wasm-rust-demo && cd wasm-rust-demo
Create Cargo Package.
cargo init

Above command will create Cargo.toml manifest file(similar like package.json in node) and src directory with main.rs basic rust file.

Edit Cargo.toml

Paste the below code in the Cargo.toml file. It defines crate-type as cdylib, which is used when compiling a dynamic library which needs to be loaded from another language like JavaScript in our case. It includes dependency as wasm-bindgen. This crate/package provides communication between Rust and JavaScript with other features.

[package]
name = "wasm-rust-demo"
version = "0.1.0"
authors = ["Piyush Goyani <thesourcepedia@gmail.com>"]
edition = "2021"

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

[dependencies]
wasm-bindgen = "0.2"

Go to the src/ directory, rename main.rs to lib.rs, and add the following content.

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn calc(a: i32, b: i32, op: char) -> i32 {
    if op == '+' {
        return a + b;
    } else if op == '-' {
        return a - b;
    } else if op == '*' {
        return a * b;
    } else if op == '/' {
        return a / b;
    } else {
        return 0;
    }
}

Here we are defining a Rust function named calc which takes three parameters, two numbers and 3rd for an operator to perform math action and return the result.

Build

 wasm-pack build --target web

This command will compile Rust code to wasm and generate a pkg directory which can be published to npm as a package and provides files which can be used in JavaScript communication.

Package Directory Content

Error during build

[INFO]: Installing wasm-bindgen...

Error: failed to download from github.com/WebAssembly/binaryen/releases/do..

To disable wasm-opt, add wasm-opt = false to your package metadata in your Cargo.toml.

Add this line in Cargo.toml

[package.metadata.wasm-pack.profile.release]
wasm-opt = false

Running WebAssembly/WASM Code.

1. By Loading Generated JS package

<script type="module">
        import init, { calc } from "./pkg/wasm_with_rust.js"
        init().then(() => {
            console.log(calc(10, 2, "+")) // 12
            console.log(calc(10, 2, "-")) // 8
            console.log(calc(10, 2, "*")) // 20
            console.log(calc(10, 2, "/")) // 5
        })
</script>

In this, we are loading a javascript file which is generated from wasm-pack which does all the job of loading WebAssembly code and all complex memory-related stuff and export functions that we wrote in Rust(e.g calc()) and init() to initialize WebAssembly. In this, we are passing two integer parameters and 3rd is an operator which decides which math operation to perform.

2. By Directly loading .wasm Binary file

<script>
  WebAssembly.instantiateStreaming(fetch('./pkg/wasm_with_rust_bg.wasm'))
  .then((results) => {
            const calc = results.instance.exports.calc
            console.log(calc(10, 2, 43)) // 12
            console.log(calc(10, 2, 45)) // 8
            console.log(calc(10, 2, 42)) // 20
            console.log(calc(10, 2, 47)) // 5
        })
</script>

In this, we are loading the wasm binary file directly which is compiled from wasm-pack. We are loading using fetch and instantiate using instantiateStreaming() method of WebAssembly class available globally. Here we are passing the same parameter as above but as you can see 3rd parameter is numeric. That is ASCII value of operator respectively. Here we can not pass string value because are not passing it to JavaScript so it can further convert to Machine Code, but Passing it to directly WASM file.

You can see the WASM Machine code that looks like below. WASM Code

Source Repo & Local Setup

git clone https://github.com/piyush-multiplexer/wasm-with-rust.git
cd wasm-with-rust
cargo install wasm-pack
wasm-pack build --target web
serve .

Resources on WebAssembly

Advantages

  • The Memory of WebAssembly is Linear. It is an expandable continuous buffer of unsigned bytes that can be read and stored from JavaSCript and WASM synchronously.
  • Can import JavaScript functions and export custom function logic specified in WASM.
  • Compiled to Binary file, Assembly-like language which gives native speed and performance in the browser.
  • and many more based on requirements.

Conclusion

In this tutorial, you get the basic idea of what is WebAssebly or wasm is, its purpose, make wasm binary from Rust Language and how to use it with JavaScript. I hope you enjoyed it give it a thumb, share, and subscribe. Have any doubts or thoughts share them in the comment section below. I am available here.

Did you find this article valuable?

Support TheSourcePedia's Blog by becoming a sponsor. Any amount is appreciated!

ย