Published on August 29, 2024By DeveloperBreeze

Rust Cheatsheet: A Comprehensive Guide to Rust Programming

This Rust cheatsheet provides a quick reference to essential Rust concepts, syntax, and functionalities. Whether you're a beginner or an experienced developer, this guide will help you quickly look up common Rust patterns and features.


1. Basic Syntax

Hello, World!

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

Variables

  • Immutable Variables (default):
let x = 5;
  • Mutable Variables:
let mut x = 5;
x = 6;
  • Constants:
const MAX_POINTS: u32 = 100_000;

Data Types

  • Scalar Types: i32, u32, f64, bool, char
  • Compound Types: Tuples, Arrays
let tup: (i32, f64, u8) = (500, 6.4, 1);
let (x, y, z) = tup;
let a = [1, 2, 3, 4, 5];

2. Control Flow

If/Else

let number = 6;

if number % 4 == 0 {
    println!("Number is divisible by 4");
} else if number % 3 == 0 {
    println!("Number is divisible by 3");
} else {
    println!("Number is not divisible by 4 or 3");
}

Loops

  • Infinite Loop:
loop {
    println!("Loop forever!");
}
  • While Loop:
let mut number = 3;

while number != 0 {
    println!("{}!", number);

    number -= 1;
}
  • For Loop:
let a = [10, 20, 30, 40, 50];

for element in a.iter() {
    println!("The value is: {}", element);
}

3. Functions

Basic Function

fn main() {
    println!("The result is: {}", add(5, 3));
}

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

Return Values

Functions return the last expression without a semicolon:

fn five() -> i32 {
    5
}

4. Ownership and Borrowing

Ownership

  • Move Semantics:
let s1 = String::from("hello");
let s2 = s1; // s1 is now invalid
  • Clone:
let s1 = String::from("hello");
let s2 = s1.clone(); // Deep copy

Borrowing

  • Immutable Borrowing:
fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);
    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}
  • Mutable Borrowing:
fn main() {
    let mut s = String::from("hello");
    change(&mut s);
}

fn change(s: &mut String) {
    s.push_str(", world");
}

Slices

let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];

5. Structs

Defining a Struct

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

Instantiating a Struct

let user1 = User {
    username: String::from("someusername"),
    email: String::from("someone@example.com"),
    sign_in_count: 1,
    active: true,
};

Struct Update Syntax

let user2 = User {
    email: String::from("another@example.com"),
    ..user1
};

Tuple Structs

struct Color(i32, i32, i32);
let black = Color(0, 0, 0);

6. Enums

Defining an Enum

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

Using Enums

let m = Message::Write(String::from("hello"));

match m {
    Message::Quit => println!("Quit"),
    Message::Move { x, y } => println!("Move to x: {}, y: {}", x, y),
    Message::Write(text) => println!("Text: {}", text),
    Message::ChangeColor(r, g, b) => println!("Change color to red: {}, green: {}, blue: {}", r, g, b),
}

7. Error Handling

Panic!

fn main() {
    panic!("Crash and burn");
}

Result and `match`

use std::fs::File;
use std::io::ErrorKind;

fn main() {
    let f = File::open("hello.txt");

    let f = match f {
        Ok(file) => file,
        Err(ref error) if error.kind() == ErrorKind::NotFound => {
            match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(e) => panic!("Problem creating the file: {:?}", e),
            }
        },
        Err(error) => {
            panic!("Problem opening the file: {:?}", error)
        },
    };
}

Using `unwrap` and `expect`

let f = File::open("hello.txt").unwrap();
let f = File::open("hello.txt").expect("Failed to open hello.txt");

8. Traits

Defining a Trait

pub trait Summary {
    fn summarize(&self) -> String;
}

Implementing a Trait

struct Article {
    title: String,
    content: String,
}

impl Summary for Article {
    fn summarize(&self) -> String {
        format!("{}, {}", self.title, self.content)
    }
}

Default Trait Methods

pub trait Summary {
    fn summarize(&self) -> String {
        String::from("(Read more...)")
    }
}

Trait Bounds

fn notify<T: Summary>(item: T) {
    println!("Breaking news! {}", item.summarize());
}

9. Lifetimes

Basic Lifetime Annotation

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

Structs with Lifetimes

struct ImportantExcerpt<'a> {
    part: &'a str,
}

10. Collections

Vectors

let mut v = Vec::new();
v.push(5);
v.push(6);
v.push(7);

let third = &v[2];

Hash Maps

use std::collections::HashMap;

let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

Iterating Over Collections

for i in &v {
    println!("{}", i);
}

for (key, value) in &scores {
    println!("{}: {}", key, value);
}

11. Concurrency

Threads

use std::thread;
use std::time::Duration;

fn main() {
    thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}

Channels

use std::sync::mpsc;
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("hi");
        tx.send(val).unwrap();
    });

    let received = rx.recv().unwrap();
    println!("Got: {}", received);
}

12. Modules and Crates

Creating Modules

mod network {
    pub fn connect() {
        println!("connected");
    }
}

Using Modules

fn main() {
    network::connect();
}

External Crates

In Cargo.toml:

[dependencies]
rand = "0.8.3"

In your code:

use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();
    let n: u8 =

 rng.gen();
    println!("Random number: {}", n);
}

13. Common Macros

`println!`

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

`vec!`

let v = vec![1, 2, 3];

`format!`

let s = format!("{} {}", "Hello", "world");

14. Cargo

Creating a New Project

cargo new my_project
cd my_project

Building and Running

cargo build
cargo run
cargo check

Adding Dependencies

In Cargo.toml:

[dependencies]
serde = "1.0"
serde_json = "1.0"

Running Tests

cargo test

15. Testing

Writing Tests

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }

    #[test]
    fn another() {
        panic!("This test will fail");
    }
}

Running Tests

cargo test

16. Error Handling

Result and Option

fn divide(dividend: f64, divisor: f64) -> Result<f64, String> {
    if divisor == 0.0 {
        Err(String::from("Cannot divide by zero"))
    } else {
        Ok(dividend / divisor)
    }
}

Unwrap and Expect

let file = File::open("hello.txt").unwrap();
let file = File::open("hello.txt").expect("File not found!");

Conclusion

This Rust cheatsheet covers the essentials you'll need while working with Rust, from basic syntax and control flow to advanced concepts like lifetimes, concurrency, and error handling. Keep this cheatsheet handy as you work with Rust to quickly recall the syntax and concepts you need.

Comments

Please log in to leave a comment.

Continue Reading: