DEV Community

loading...
Cover image for 🦕🦀Writing WebAssembly in Rust and running it in Deno!

🦕🦀Writing WebAssembly in Rust and running it in Deno!

lampewebdev profile image Michael "lampe" Lazarski ・3 min read

Requirements

You need to have to follow tools installed on your machine:

  • rustc
  • rustup
  • cargo
  • deno

These are standard things you usually use while developing Rust and working with Deno.
We now need to install wasm specific tools for rust.
First we need to add a compiler target like that:

rustup target add wasm32-unknown-unknown

We also need to the wasm-gc tool

cargo install wasm-gc

I'm usuing Visual Studio Code for development and for this project I also installed the following extensions:

  • Better Toml bungcip.better-toml
  • Rust rust-lang.rust

Creating a rust lib

For the rust part, we need to create a small cargo lib.
We can do it with the following command:

cargo new --lib wasm_deno_example
cd wasm_deno_example

Next, we can open the project in VSCode
and we need to add the dependencies for wasm to our Cargo.toml.

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

cdylib makes our project usable with other languages like C or in our case wasm. It also removes all the specific stuff that is needed for rust.

Our small rust function

We now will change the src/lib.rs file to the following code:

#[no_mangle]
pub extern "C" fn square(x: u32) -> u32 {
    x * x
}

This is a simple function that takes a number and returns a number.
Important here is that we add the extern keyword so this function can be imported in our Deno code. When you are reading post liks this you should understand the x * x 😉

Compiling the rust to wasm

Now we can compile our rust code to wasm code.
We first need to compile build it with the following command:

$ cargo build --target wasm32-unknown-unknown

And we also need to strip it down from all the stuff we dont need. This will remove all the unneeded code for wasm and make the file way smaller.

wasm-gc target/wasm32-unknown-unknown/debug/wasm_deno_example.wasm

That's it we now have a wasm binary ready to be loaded into Deno and executed.

Run it with Deno

We now need to create a main.ts. The name of the does not really matter it's just the one I will use here.

When we need to add the following code to the file.

const wasmCode = await Deno.readFile("./target/wasm32-unknown-unknown/debug/wasm_deno_example.wasm");
const wasmModule = new WebAssembly.Module(wasmCode);
const wasmInstance = new WebAssembly.Instance(wasmModule);
const {
    square,
} = wasmInstance.exports;

console.log(square(1));
console.log(square(2));
console.log(square(3));
console.log(square(4));

Let us go through the steps.

  • 1. Simple loads the raw file.
  • 2. Makes a wasm module out of our file. So that we can work with it.
  • 3. Creates an instance of our module so that we can use the functions.
  • 4. We are importing our wasm square() function into our Deno code.
  • 5. We are console logging the square number of different numbers.

Now let's execute this code with

deno run --allow-read main.ts

The output should be the following:

1
4
9
16

The Repo

You can find the code in the following Repo

Would you like to see more Deno content? Please let me know! I would like to make more posts and content about Deno!

👋Say Hello! Instagram | Twitter | LinkedIn | Medium | Twitch | YouTube

Discussion (19)

pic
Editor guide
Collapse
terkwood profile image
Felix Terkhorn

Perfect timing 🌟

Collapse
lampewebdev profile image
Michael "lampe" Lazarski Author

Nice! Hope it will help 😄👍

Collapse
terkwood profile image
Felix Terkhorn

Absolutely!! I need to dig in on your finer grained details here, but this effort is on my shorter lists 📃 🏁 Thank you

Thread Thread
lampewebdev profile image
Michael "lampe" Lazarski Author

Glad if I can help at least a little bit 😄👍

Thread Thread
terkwood profile image
Felix Terkhorn • Edited

I followed along and it was completely painless!

Added a build script written using DENO to wrap up your two example commands with a pleasantly chmod 755'd interface.

Thanks again for contributing this!

(I keep most of my work public, but declined to put a license on my repo, since I didn't see one posted on yours. Didn't wanna step on your toes! Cheers)

Thread Thread
lampewebdev profile image
Michael "lampe" Lazarski Author

Nice!

I will add a MIT Liecence now ;)
I always forget that :D

Collapse
shaijut profile image
Shaiju T

😄 Nice, I have not learned Node.js yet, So were should I start Node.js or Deno ?

Collapse
lampewebdev profile image
Michael "lampe" Lazarski Author

Hey,
They share a lot of concepts and a lot of ideas and also code.
So I would start with the nodejs basics because you just have more learning material out on the internet but I would learn the basics so you can easy transfare your knowledge later to Deno.

Collapse
waylonwalker profile image
Waylon Walker

The wasm support in deno looks top notch.

Collapse
lampewebdev profile image
Michael "lampe" Lazarski Author

Indeed it is super easy :D

Collapse
reselbob profile image
Bob Reselman • Edited

This is a great intro to using Deno and WebAssembly. It makes the basic concepts very easy to understand. Thanks for making this contribution.

Collapse
lampewebdev profile image
Collapse
reselbob profile image
Bob Reselman

You inspired me! Thus I transcribed your lesson into a Katacoda scenario.

katacoda.com/reselbob/scenarios/de...

Of course, I give you full credit for the inspiration.

Collapse
ben profile image
Ben Halpern

Dang, this is super interesting

Collapse
terkwood profile image
Felix Terkhorn • Edited

Yah, thinking about optimized hotspots here 🌟

Our hope is that the dev flow with Deno is significantly faster than rust, in terms of satisfying the compiler's requirements and (we think) actually waiting for compilation to finish. Rust compilation is very slow, especially in release mode.

Perhaps there's a nice use case for quickly writing a bunch of typescript and then swapping out rust in targeted sections. At least in theory.

The wasm support in Deno prevents this from feeling like a snobbish hack!

Collapse
lampewebdev profile image
Collapse
shaijut profile image
Shaiju T

Hi typo in title, should be running isn't?

Collapse
lampewebdev profile image
Collapse
chadbr profile image
chadbr • Edited

Silly question — how do you do two functions? Keep adding to the wasmInstance.exports definition? Is it doing name matching? Ordered by function order in the Rust file?