# Introduction to WebAssembly(Wasm) with Rust for Beginners

### 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**)[https://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**](https://github.com/rustwasm/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](https://cdn.hashnode.com/res/hashnode/image/upload/v1661760197249/cQ9TyJShs.png align="center")

##### Error during build
> [INFO]: Installing wasm-bindgen...

> Error: failed to download from https://github.com/WebAssembly/binaryen/releases/download/version_90/binaryen-version_90-x86-linux.tar.gz

> 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
```javascript
<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
```javascript
<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](https://cdn.hashnode.com/res/hashnode/image/upload/v1661762897772/2YH4xwZ0d.png align="center")

#### [Source Repo & Local Setup](https://github.com/piyush-multiplexer/wasm-with-rust)
```
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
- [WebAssembly](https://webassembly.org/)
- [WebAssembly on MDN](https://developer.mozilla.org/en-US/docs/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.](https://hashnode.com/@piyushgoyani)
