Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Road to WebAssembly is Paved with Rust

rvidal
November 25, 2018

The Road to WebAssembly is Paved with Rust

A summary of what is WebAssembly, what is the Rust programming language and what are its strenghts, and how to use the latter to target the former.

rvidal

November 25, 2018
Tweet

More Decks by rvidal

Other Decks in Programming

Transcript

  1. WebAssembly is a binary instruction format for a stack-based virtual

    machine [...] enabling deployment on the web for client and server applications.
  2. 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
  3. // No <script type="wasm"> _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)
  4. 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
  5. 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
  6. 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
  7. 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
  8. Expressiveness and Abstraction #[derive(Deserialize)] struct IceCream { cone: String, #[serde(rename

    = "scoops")] scoop_flavors: Vec<String> } let data = r#"{"cone": "waffle", "scoops": ["vanilla", "lemon"]}"#; serde_json::from_str(data)? .scoop_flavors .iter() .for_each(|flavor| { println!("{}", &flavor); });
  9. 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<u32, u32> = pairs.into_iter().collect(); println!("First pair was {:?}", first_pair);
  10. 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
  11. Community and Resources  Docs.rs Embedded Rust, Aaron Power, CC

    BY 4.0. rustwasm logo, MIT. Lucy, rust-artwork, CC BY 4.0
  12. pub fn add(x: usize, y: usize) -> usize { x

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

    + y // Not quite } $ cargo build myWasmInstance.exports.add(2, 3); // 5! The Dream
  14. 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<u32> { vec![9, 42, 345234987629] } Complex Types
  15. 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
  16. #[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<u32> { vec![9, 42, 345234987629] } wasm-bindgen to the rescue
  17. #[wasm_bindgen] pub fn add(x: usize, y: usize) -> usize {

    x + y } $ cargo build myWasmInstance.exports.add(2, 3); // 5! The Dream (take #2)
  18. #[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)
  19. #[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)
  20. 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
  21. // webpack.config.js module.exports = { entry: "./index.js" }; // index.js

    import("./pkg") .then(m => m.greet()); <!-- index.html --> <body> <script src="./main.js"></script> </body> Hello World
  22. 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<String> { 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
  23. 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
  24. 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
  25. 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