Rust Snippets


String slice && reference

  • Array : is a collection of objects of same type T
  • Slice : similar to array, but their length is unknown at compile time

Scoping rules

  • RAII
  • Ownership and moves resources can only have one owner. So traditional variable assignment can only be move or reference or copy.
    • Mutability: mutability can changes when the variable is moved to another owner.
      1
      2
      3
      let a = Box::new(2);
      let mut b = a; // move Box to b
      *b = 4; // it's ok.
    • Partial moves:

Borrowing

  • mutable data can be borrowed immutably
  • immutable data cannot be borrowed mutably

Ref pattern

  • In assignment:
1
2
3
let c:char = 'A';
let ref a = c;
let b = &c; // *a == *b
  • In pattern destructuion
1
2
3
4
5
6
7
8
9
10
let point = Point{x:2,y:4};
let mut mutable_point = point;

{
// `ref` can be paired with `mut` to take mutable references.
let Point { x: _, y: ref mut mut_ref_to_y } = mutable_point;

// Mutate the `y` field of `mutable_point` via a mutable reference.
*mut_ref_to_y = 1;
}
1
2
3
4
5
6
let mut mutable_tuple = (Box::new(5u32), 3u32);
{
// Destructure `mutable_tuple` to change the value of `last`.
let (_, ref mut last) = mutable_tuple;
*last = 2u32;
}

Snippets

Size of variable

1
println!("array occupies {} bytes", mem::size_of_val(&arr));

Iterate over Vector

With indexed position

1
2
3
4
let v = vec![1; 10];
for (pos, e) in v.iter().enumerate() {
println!("Element at position {}: {:?}", pos, e);
}

With iterator

1
2
3
4
for it in v.iter() {
// it is type of `&str`
println!("{}",it);
}

data type conversion that narrows down the range of value

https://doc.rust-lang.org/std/convert/trait.TryFrom.html

  • try_from(var)Result
  • try_from(var).ok()Option

Example:

1
2
3
fn example(v: i32) -> Option<usize> {
usize::try_from(v).ok()
}

Generate iterator step_by 2.

1
2
3
4
5
pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T> {
iter.enumerate()
.filter(|(i,e)| i %2 == 0)
.map(|(i,e)| e)
}

Box, ref, & and *

  • Box: a library-defined smart pointer type
  • ref: a syntax for pattern matching
1
2
3
4
5
&T        - immutable (shared) reference
&mut T - mutable (exclusive) reference

*const T - immutable raw pointer
*mut T - mutable raw pointer

Both references and raw pointers can be created using & operator:

1
2
3
4
5
6
7
let x: u32 = 12;

let ref1: &u32 = &x;
let raw1: *const u32 = &x;

let ref2: &mut u32 = &mut x;
let raw2: *mut u32 = &mut x;

. automatically references or dereferences its left argument

1
2
3
4
5
struct X { n: u32 };

impl X {
fn method(&self) -> u32 { self.n }
}
  • we don’t have to type (*self).method but using self.method instead.

Reference && Pointers

  • Main pointer kind used in rust should be references
  • Raw pointers, which don’t have restrictions or references, should be used in low-level code implementing high-level abstractions

Dynamically-sized (unsized) types

A fat pointer is basically a structure which contains the actual pointer to the piece of data and some additional information(length for slices, pointer to vtable for traits objects. Rust handles these details about pointer content transparently for the user.

Box<T>

  • can be borrowed
  • is equivalent to T
  • similar to built-in pointers, * to dereference

ref

ref is a syntax in patterns to obtain a variable of the reference type instead of a value

Case 1

1
2
3
4
5
let x: u32 = 12;

let y = x; // y: u32, a copy of x
let ref z = x; // z: &u32, points to x
let ref mut zz = x; // zz: &mut u32, points to x

can be over rewritten with:

1
2
let z = &x;
let zz = &mut x;

Case 2

1
2
3
4
5
6
let x: Option<Vec<u32>> = ...;

match x {
Some(ref v) => ...
None => ...
}

x is only borrowed inside the whole match statement, which allows using x after this match

1
2
3
4
match x {
Some(v) => ...
None => ...
}

if using this, part of x value are moved.

  • Some(v)

  • Some(&v)

  • Some(ref v)

  • move and copy

From Range to Vec

1
2
3
let v = (1..10).collect::<Vec<u32>>();
// or ??
let v:Vec<u32> = (1..10).collect();

From &[i32] to Vec

1
to_vec();

Vec use case


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
pub struct HighScores {
v:Vec<u32>
}

impl HighScores {
pub fn new(scores: &[u32]) -> Self {
let mut v:Vec<u32> = Vec::new();
v = scores.to_vec();
if scores.len() == 0 {
HighScores {last_added: 0, v}
} else {
HighScores { last_added:*scores.get(scores.len()-1).unwrap_or(&0), v }
}
}

pub fn scores(&self) -> &[u32] {
&self.v[..]
}

pub fn latest(&self) -> Option<u32> {
if self.v.len() == 0 {
None
} else {
Some(self.last_added)
}
}

pub fn personal_best(&self) -> Option<u32> {
if self.v.len() == 0 {
None
} else {
let mut v = self.v.clone();
v.sort();
Some(v[v.len()-1])
}
}

pub fn personal_top_three(&self) -> Vec<u32> {
let mut v:Vec<u32> = Vec::new();
// let mut i = 0;
let mut tmp = self.v.clone();
tmp.sort();
for i in 1..=3 {
if tmp.len() < i {
continue;
}
let val = tmp.get(tmp.len()-i).unwrap();
v.push(*val);
}
v
}
}

Things to do to simplify the code:

  • map Option<&T> to Option<T>
    1
    2
    let v:Vec<i32> = Vec::new();
    v.last().cloned() // ->Option<T>
  • get last element of Vector
    1
    v.iter().last()
  • get the max element of vector
    1
    v.iter().max()
  • get the max 3 element of vector
    1
    2
    3
    4
    let mut res_vec = self.scores.to_vec();
    res_vec.sort_unstable_by(|a, b| b.cmp(a));
    res_vec.truncate(3);
    res_vec

Custom keys that put into hash function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use std::hash::{Hash, Hasher};

struct Person {
id: u32,
name: String,
phone: u64,
}

impl std::hash::Hash for Person {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
self.phone.hash(state);
}
}

How to implement Eq and Hash for my own structs to use them as a HashMap key?

indexing string

How to index a String in Rust

Find min and max value in HashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use std::collections::HashMap;

fn example<K, V>(a_hash_map: &HashMap<K, V>) -> Option<&K>
where
V: Ord,
{
a_hash_map
.iter()
.max_by(|a, b| a.1.cmp(&b.1))
.map(|(k, _v)| k)
}

fn main() {
let map: HashMap<_, _> = vec![(2, 4), (1, 3), (5, 2)].into_iter().collect();
dbg!(example(&map));
}

How do I get the key associated with the maximum value of a Rust HashMap?

Split string and use case of std::str::pattern

1
2
3
4
5
6
let mut iter = "A few words".split(' ');
// or .split_ascii_whitespace();

assert_eq!(Some("A"), iter.next());
assert_eq!(Some("few"), iter.next());
assert_eq!(Some("words"), iter.next());

split method takes a Pattern as an argument. It can be numerous forms.

Example:

1
2
3
4
5
6
7
8
9
10
let s = "Can you find a needle in a haystack?";

// &str pattern
assert_eq!(s.find("you"), Some(4));
// char pattern
assert_eq!(s.find('n'), Some(2));
// slice of chars pattern
assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u'][..]), Some(1));
// closure pattern
assert_eq!(s.find(|c: char| c.is_ascii_punctuation()), Some(35));

Iterate over Enum

turn enum into array and implement iterator trait

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use self::Color::*;
use std::slice::Iter;
pub enum Color {
Red,
Blue,
Green,
Purple
}
impl Color {
pub fn iterator() -> Iter<'static, Color> {
static COLORS: [Color; 4] = [Red,Blue,Green,Purple];
COLORS.iter()
}
}

associated constant

1
2
3
4
5
6
7
8
9
10
11
12
13
pub enum Color {
Red,
Blue,
Green,
Purple
}
impl Color {
const VALUES: [Color; 4] = [Self::Red,Self::Blue,Self::Green,Self::Purple];
}
// iterate with..
for c in Color::VALUES.iter() {
println!("{:#?}",c);
}

HashMap Example

initialize HashMap using macro-like declaration

1
2
3
4
5
let table:HashMap<char,u64> = [
('A',1),
('E',1),
('I',1),
('O',1)].iter().cloned().collect();

From Zip

1
2
3
4
5
6
7
8
let k = vec![1,2,3,4];
let v = vec![2,4,6,8];

let hm:HashMap<i32,i32> = k.iter()
.zip(v.iter())
.map(|a| (*a.0,*a.1))
.collect();
println!("{:?}",hm);