Rust Basics for Wasm
Why learn Rust basics?
You don't need to master all of Rust to use WebAssembly. This lesson covers the minimal subset you'll use in every Wasm project.
Functions
Rust functions use fn, explicit types, and the last expression (without ;) is the return value:
fn multiply(a: i32, b: i32) -> i32 {
a * b // returned implicitly
}Imports: use, ::, and *
You'll see this line at the top of every Wasm file:
use wasm_bindgen::prelude::*;Let's break it down piece by piece:
use — bring items into scope
use is like import in JavaScript. Without it, you'd have to write the full path every time:
// Without use: verbose
wasm_bindgen::prelude::wasm_bindgen
// With use: clean
use wasm_bindgen::prelude::*;
#[wasm_bindgen] // now available directly:: — path separator
:: navigates through modules (like / in a file path or . in JavaScript):
// crate::module::submodule::item
use wasm_bindgen::prelude::*;
// ^^^^^^^^^^^^ ^^^^^^^ ^
// crate name module everything in it
use std::collections::HashMap;
// ^^^ ^^^^^^^^^^^ ^^^^^^^
// std module specific type
use web_sys::Document;
// ^^^^^^^ ^^^^^^^^
// crate specific typeThink of it as: crate_name::module::Item
* — glob import (everything)
* imports all public items from a module:
use wasm_bindgen::prelude::*; // imports everything from preludeThis is common for "prelude" modules — they're curated sets of the most-used items. wasm_bindgen::prelude::* gives you:
#[wasm_bindgen]attributeJsValuetypeJsCasttrait (fordyn_into())- And other essentials
You can also import specific items instead:
// Import only what you need
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue;
// Or group imports with braces
use web_sys::{Document, Element, Window};
// ^^^^^^^^ ^^^^^^^ ^^^^^^
// three specific types from web_sysCommon import patterns in Wasm
// The essentials (in almost every file)
use wasm_bindgen::prelude::*;
// Specific web APIs
use web_sys::{Document, Element, HtmlCanvasElement};
// JavaScript built-in types
use js_sys::{Array, Object, JSON};
// Closures for event handlers
use wasm_bindgen::closure::Closure;
// Async support
use wasm_bindgen_futures::JsFuture;Complete Wasm Type Reference
These are all the types you can pass between Rust and JavaScript through wasm-bindgen:
Primitives (zero-cost — passed directly through Wasm)
| Rust | JavaScript | Notes |
|---|---|---|
i8, i16, i32 |
number |
Signed integers |
u8, u16, u32 |
number |
Unsigned integers |
i64, u64 |
BigInt |
64-bit integers map to BigInt, not number |
isize, usize |
number |
Platform-sized integers (32-bit in Wasm) |
f32, f64 |
number |
Floating point |
bool |
boolean |
|
char |
string |
Single Unicode character |
Strings (copied across the Wasm boundary)
| Rust | JavaScript | Direction | Notes |
|---|---|---|---|
&str |
string |
JS → Rust | Borrowed, read-only. JS string is encoded to UTF-8 |
String |
string |
Rust → JS | Owned. UTF-8 bytes decoded back to JS string |
Typed Arrays (copied or zero-copy via views)
| Rust | JavaScript | Notes |
|---|---|---|
Vec<u8>, &[u8] |
Uint8Array |
Byte buffers, file data |
Vec<i8>, &[i8] |
Int8Array |
|
Vec<u16>, &[u16] |
Uint16Array |
|
Vec<i16>, &[i16] |
Int16Array |
|
Vec<u32>, &[u32] |
Uint32Array |
|
Vec<i32>, &[i32] |
Int32Array |
|
Vec<f32>, &[f32] |
Float32Array |
Graphics, audio data |
Vec<f64>, &[f64] |
Float64Array |
Physics simulations |
Vec<u64>, &[u64] |
BigUint64Array |
|
Vec<i64>, &[i64] |
BigInt64Array |
Complex Types
| Rust | JavaScript | Notes |
|---|---|---|
JsValue |
any |
Catch-all for any JS value |
Option<T> |
T | undefined |
None becomes undefined |
Result<T, JsValue> |
T (throws on Err) |
Errors become JS exceptions |
#[wasm_bindgen] struct |
class |
Exported as a JS class, pointer-based (no copy) |
Box<[JsValue]> |
Array |
JS array of any values |
Closure<dyn FnMut()> |
Function |
Rust closures as JS callbacks |
js-sys Built-in Types
Rust (js_sys::) |
JavaScript | Notes |
|---|---|---|
js_sys::Array |
Array |
Full Array API |
js_sys::Object |
Object |
Generic JS object |
js_sys::Map |
Map |
|
js_sys::Set |
Set |
|
js_sys::Date |
Date |
|
js_sys::RegExp |
RegExp |
|
js_sys::Promise |
Promise |
Use with wasm-bindgen-futures |
js_sys::Function |
Function |
Callable JS function |
js_sys::Uint8Array |
Uint8Array |
Zero-copy view into Wasm memory |
Structs
Structs are Rust's version of classes. You'll export these to JavaScript as Wasm objects:
struct GameState {
score: u32,
level: u32,
}
impl GameState {
fn new() -> Self {
Self { score: 0, level: 1 }
}
fn add_points(&mut self, points: u32) {
self.score += points;
}
}Ownership & Borrowing (simplified)
The one Rust concept that trips people up. For Wasm, you need to know:
&str— borrow a string (read-only, cheap)String— own a string (can modify, must allocate)&self— method borrows the struct (read-only)&mut self— method borrows the struct (can modify)
fn print_name(name: &str) { // borrows, doesn't own
println!("Name: {}", name);
}
fn make_greeting(name: &str) -> String { // returns owned String
format!("Hello, {}!", name)
}Error handling: Option and Result
Wasm functions that can fail should return Result<T, JsValue>:
// Option: value might not exist
fn find_user(id: u32) -> Option<String> {
if id == 1 { Some("Alice".to_string()) } else { None }
}
// Result: operation might fail (in Wasm, use JsValue for errors)
fn parse_number(s: &str) -> Result<i32, String> {
s.parse::<i32>().map_err(|e| e.to_string())
}Try It
Click Run to see all the examples in action. Try modifying the code — add a new method to Point or change the greet function.
Try It
Chapter Quiz
Pass all questions to complete this lesson