Rust Cheatsheet

This is a cheatsheet for rust.

Installation

sudo apt update && sudo apt install cargo -y

Hello World

# Create a new project first. cargo new hello_world
# Go to the project dir. cd hello_world
# Compile the source code. cargo build
# Run the code cargo run

Source Code

The source code of the hello world program is

fn main() { println!("Hello, world!"); }

Basics

Variables

x : i32 = 1; // An i32 variable.
x : bool = true; // A boolean variable.
x : f32 = 1.2; // A float 32 variable.

All variable data types:

DataTypeDescription
boolThe boolean type.
charA character type.
i8The 8-bit signed integer type.
i16The 16-bit signed integer type.
i32The 32-bit signed integer type.
i64The 64-bit signed integer type.
isizeThe pointer-sized signed integer type.
u8The 8-bit unsigned integer type.
u16The 16-bit unsigned integer type.
u32The 32-bit unsigned integer type.
u64The 64-bit unsigned integer type.
usizeThe pointer-sized unsigned integer type.
f32The 32-bit floating point type.
f64The 64-bit floating point type.
arrayA fixed-size array, denoted [T; N], for the element type, T, and the non-negative compile-time constant size, N.
sliceA dynamically-sized view into a contiguous sequence, [T].
strString slices.
tupleA finite heterogeneous sequence, (T, U, ..).

Functions

pub fn foo(x: i32, y: i32) -> i32 { x + y }

Control Flow

If

if x > 0 { ... } else { ... }

Loops

// For loop. for i in iterator { ... }
// While loop. let i = 0 while i < 10 { ... i += 1; }

Structs And Traits

// Defining structs. pub struct Base { a: i32, b: i32, c: i32, }
pub struct Derived1 { base: Base, d: i32, }
pub struct Derived2 { base: Base, e: i32, }
// Defining traits. pub trait BaseTrait { fn a(&self) -> i32; fn b(&self) -> i32; fn c(&self) -> i32; }
pub trait Derived1Trait : BaseTrait { fn d(&self) -> i32; }
pub trait Derived2Trait : BaseTrait { fn e(&self) -> i32; }
// Implementations. impl BaseTrait for Derived1 { fn a(&self) -> i32 { self.base.a } fn b(&self) -> i32 { self.base.b } fn c(&self) -> i32 { self.base.c } }
impl Derived1Trait for Derived1 { fn d(&self) -> i32 { self.d } }
impl BaseTrait for Derived2 { fn a(&self) -> i32 { self.base.a } fn b(&self) -> i32 { self.base.b } fn c(&self) -> i32 { self.base.c } }
impl Derived2Trait for Derived2 { fn e(&self) -> i32 { self.e } }

Enums

enum IpAddrKind { V4, V6, }

References

let data: DataType = DataType::new();
// Create a reference. let data_ref: &DataType = &data;
// Create a mutable reference. let mut data_mut_ref: &DataType = &data;

Smart Pointers

Smart pointers allow us to define data on heap instead of stack.

Box<T>

Define a single owner smart pointer.

let data: Box<DataType> = Box::new(DataType::new());

Rc<T>

Define a multi-owners smart pointer.

use std::rc::Rc; let data: Rc<DataType> = Rc::new(DataType::new());

Ref<T> and RefCell<T>

use std::rc::Rc; use std::cell::RefCell;
let data: Box<RefCell<DataType>> = Box::new(RefCell::new(DataType::new()));
// Get a reference. let data_ref = data.borrow();
// Get an immutable reference. let data_mut_ref = data.borrow_mut();

Common Data Structures

Vector<T>

let mut vec = Vec::new(); vec.push(1); vec.push(2);
assert_eq!(vec.len(), 2); assert_eq!(vec[0], 1);
assert_eq!(vec.pop(), Some(2)); assert_eq!(vec.len(), 1);
vec[0] = 7; assert_eq!(vec[0], 7);
vec.extend([1, 2, 3]);
for x in &vec { println!("{x}"); } assert_eq!(vec, [7, 1, 2, 3]);

HashMap<K, V>

use std::collections::HashMap;
// Type inference lets us omit an explicit type signature (which // would be `HashMap<String, String>` in this example). let mut book_reviews = HashMap::new();
// Review some books. book_reviews.insert( "Adventures of Huckleberry Finn".to_string(), "My favorite book.".to_string(), ); book_reviews.insert( "Grimms' Fairy Tales".to_string(), "Masterpiece.".to_string(), ); book_reviews.insert( "Pride and Prejudice".to_string(), "Very enjoyable.".to_string(), ); book_reviews.insert( "The Adventures of Sherlock Holmes".to_string(), "Eye lyked it alot.".to_string(), );
// Check for a specific one. // When collections store owned values (String), they can still be // queried using references (&str). if !book_reviews.contains_key("Les Misérables") { println!("We've got {} reviews, but Les Misérables ain't one.", book_reviews.len()); }
// oops, this review has a lot of spelling mistakes, let's delete it. book_reviews.remove("The Adventures of Sherlock Holmes");
// Look up the values associated with some keys. let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"]; for &book in &to_find { match book_reviews.get(book) { Some(review) => println!("{book}: {review}"), None => println!("{book} is unreviewed.") } }
// Look up the value for a key (will panic if the key is not found). println!("Review for Jane: {}", book_reviews["Pride and Prejudice"]);
// Iterate over everything. for (book, review) in &book_reviews { println!("{book}: \"{review}\""); }

Queue<T>

// Create a simple Queue let mut q: Queue<isize> = queue![];
// Add some elements to it q.add(1); q.add(-2); q.add(3);
// Check the Queue's size q.size(); // 3
// Remove an element q.remove(); // Ok(1)
// Check the Queue's size q.size(); // 2
// Peek at the next element scheduled for removal q.peek(); // Ok(-2)
// Confirm that the Queue size hasn't changed q.size(); // 2
// Remove the remaining elements q.remove(); // Ok(-2) q.remove(); // Ok(3)
// Peek into an empty Queue q.peek(); // Raises an error
// Attempt to remove an element from an empty Queue q.remove(); // Raises an error ```