Skip to content

Instantly share code, notes, and snippets.

@thatal
Created June 10, 2024 03:49
Show Gist options
  • Save thatal/0ec2156c4dc70a385cb459f658c1dec1 to your computer and use it in GitHub Desktop.
Save thatal/0ec2156c4dc70a385cb459f658c1dec1 to your computer and use it in GitHub Desktop.
Cheat sheet for rust language

Rust Cheat Sheet

1. Basic Syntax

  • Hello World

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

    // This is a single-line comment
    /*
     * This is a multi-line comment
     */

2. Variables

  • Immutable Variable

    let x = 5;
  • Mutable Variable

    let mut y = 5;
    y = 6;
  • Constant

    const MAX_POINTS: u32 = 100_000;

3. Data Types

  • Scalar Types

    • Integer: i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize
    • Floating-point: f32, f64
    • Character: char
    • Boolean: bool
  • Compound Types

    • Tuple
      let tup: (i32, f64, u8) = (500, 6.4, 1);
      let (x, y, z) = tup;
    • Array
      let a = [1, 2, 3, 4, 5];
      let first = a[0];

4. Functions

  • Basic Function

    fn main() {
        let result = add(5, 3);
        println!("Result: {}", result);
    }
    
    fn add(x: i32, y: i32) -> i32 {
        x + y
    }
  • Functions with Multiple Returns

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

5. Control Flow

  • If-Else

    if x < 5 {
        println!("x is less than 5");
    } else {
        println!("x is 5 or greater");
    }
  • Loop

    loop {
        println!("Infinite loop");
        break;
    }
  • While

    while x < 10 {
        x += 1;
    }
  • For

    for number in (1..4).rev() {
        println!("{}!", number);
    }

6. Ownership

  • Ownership and Borrowing
    fn main() {
        let s1 = String::from("hello");
        let s2 = s1;
        println!("{}", s2); // s1 is moved to s2, s1 is no longer valid
    }
    
    fn borrow_example(s: &String) {
        println!("{}", s);
    }

7. Structs

  • Defining and Using Structs
    struct User {
        username: String,
        email: String,
        sign_in_count: u64,
        active: bool,
    }
    
    let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

8. Enums

  • Defining and Using Enums
    enum Message {
        Quit,
        Move { x: i32, y: i32 },
        Write(String),
        ChangeColor(i32, i32, i32),
    }
    
    let msg = Message::Write(String::from("hello"));

9. Pattern Matching

  • Match
    let number = 7;
    match number {
        1 => println!("One!"),
        2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
        13..=19 => println!("A teen"),
        _ => println!("Ain't special"),
    }

10. Error Handling

  • Result Enum

    use std::fs::File;
    use std::io::ErrorKind;
    
    fn main() {
        let f = File::open("hello.txt");
        let _file = match f {
            Ok(file) => file,
            Err(ref error) if error.kind() == ErrorKind::NotFound => {
                File::create("hello.txt").unwrap_or_else(|error| {
                    panic!("Problem creating the file: {:?}", error);
                })
            },
            Err(error) => {
                panic!("Problem opening the file: {:?}", error);
            }
        };
    }
  • Panic

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

11. Modules

  • Defining and Using Modules
    mod front_of_house {
        pub mod hosting {
            pub fn add_to_waitlist() {}
        }
    }
    
    pub fn eat_at_restaurant() {
        crate::front_of_house::hosting::add_to_waitlist();
    }

12. Crate and Package

  • Cargo.toml
    [package]
    name = "hello_world"
    version = "0.1.0"
    authors = ["Your Name <you@example.com>"]
    edition = "2021"
    
    [dependencies]

13. Traits

  • Defining and Implementing Traits
    pub trait Summary {
        fn summarize(&self) -> String;
    }
    
    pub struct NewsArticle {
        pub headline: String,
        pub location: String,
        pub author: String,
        pub content: String,
    }
    
    impl Summary for NewsArticle {
        fn summarize(&self) -> String {
            format!("{}, by {} ({})", self.headline, self.author, self.location)
        }
    }

14. Generics

  • Using Generics
    fn largest<T: PartialOrd>(list: &[T]) -> &T {
        let mut largest = &list[0];
        for item in list {
            if item > largest {
                largest = item;
            }
        }
        largest
    }

15. Lifetimes

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

Additional Rust Features and Syntax

16. Macros

  • Defining and Using Macros
    macro_rules! say_hello {
        () => {
            println!("Hello!");
        };
    }
    
    fn main() {
        say_hello!();
    }

17. Closures

  • Defining and Using Closures

    let add_one = |x: i32| -> i32 { x + 1 };
    println!("{}", add_one(5));
  • Closures with Environment Capture

    let x = 4;
    let equal_to_x = |z| z == x;
    let y = 4;
    assert!(equal_to_x(y));

18. Iterators

  • Creating and Using Iterators

    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter();
    
    for val in v1_iter {
        println!("Got: {}", val);
    }
  • Using map and collect

    let v1: Vec<i32> = vec![1, 2, 3];
    let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();

19. Smart Pointers

  • Using Box<T> for Heap Allocation

    let b = Box::new(5);
    println!("b = {}", b);
  • Using Rc<T> for Reference Counting

    use std::rc::Rc;
    
    let a = Rc::new(5);
    let b = Rc::clone(&a);
    println!("count after creating b = {}", Rc::strong_count(&a));
  • Using RefCell<T> for Interior Mutability

    use std::cell::RefCell;
    
    let x = RefCell::new(5);
    *x.borrow_mut() += 1;
    println!("x = {:?}", x.borrow());

20. Concurrency

  • Using Threads

    use std::thread;
    use std::time::Duration;
    
    let handle = 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));
    }
    
    handle.join().unwrap();
  • Using Channels

    use std::sync::mpsc;
    use std::thread;
    
    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);

21. Unsafe Rust

  • Using Unsafe Code

    let mut num = 5;
    
    let r1 = &num as *const i32;
    let r2 = &mut num as *mut i32;
    
    unsafe {
        println!("r1 is: {}", *r1);
        println!("r2 is: {}", *r2);
    }
  • Calling Unsafe Functions

    unsafe fn dangerous() {}
    
    unsafe {
        dangerous();
    }

22. Advanced Traits

  • Trait Objects for Dynamic Dispatch
    pub trait Draw {
        fn draw(&self);
    }
    
    pub struct Screen {
        pub components: Vec<Box<dyn Draw>>,
    }
    
    impl Screen {
        pub fn run(&self) {
            for component in self.components.iter() {
                component.draw();
            }
        }
    }

23. Attribute Macros

  • Using Derive Macros

    #[derive(Debug)]
    struct Rectangle {
        width: u32,
        height: u32,
    }
    
    fn main() {
        let rect1 = Rectangle {
            width: 30,
            height: 50,
        };
    
        println!("rect1 is {:?}", rect1);
    }
  • Custom Attributes

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

24. Asynchronous Programming

  • Using async/await
    use tokio::time::{sleep, Duration};
    
    #[tokio::main]
    async fn main() {
        async fn say_hello() {
            sleep(Duration::from_secs(1)).await;
            println!("Hello, world!");
        }
    
        say_hello().await;
    }

More Rust Features and Syntax

25. Dependency Injection

Rust doesn't have built-in support for dependency injection (DI) like some other languages, but DI can be achieved through various patterns and libraries. Here’s a simple example using traits and structs:

  • Simple Dependency Injection
    trait Messenger {
        fn send(&self, msg: &str);
    }
    
    struct Email;
    impl Messenger for Email {
        fn send(&self, msg: &str) {
            println!("Sending email: {}", msg);
        }
    }
    
    struct Logger<M: Messenger> {
        messenger: M,
    }
    
    impl<M: Messenger> Logger<M> {
        fn log(&self, msg: &str) {
            self.messenger.send(msg);
        }
    }
    
    fn main() {
        let email = Email;
        let logger = Logger { messenger: email };
    
        logger.log("Hello, Dependency Injection!");
    }

26. Installing Packages (Crates)

  • Using Cargo to Install Packages
    • Add the dependency in Cargo.toml:

      [dependencies]
      rand = "0.8"
    • Use the package in your project:

      use rand::Rng;
      
      fn main() {
          let mut rng = rand::thread_rng();
          let n: u32 = rng.gen();
          println!("Random number: {}", n);
      }

27. Custom Types

  • Type Aliases

    type Kilometers = i32;
    
    let x: Kilometers = 5;
  • Newtype Pattern

    struct Wrapper(Vec<String>);
    
    impl Wrapper {
        pub fn new() -> Wrapper {
            Wrapper(Vec::new())
        }
    }

28. Destructuring

  • Destructuring Structs

    struct Point {
        x: i32,
        y: i32,
    }
    
    let p = Point { x: 0, y: 7 };
    let Point { x, y } = p;
  • Destructuring Enums

    enum Message {
        Quit,
        Move { x: i32, y: i32 },
        Write(String),
        ChangeColor(i32, i32, i32),
    }
    
    let msg = Message::ChangeColor(0, 160, 255);
    
    match msg {
        Message::Quit => println!("The Quit variant has no data to destructure."),
        Message::Move { x, y } => println!("Move in the x direction {} and in the y direction {}", x, y),
        Message::Write(text) => println!("Text message: {}", text),
        Message::ChangeColor(r, g, b) => println!("Change the color to red {}, green {}, and blue {}", r, g, b),
    }

29. Inline Assembly

  • Using Inline Assembly
    unsafe {
        asm!("nop");
    }

30. Unsafe Rust

  • Accessing and Modifying a Mutable Static Variable
    static mut COUNTER: u32 = 0;
    
    fn add_to_count(inc: u32) {
        unsafe {
            COUNTER += inc;
        }
    }
    
    fn main() {
        add_to_count(3);
        unsafe {
            println!("COUNTER: {}", COUNTER);
        }
    }

31. Procedural Macros

  • Creating a Procedural Macro
    • Define the macro in a separate crate:

      // in src/lib.rs
      extern crate proc_macro;
      use proc_macro::TokenStream;
      use quote::quote;
      use syn;
      
      #[proc_macro]
      pub fn make_hello(item: TokenStream) -> TokenStream {
          let input = syn::parse_macro_input!(item as syn::LitStr);
          let expanded = quote! {
              println!("Hello, {}!", #input);
          };
          TokenStream::from(expanded)
      }
    • Use the macro in your main project:

      use my_macro::make_hello;
      
      fn main() {
          make_hello!("world");
      }

32. Feature Flags

  • Using Feature Flags in Cargo
    • Define features in Cargo.toml:

      [features]
      default = []
      secure = ["ring"]
    • Conditional Compilation:

      #[cfg(feature = "secure")]
      fn secure_function() {
          println!("Secure function enabled");
      }
      
      #[cfg(not(feature = "secure"))]
      fn secure_function() {
          println!("Secure function not enabled");
      }

33. Converting Between Types

  • Using From and Into Traits
    impl From<i32> for Point {
        fn from(item: i32) -> Self {
            Point { x: item, y: item }
        }
    }
    
    let p: Point = 5.into();

34. Default Trait

  • Implementing the Default Trait
    #[derive(Debug)]
    struct Point {
        x: i32,
        y: i32,
    }
    
    impl Default for Point {
        fn default() -> Self {
            Point { x: 0, y: 0 }
        }
    }
    
    fn main() {
        let origin: Point = Default::default();
        println!("Origin: {:?}", origin);
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment