Slide 1

Slide 1 text

The Road to WebAssembly is Paved with Rust comm t 2018 i ı

Slide 2

Slide 2 text

Software Engineer at Tuenti MadRust co-organizer Former JavaScripter  jrvidal  _rvidal

Slide 3

Slide 3 text

TOC Wasm! Rust! Rust Wasm!

Slide 4

Slide 4 text

WebAssembly is a binary instruction format for a stack-based virtual machine [...] enabling deployment on the web for client and server applications.

Slide 5

Slide 5 text

Trinity → Tetrarchy Lin Clark CC BY-SA 3.0

Slide 6

Slide 6 text

How does it look (module ;; Wasm is all about modules... (func $my_add_function (param $lhs i32) (param $rhs i32) (result i32) get_local $lhs get_local $rhs i32.add) (export "add" ;; ... that export things (func $my_add_function))) 0061736d 01000000 01070160 027f7f01 7f030201 00070701 03616464 00000a09 01070020 0020016a 0b

Slide 7

Slide 7 text

// No _yet_ const request = fetch("my-module.wasm"); const { instance, module } = await ( WebAssembly.instantiateStreaming(request) ); instance.exports.add(7, 4); // Boom How does it look (from JS)

Slide 8

Slide 8 text

Use Case: ...

Slide 9

Slide 9 text

Use Case: Portability / Extend the Web "Alfred, I want a triple-shot americano with milk" Small Medium Large Single Shot Double Shot Triple Shot Americano Cappuccino Espresso Latte Mocha Milk Cream Picovoice

Slide 10

Slide 10 text

Use Case: Portability / Extend the Web squoosh.app

Slide 11

Slide 11 text

Use Case: Portability / Extend the Web PSPDFKit

Slide 12

Slide 12 text

Use Cases: there are more! Web-as-a-Platform: "Bring your C/C++ application to the Web" Polyglot Web "Bring your favourite language to the Web" Beyond the Web Node.js Serverless Blockchain/Cryptocurrencies

Slide 13

Slide 13 text

Rust → ⚙ → Wasm

Slide 14

Slide 14 text

But first...

Slide 15

Slide 15 text

But first... (honest title) Using WebAssembly to sell you some Rust

Slide 16

Slide 16 text

Systems Programming Ring 3 Ring 2 Ring 1 Ring 0 Kernel Device drivers Applications Device drivers Least privileged Most privileged Chrislb, CC BY-SA 3.0. Hertzsprung, CC BY-SA 3.0. Virtual Machines ‐ Ravi, Nair. SimonWaldherr, CC BY-SA 4.0

Slide 17

Slide 17 text

Systems Programming for Everyone Ring 3 Ring 2 Ring 1 Ring 0 Kernel Device drivers Applications Device drivers Least privileged Most privileged Expressiveness and Abstraction Safety and Reliability Tooling and Ecosystem Community and Resources Chrislb, CC BY-SA 3.0. Hertzsprung, CC BY-SA 3.0. Virtual Machines ‐ Ravi, Nair. SimonWaldherr, CC BY-SA 4.0

Slide 18

Slide 18 text

Expressiveness and Abstraction #[derive(Deserialize)] struct IceCream { cone: String, #[serde(rename = "scoops")] scoop_flavors: Vec } let data = r#"{"cone": "waffle", "scoops": ["vanilla", "lemon"]}"#; serde_json::from_str(data)? .scoop_flavors .iter() .for_each(|flavor| { println!("{}", &flavor); });

Slide 19

Slide 19 text

Safety and Reliability let file = match File::open(file_path) { Ok(file) => file, Err(e) => return MyError::IOError }; let contents = match file.read_to_string() { Ok(text) => text, Err(e) => return MyError::EncodingError }; let pairs = vec![(0, 1), (2, 3), (4, 5)]; let first_pair = &pairs[0]; // Cannot move out of `pairs` because it is borrowed let map : HashMap = pairs.into_iter().collect(); println!("First pair was {:?}", first_pair);

Slide 20

Slide 20 text

Tooling and Ecosystem $ cargo new commitconf && cd commitconf Created binary (application) `commitconf` project $ echo 'lazy_static = "1.2.0"' >> Cargo.toml $ cargo run Updating crates.io index Compiling lazy_static v1.2.0 Compiling commitconf v0.1.0 Finished dev [unoptimized + debuginfo] target in 6.17s Running `target/debug/commitconf` Hello, world! $ cargo test # Run tests (with #[test] !!) $ cargo doc # Generate docs $ cargo fmt # Formatter / prettifier $ cargo clippy # Linter $ cargo build --target=aarch64-linux-android # X-compiling

Slide 21

Slide 21 text

Community and Resources  Docs.rs Embedded Rust, Aaron Power, CC BY 4.0. rustwasm logo, MIT. Lucy, rust-artwork, CC BY 4.0

Slide 22

Slide 22 text

Rust → ⚙ → Wasm For real now

Slide 23

Slide 23 text

pub fn add(x: usize, y: usize) -> usize { x + y } $ cargo build myWasmInstance.exports.add(2, 3); // 5! The Dream

Slide 24

Slide 24 text

pub fn add(x: usize, y: usize) -> usize { x + y // Not quite } $ cargo build myWasmInstance.exports.add(2, 3); // 5! The Dream

Slide 25

Slide 25 text

This is also part of our dream, right? // (In JS) typeof bid_farewell("Ferris") ? pub fn bid_farewell(name: String) -> String { format!("Farewell {}", &name) } // (In JS) typeof my_favourite_numbers() ??? pub fn my_favourite_numbers() -> Vec { vec![9, 42, 345234987629] } Complex Types

Slide 26

Slide 26 text

Memory is the Polyfill var memory = new Uint8Array( myWasmInstance.exports.memory.buffer ); console.log( memory.slice(address, address + length) ); memory[address] = 0x42; Based on Lin Clark, CC BY-SA 3.0

Slide 27

Slide 27 text

#[wasm_bindgen] pub fn add(x: usize, y: usize) -> usize { x + y } #[wasm_bindgen] pub fn bid_farewell(name: String) -> String { format!("Farewell {}", name) } #[wasm_bindgen] pub fn my_favourite_numbers() -> Vec { vec![9, 42, 345234987629] } wasm-bindgen to the rescue

Slide 28

Slide 28 text

#[wasm_bindgen] pub fn add(x: usize, y: usize) -> usize { x + y } $ cargo build myWasmInstance.exports.add(2, 3); // 5! The Dream (take #2)

Slide 29

Slide 29 text

#[wasm_bindgen] pub fn add(x: usize, y: usize) -> usize { x + y } $ cargo build # Not quite myWasmInstance.exports.add(2, 3); // 5! The Dream (take #2)

Slide 30

Slide 30 text

#[wasm_bindgen] pub fn add(x: usize, y: usize) -> usize { x + y } $ wasm-pack build myWasmInstance.exports.add(2, 3); // 5! The Dream (final take)

Slide 31

Slide 31 text

Getting started with wasm-pack use wasm_bindgen::prelude::*; cfg_if! { // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global // allocator. if #[cfg(feature = "wee_alloc")] { extern crate wee_alloc; #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; } } #[wasm_bindgen] extern { fn alert(s: &str); } #[wasm_bindgen] pub fn greet() { alert("Hello, hello-world!"); } 00:00

Slide 32

Slide 32 text

// webpack.config.js module.exports = { entry: "./index.js" }; // index.js import("./pkg") .then(m => m.greet()); Hello World

Slide 33

Slide 33 text

use web_sys::console; use js_sys::JsString; let greet = JsString::from("Hello, world"); console::log_1(&greet); JS interoperation

Slide 34

Slide 34 text

Parsing Exif Metadata }); } Ok(parsed_fields) } /// Attempts to parse a Tiff field value (it does not accept all Tiff value types) fn parse_exif_field_value(value: ExifValue) -> Option { let parsed = match value { ExifValue::Ascii(slices) => slices .into_iter() .filter_map(|b| std::str::from_utf8(&b).ok()) .fold(String::new(), |mut acc, piece| { acc += piece; acc }), _ => return None, }; Some(parsed) } 00:00

Slide 35

Slide 35 text

import pkg from "./pkg"; let reader = new FileReader(); reader.onload = e => { let data = new Uint8Array(e.target.result); pkg.get_exif(data, (tag, value) => { // ... }); }; reader.readAsArrayBuffer(file); Exif in Wasm

Slide 36

Slide 36 text

What if I want to use my WebAssembly from Node.js? Or if I prefer not to use a bundler? [1] What happens if I try to open a file in Rust: File::open("...")? [2] What types does wasm-bindgen support? How are types converted to JS and viceversa? [3] What is wasm-bindgen polyfilling, i.e. how will Wasm evolve in the future? [4] [5] Are there other ways to target Wasm in Rust? [6] Frinkiac

Slide 37

Slide 37 text

Further Reading The Rust and WebAssembly Book The wasm-bindgen Guide The section on web-sys The wasm-pack site and book The Rust and WebAssembly blog API documentation: wasm-bindgen, js-sys and web-sys The Rust documentation MadRust

Slide 38

Slide 38 text

Enjoy Rust and Wasm!