Skip to content

Instantly share code, notes, and snippets.

@belsrc
Last active October 10, 2023 14:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save belsrc/5588a45fba849b8d38553e8afddd2029 to your computer and use it in GitHub Desktop.
Save belsrc/5588a45fba849b8d38553e8afddd2029 to your computer and use it in GitHub Desktop.
WIP Rust/WASM learn

Rust Data Types

https://doc.rust-lang.org/rust-by-example/primitives.html

https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/primitive-types.html

Scalar Values
Signed Integers i8, i16, i32, i64, i128 and isize (architecture pointer size) let x: i32 = -42;
Unsigned Integers u8, u16, u32, u64, u128 and usize (architecture pointer size) let x: u32 = 42;
Floating Point f32, f64 let y: f64 = 1.0;
Unicode (4 bytes) char let x: char = 'x';
String str let x: &'static str = "Hello there.";
Boolean bool let z: bool = false;
Unit () (only possible value is an empty tuple) ()
Compound Values
Array [T, len] let a: [i32; 3] = [1, 2, 3];
Tuple (T1, T2, ...) let x: (i32, &str) = (1, "hello");

Integers can, alternatively, be expressed using hexadecimal, octal or binary notation using these prefixes respectively: 0x, 0o or 0b. 0x80 or 0b0011 as examples.

Arrays are created using brackets [], and their length, which is known at compile time, is part of their type signature [T; length].

wasm-bindgen Input/Return Data Types

https://rustwasm.github.io/docs/wasm-bindgen/reference/types.html

Rust/bindgen type T param &T param &mut T param T return Option<&T> param Option<T> return JS Type
JsValue any
Box<[JsValue]> any[]
*const T / *mut T number
(Un)Signed / Float number
bool boolean
char string
str string
String string
Number Slice ([u16]) TypedArray
Boxed Number Slice TypedArray
Result<T, JsValue> T / Error

† : The Result type can be returned from functions exported to JS as well as closures in Rust. Only Result<T, JsValue> is supported where T can be converted to JS. Whenever Ok(val) is encountered it's converted to JS and handed off, and whenever Err(error) is encountered an exception is thrown in JS with error.

General Rust Notes

  • Variable bindings are immutable by default, but this can be overridden using the mut modifier.
let _immutable_binding = 1;
let mut mutable_binding = 1;
  • Rust provides no implicit type conversion (coercion) between primitive types. But, explicit type conversion (casting) can be performed using the as keyword.
let decimal = 65.4321_f32;
let integer = decimal as u8;
let character = integer as char;
  • When casting any value to an unsigned type, T, T::MAX + 1 is added or subtracted until the value fits into the new type. Under the hood, the first 8 least significant bits (LSB) are kept, while the rest towards the most significant bit (MSB) get truncated.

  • Numeric literals can be type annotated by adding the type as a suffix. As an example, to specify that the literal 42 should have the type i32, write 42i32. The type of unsuffixed numeric literals will depend on how they are used. If no constraint exists, the compiler will use i32 for integers, and f64 for floating-point numbers.

  • The type inference engine is pretty smart. It does more than looking at the type of the value expression during an initialization. It also looks at how the variable is used afterwards to infer its type.

  • Slices are similar to arrays, but their length is not known at compile time. Instead, a slice is a two-word object; the first word is a pointer to the data, the second word the length of the slice. Slices can point to a section of an array. They are of the form [starting_index..ending_index]. starting_index is the first position in the slice. ending_index is one more than the last position in the slice.

// Given
let xs: [i32; 5] = [1, 2, 3, 4, 5]; 

// The Slice
&xs[1 .. 3];
  • let can be used to bind the members (spread) of a tuple to variables.
fn reverse(pair: (i32, bool)) -> (bool, i32) {
    let (int_param, bool_param) = pair;

    (bool_param, int_param)
}
  • There are three types of structures that can be created using the struct keyword:

    1. Tuple structs, which are, basically, named tuples.
    struct Pair(i32, f32);
    
    1. Unit structs, which are field-less, are useful for generics.
    struct Unit;
    
    1. The classic C structs
    struct Point {
      x: f32,
      y: f32,
    }
    
  • The enum keyword allows the creation of a type which may be one of a few different variants. Any variant which is valid as a struct is also valid in an enum.

enum WebEvent {
  // An `enum` variant may either be `unit-like`,
  PageLoad,
  PageUnload,
  // like tuple structs,
  KeyPress(char),
  Paste(String),
  // or c-like structures.
  Click { x: i64, y: i64 },
}
  • enum can also be used as C-like enums.
// enum with implicit discriminator (starts at 0)
enum Number {
  Zero,
  One,
  Two,
}
  • The use declaration can be used so manual scoping isn't needed
  // Explicitly `use` each name so they are available without
  // manual scoping.
  use crate::Status::{Poor, Rich};

  // Automatically `use` each name inside `Work`.
  use crate::Work::*;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment