Rust Buster Cheatsheet made to help myself keep an index of syntax as I learn Rust

In Rust, variables are immutable by default, promoting safer and more predictable code.
let x = 5; // Immutable variable
let mut y = 10; // Mutable variable
const MAX_POINTS: u32 = 100_000; // Constant
let declares an immutable variable.let mut declares a mutable variable that can be changed later.const declares a constant, which must have a type annotation and be assigned a constant expression.Rust has several basic data types to represent numbers, characters, and strings.
let a: u32 = 42; // Unsigned 32-bit integer
let b: i64 = -100; // Signed 64-bit integer
let c: f32 = 3.14; // 32-bit floating-point number
let d: bool = true; // Boolean
let e: char = 'x'; // Character
let f: &str = "Hello, World!"; // String slice
let g: String = String::from("Hello, World!"); // Owned String
u32: Unsigned 32-bit integer (0 to 4,294,967,295)i64: Signed 64-bit integer (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)f32: 32-bit floating-point numberbool: Boolean (true or false)char: Unicode scalar value&str: String slice (borrowed string)String: Owned string (can be modified)Structs are custom data types that group related data together.
struct Person {
name: String,
age: u32,
}
// Creating an instance of a struct
let person = Person {
name: String::from("Alice"),
age: 30,
};
// Accessing struct fields
println!("Name: {}", person.name); // Name: Alice
println!("Age: {}", person.age); // Age: 30
// Mutable struct instance
let mut mutable_person = Person {
name: String::from("Bob"),
age: 25,
};
mutable_person.age = 26; // Updating age field
// Tuple Struct
struct Point(i32, i32);
let point = Point(10, 20);
// Unit Struct (marker)
struct Unit;
let unit = Unit;
Implementations allow you to define methods and associated functions for structs.
impl Person {
// Associated function (constructor)
fn new(name: &str, age: u32) -> Person {
Person {
name: String::from(name),
age,
}
}
// Method
fn say_hello(&self) {
println!("Hello, my name is {}", self.name);
}
// Mutable method
fn have_birthday(&mut self) {
self.age += 1;
}
}
// Using the `new` constructor and methods
let mut alice = Person::new("Alice", 30);
alice.say_hello(); // Hello, my name is Alice
alice.have_birthday();
println!("Alice's new age: {}", alice.age); // Alice's new age: 31
new) are called on the struct itself.&self or &mut self as the first parameter and are called on instances.Enums allow you to define a type that can be one of several variants.
enum Direction {
North,
South,
East,
West,
}
let direction = Direction::East;
enum OptionalInt {
Value(i32),
Nothing,
}
let x = OptionalInt::Value(42);
let y = OptionalInt::Nothing;
Direction.OptionalInt.Pattern matching is a powerful feature in Rust for destructuring and matching against patterns.
match direction {
Direction::North => println!("Going North"),
Direction::South => println!("Going South"),
Direction::East => println!("Going East"),
Direction::West => println!("Going West"),
}
match x {
OptionalInt::Value(n) => println!("Value: {}", n),
OptionalInt::Nothing => println!("Nothing"),
}
match expressions must be exhaustive, covering all possible cases.Vectors are dynamic arrays that can grow or shrink in size.
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
vec.push(3);
let first = vec[0]; // 1
// Slices
let slice = &vec[1..3]; // Creates a slice of the vector from index 1 to 2
println!("Slice: {:?}", slice); // Slice: [2, 3]
// Iterating over vectors
for x in &vec {
println!("{}", x);
}
for loop.Rust's ownership system is a key feature that ensures memory safety without a garbage collector.
let s1 = String::from("hello");
let s2 = s1; // s1 is invalid after this line
let s3 = s2.clone(); // Create a clone
let s4 = String::from("world");
let s5 = &s4; // Borrowing reference
println!("{}, {}", s5, s4); // world, world
clone() method.Traits define shared behavior across types.
trait Summary {
fn summarize(&self) -> String;
}
struct Article {
headline: String,
content: String,
}
impl Summary for Article {
fn summarize(&self) -> String {
format!("{} - {}", self.headline, self.content.split_whitespace().take(5).collect::>().join(" "))
}
}
let article = Article {
headline: String::from("Rust Cheatsheet"),
content: String::from("This is a cheatsheet for the Rust programming language."),
};
println!("{}", article.summarize());
Rust uses the Result and Option types for error handling.
// Using Result
fn divide(x: f64, y: f64) -> Result {
if y == 0.0 {
Err(String::from("Division by zero"))
} else {
Ok(x / y)
}
}
match divide(10.0, 2.0) {
Ok(result) => println!("Result: {}", result),
Err(e) => println!("Error: {}", e),
}
// Using Option
fn find_user(id: u32) -> Option {
if id == 1 {
Some(String::from("Alice"))
} else {
None
}
}
match find_user(1) {
Some(name) => println!("User found: {}", name),
None => println!("User not found"),
}
Result represents either success (Ok(T)) or failure (Err(E)).Option represents either some value (Some(T)) or no value (None).Closures are anonymous functions that can capture their environment.
let add_one = |x: i32| x + 1;
println!("5 + 1 = {}", add_one(5));
Iterators allow you to process sequences of elements.
let numbers = vec![1, 2, 3, 4, 5];
let doubled: Vec = numbers.iter().map(|&x| x * 2).collect();
println!("Doubled numbers: {:?}", doubled);
map, filter, and fold are available on iterators.Generics allow you to write flexible, reusable code that works with multiple types.
fn largest(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list.iter() {
if item > largest {
largest = item;
}
}
largest
}
let numbers = vec![34, 50, 25, 100, 65];
println!("The largest number is {}", largest(&numbers));
T must implement the PartialOrd trait.Lifetimes ensure that references are valid for as long as they're used.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
let result;
{
let string1 = String::from("short");
let string2 = String::from("longer");
result = longest(string1.as_str(), string2.as_str());
}
println!("The longest string is {}", result);
'a.Smart pointers are data structures that act like pointers but have additional metadata and capabilities.
use std::rc::Rc;
let s = Rc::new(String::from("Hello, Rust!"));
let s1 = Rc::clone(&s);
let s2 = Rc::clone(&s);
println!("{} has {} strong references", s, Rc::strong_count(&s));
Rc (Reference Counted) allows multiple ownership of the same data.Rust provides tools for safe and efficient concurrent programming.
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));
}
});
handle.join().unwrap();
thread::spawn creates a new thread.handle.join() waits for the spawned thread to finish.Modules help organize and encapsulate code.
mod math {
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
}
use math::add;
println!("5 + 3 = {}", add(5, 3));
mod defines a module.pub makes items public and accessible outside the module.use brings items into scope.This cheatsheet covers many of the fundamental concepts in Rust. Each section provides code examples and explanations to help you understand and use these features effectively in your Rust programs.
In Rust, variables are immutable by default, promoting safer and more predictable code.
let x = 5; // Immutable variable
let mut y = 10; // Mutable variable
const MAX_POINTS: u32 = 100_000; // Constant
let declares an immutable variable.let mut declares a mutable variable that can be changed later.const declares a constant, which must have a type annotation and be assigned a constant expression.Rust has several basic data types to represent numbers, characters, and strings.
let a: u32 = 42; // Unsigned 32-bit integer
let b: i64 = -100; // Signed 64-bit integer
let c: f32 = 3.14; // 32-bit floating-point number
let d: bool = true; // Boolean
let e: char = 'x'; // Character
let f: &str = "Hello, World!"; // String slice
let g: String = String::from("Hello, World!"); // Owned String
u32: Unsigned 32-bit integer (0 to 4,294,967,295)i64: Signed 64-bit integer (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)f32: 32-bit floating-point numberbool: Boolean (true or false)char: Unicode scalar value&str: String slice (borrowed string)String: Owned string (can be modified)Structs are custom data types that group related data together.
struct Person {
name: String,
age: u32,
}
// Creating an instance of a struct
let person = Person {
name: String::from("Alice"),
age: 30,
};
// Accessing struct fields
println!("Name: {}", person.name); // Name: Alice
println!("Age: {}", person.age); // Age: 30
// Mutable struct instance
let mut mutable_person = Person {
name: String::from("Bob"),
age: 25,
};
mutable_person.age = 26; // Updating age field
// Tuple Struct
struct Point(i32, i32);
let point = Point(10, 20);
// Unit Struct (marker)
struct Unit;
let unit = Unit;
Implementations allow you to define methods and associated functions for structs.
impl Person {
// Associated function (constructor)
fn new(name: &str, age: u32) -> Person {
Person {
name: String::from(name),
age,
}
}
// Method
fn say_hello(&self) {
println!("Hello, my name is {}", self.name);
}
// Mutable method
fn have_birthday(&mut self) {
self.age += 1;
}
}
// Using the `new` constructor and methods
let mut alice = Person::new("Alice", 30);
alice.say_hello(); // Hello, my name is Alice
alice.have_birthday();
println!("Alice's new age: {}", alice.age); // Alice's new age: 31
new) are called on the struct itself.&self or &mut self as the first parameter and are called on instances.Enums allow you to define a type that can be one of several variants.
enum Direction {
North,
South,
East,
West,
}
let direction = Direction::East;
enum OptionalInt {
Value(i32),
Nothing,
}
let x = OptionalInt::Value(42);
let y = OptionalInt::Nothing;
Direction.OptionalInt.Pattern matching is a powerful feature in Rust for destructuring and matching against patterns.
match direction {
Direction::North => println!("Going North"),
Direction::South => println!("Going South"),
Direction::East => println!("Going East"),
Direction::West => println!("Going West"),
}
match x {
OptionalInt::Value(n) => println!("Value: {}", n),
OptionalInt::Nothing => println!("Nothing"),
}
match expressions must be exhaustive, covering all possible cases.Vectors are dynamic arrays that can grow or shrink in size.
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
vec.push(3);
let first = vec[0]; // 1
// Slices
let slice = &vec[1..3]; // Creates a slice of the vector from index 1 to 2
println!("Slice: {:?}", slice); // Slice: [2, 3]
// Iterating over vectors
for x in &vec {
println!("{}", x);
}
for loop.Rust's ownership system is a key feature that ensures memory safety without a garbage collector.
let s1 = String::from("hello");
let s2 = s1; // s1 is invalid after this line
let s3 = s2.clone(); // Create a clone
let s4 = String::from("world");
let s5 = &s4; // Borrowing reference
println!("{}, {}", s5, s4); // world, world
clone() method.Traits define shared behavior across types.
trait Summary {
fn summarize(&self) -> String;
}
struct Article {
headline: String,
content: String,
}
impl Summary for Article {
fn summarize(&self) -> String {
format!("{} - {}", self.headline, self.content.split_whitespace().take(5).collect::>().join(" "))
}
}
let article = Article {
headline: String::from("Rust Cheatsheet"),
content: String::from("This is a cheatsheet for the Rust programming language."),
};
println!("{}", article.summarize());
Rust uses the Result and Option types for error handling.
// Using Result
fn divide(x: f64, y: f64) -> Result {
if y == 0.0 {
Err(String::from("Division by zero"))
} else {
Ok(x / y)
}
}
match divide(10.0, 2.0) {
Ok(result) => println!("Result: {}", result),
Err(e) => println!("Error: {}", e),
}
// Using Option
fn find_user(id: u32) -> Option {
if id == 1 {
Some(String::from("Alice"))
} else {
None
}
}
match find_user(1) {
Some(name) => println!("User found: {}", name),
None => println!("User not found"),
}
Result represents either success (Ok(T)) or failure (Err(E)).Option represents either some value (Some(T)) or no value (None).Closures are anonymous functions that can capture their environment.
let add_one = |x: i32| x + 1;
println!("5 + 1 = {}", add_one(5));
Iterators allow you to process sequences of elements.
let numbers = vec![1, 2, 3, 4, 5];
let doubled: Vec = numbers.iter().map(|&x| x * 2).collect();
println!("Doubled numbers: {:?}", doubled);
map, filter, and fold are available on iterators.Generics allow you to write flexible, reusable code that works with multiple types.
fn largest(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list.iter() {
if item > largest {
largest = item;
}
}
largest
}
let numbers = vec![34, 50, 25, 100, 65];
println!("The largest number is {}", largest(&numbers));
T must implement the PartialOrd trait.Lifetimes ensure that references are valid for as long as they're used.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
let result;
{
let string1 = String::from("short");
let string2 = String::from("longer");
result = longest(string1.as_str(), string2.as_str());
}
println!("The longest string is {}", result);
'a.Smart pointers are data structures that act like pointers but have additional metadata and capabilities.
use std::rc::Rc;
let s = Rc::new(String::from("Hello, Rust!"));
let s1 = Rc::clone(&s);
let s2 = Rc::clone(&s);
println!("{} has {} strong references", s, Rc::strong_count(&s));
Rc (Reference Counted) allows multiple ownership of the same data.Rust provides tools for safe and efficient concurrent programming.
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));
}
});
handle.join().unwrap();
thread::spawn creates a new thread.handle.join() waits for the spawned thread to finish.Modules help organize and encapsulate code.
mod math {
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
}
use math::add;
println!("5 + 3 = {}", add(5, 3));
mod defines a module.pub makes items public and accessible outside the module.use brings items into scope.This cheatsheet covers many of the fundamental concepts in Rust. Each section provides code examples and explanations to help you understand and use these features effectively in your Rust programs.