Wasm Spasm

I attend a tech night (geek night) with some friends. One friend was presenting how he made a real-time operating system with Rust for a simple microprocessor. This reminded me that I have been wanting to learn Rust for quite some time.

Web Assembly has been around for a couple years now. I would try and say when, but I just feel kind of lazy. The process of releasing it is kind of not normal. Anyway, ever since its release, I’ve wanted to make a hello world application.

Web Assembly is a low level binary that can be executed through the internet browser. Languages like C and Rust can target Web Assembly binaries in their compilation. This is great, because more computer resource intensive tasks can utilize Web Assembly for performance optimization.

I thought about why I would want to use Web Assembly. As a web developer, I thought it would be valuable to have a skill and to be familiar with Web Assembly from Rust compilation. I chose Rust, because it is a modern LLVM, and I do not want to pick up C considering its age (yes I know it is still really credible). Rust boasts to culimate years of low level programming experience into a great language.

So I learned eventually that I needed to install Emscripten (recently I learned that is not completely necessary anymore thanks to cutting edge Rust). I saw some tutorials of how to install Emscripten and the SDK. At the time, I found that it was probably very long to install (I say probably because I never found out). That scared me, and I stopped trying to install Emscripten. Trying to install Emscripten actually happened a couple times in the past year.

Eventually, I decided to try it again. I first went to download Emscripten from its Github source, but I while trying to activate it I found I had some versioning issues. I looked around for a solution or something different. I saw that the SDK had everything included with it and it fixed the versioning. That scared me again, because I remembered how long the install probably was. I cautiously moved forward with this attempt. Remarkably, I followed the instructions and it went without a hitch this time! This got me excited, and I tried out some simple code to see what I can do.

I found some code and a tutorial .

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#[derive(Debug)]
enum Direction { North, South, East, West }

fn is_north(dir: Direction) -> bool {
    match dir {
        Direction::North => true,
        _ => false,
    }
}

fn main() {
    let points = Direction::South;
    println!("{:?}", points);
    let compass = is_north(points);
    println!("{}", compass);
}

I added a compilation target with rustup target add wasm32-unknown-emscripten and I compiled the program with cargo build --target=wasm32-unknown-emscripten --release. I then had to make what is called JavaScript glue. There are multiple other ways to glue wasm modules to the application in JavaScript than want I have implemented here.

1
2
3
4
5
6
7
8
//In one script tag
var Module = {
    wasmBinaryFile: "wasm_demo.wasm"
}

//and another script tag to call the JavaScript glue that was
//compiled from Rust.
wasm-demo.js`

After a moment of fiddling around, I was actually able to get an output of South and false, which outputs to the internet browser. I was hysterical (no not really) when I finally achieved this. This opened up a whole new (rusty) world (web) for me. I was excited. This would certainly motivate me to dive into the Rust textbook. I want to learn more and become a full level computer programmer. All the way from high level programming to low level(ish) programming.

Rust Node FFI

Since I had learned wasm (Web Assembly), I realized that the equivalent thing can probably be done with Nodejs. There were a couple ways to link Nodejs with Rust. One through the ffi (foreign functions interface) npm library, and the other through Web Assembly again. Having done Web Assembly already, I decided to give ffi a shot. I had some code in a lib.rs, and the Cargo.toml had a crate-type specifier (I’m not sure on terminology at the moment).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//This is my lib.rs
#[no_mangle]
pub extern fn fibonacci(x: i32) -> i32 {
if x <= 2 {
    return 1;
} else {
    return fibonacci(x - 1) + fibonacci(x - 2);
}
}

#[no_mangle]
pub extern fn add(x: i32, y: i32) -> i32 {
return x + y;
}

//This is my Cargo.toml
[package]
name = "hello_cargo"
version = "0.1.0"
authors = ["andrewgremlich"]

[dependencies]

[lib]
name = "mather"
crate-type = ["dylib"]

After some more fiddling around, I eventually got the two functions I had in Rust to get invoked from the Nodejs runtime.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var ffi = require('ffi');
const path = require('path');

var lib = ffi.Library(path.join(__dirname, '../target/release/libmather'), {
add: ['int', ['int', 'int']],
fibonacci: ['int', ['int']]
});

var num = lib.add(2, 6);
var fib = lib.fibonacci(4);

console.log(num)
console.log(fib)

Now I was super excited. I wondered what I could do. I thought it possble to make an image processor progressive web application. But then I imagine making an offline progressive web application that has a wasm module had some extra details that I may not know of. I saw something over at MDN that could help. There are a lot of possibilities now! I better start learning some Rust!

Resources

WASM demo Github repository Learning rust repository