Complete Rust reference covering syntax, ownership, lifetimes, generics, traits, collections, error handling, concurrency, smart pointers, modules, testing, and Cargo commands. Includes 22 sections with code examples—from basics to advanced features like async, macros, and unsafe Rust. Perfect for quick lookup.
- Basic Syntax
- Variables and Mutability
- Data Types
- Functions
- Control Flow
- Ownership and Borrowing
- Structs
- Enums and Pattern Matching
- Collections
- Error Handling
- Generics
- Traits
- Lifetimes
- Closures
- Iterators
- Smart Pointers
- Concurrency
- Modules and Crates
- Testing
- Advanced Features
- Common Macros
- Cargo Commands
fn main() {
println!("Hello, World!");
}// Line comment
/* Block comment
Multi-line */
/// Documentation comment (outer)
//! Inner documentation comment
println!("Hello"); // with newline
print!("Hello"); // without newline
println!("Number: {}", 42); // placeholder
println!("{0} {1} {0}", 1, 2); // positional
println!("{name}: {age}", name="Bob", age=30); // named
println!("{:b}", 10); // binary: 1010
println!("{:x}", 255); // hex: ff
println!("{:.2}", 3.14159); // 2 decimal placeslet x = 5; // immutable (default)
let mut y = 5; // mutable
y = 10; // OK
const MAX_POINTS: u32 = 100_000; // constant (always immutable)
static HELLO: &str = "Hello"; // static variablelet x = 5;
let x = x + 1; // shadowing (new variable)
let x = "hello"; // type can changelet (a, b) = (1, 2);
let [x, y] = [1, 2];
let Point { x, y } = point;// Integers
let a: i8 = -128; // -128 to 127
let b: u8 = 255; // 0 to 255
let c: i16 = -32768; // i32, i64, i128, isize, usize
let d: u32 = 42; // u16, u64, u128
// Floats
let e: f32 = 3.14; // f64 (double) default
let f: f64 = 2.71828;
// Boolean
let g: bool = true;
// Character
let h: char = '😀'; // 4 bytes Unicode// Tuple
let tup: (i32, f64, char) = (500, 6.4, 'A');
let (a, b, c) = tup; // destructuring
let first = tup.0; // index access
// Array (fixed length, same type)
let arr: [i32; 5] = [1, 2, 3, 4, 5];
let zeros = [0; 10]; // array of 10 zeros
let first = arr[0];
// Slice (reference to contiguous sequence)
let slice: &[i32] = &arr[1..4]; // [2, 3, 4]
let slice_full = &arr[..]; // whole arraytype Kilometers = i32;
let distance: Kilometers = 100;fn add(x: i32, y: i32) -> i32 {
x + y // no semicolon = expression (return value)
}
fn print_message() {
println!("Hello"); // no return value -> ()
}fn divide(x: f64, y: f64) -> Result<f64, String> {
if y == 0.0 {
Err(String::from("Division by zero"))
} else {
Ok(x / y)
}
}impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn new(width: u32, height: u32) -> Self { // associated function
Self { width, height }
}
}let number = 6;
if number % 4 == 0 {
println!("divisible by 4");
} else if number % 3 == 0 {
println!("divisible by 3");
} else {
println!("not divisible");
}
// if as expression
let condition = true;
let number = if condition { 5 } else { 6 };// Infinite loop
loop {
println!("forever");
break; // exit loop
}
// while loop
let mut n = 0;
while n < 5 {
println!("{}", n);
n += 1;
}
// for loop (range)
for i in 0..5 { // 0 to 4
println!("{}", i);
}
for i in 0..=5 { // 0 to 5 (inclusive)
println!("{}", i);
}
// Iterate over collection
let fruits = vec!["apple", "banana", "cherry"];
for fruit in &fruits {
println!("{}", fruit);
}
// Loop with index
for (i, fruit) in fruits.iter().enumerate() {
println!("{}: {}", i, fruit);
}let x = 1;
match x {
1 => println!("one"),
2 => println!("two"),
3 | 4 => println!("three or four"),
5..=10 => println!("five to ten"),
_ => println!("other"), // catch-all
}
// match as expression
let result = match x {
1 => "one",
2 => "two",
_ => "other",
};let some_option = Some(5);
if let Some(x) = some_option {
println!("{}", x);
}
let optional = Some(7);
if let Some(7) = optional {
println!("seven");
}let mut stack = Vec::new();
stack.push(1);
stack.push(2);
while let Some(top) = stack.pop() {
println!("{}", top);
}- Each value has a variable (owner)
- Only one owner at a time
- When owner goes out of scope, value dropped
let s1 = String::from("hello");
let s2 = s1; // s1 moved to s2 (s1 invalid)
// println!("{}", s1); // ERROR: s1 moved
let x = 5;
let y = x; // Copy (integers are Copy trait)
println!("{}", x); // OKlet s1 = String::from("hello");
let s2 = s1.clone(); // Deep copy
println!("{} {}", s1, s2); // OK// Immutable reference (multiple allowed)
let s1 = String::from("hello");
let len = calculate_length(&s1); // borrow s1
fn calculate_length(s: &String) -> usize {
s.len() // s is dropped, but not the value
}
// Mutable reference (only one allowed)
let mut s = String::from("hello");
change(&mut s);
fn change(some_string: &mut String) {
some_string.push_str(", world");
}- One mutable OR any number of immutable references
- References must always be valid (no dangling)
let mut x = 5;
let y = &mut x;
*y += 1; // dereference mutable reference// Classic struct
struct Person {
name: String,
age: u32,
email: String,
}
// Tuple struct
struct Color(u8, u8, u8);
let black = Color(0, 0, 0);
// Unit struct (no fields)
struct AlwaysEqual;
let subject = AlwaysEqual;let person = Person {
name: String::from("Alice"),
age: 30,
email: String::from("alice@example.com"),
};
// Access fields
println!("{}", person.name);
// Update syntax
let person2 = Person {
name: String::from("Bob"),
..person // remaining fields from person
};
// Tuple struct access
let Color(r, g, b) = black;
println!("{} {} {}", r, g, b);
println!("{}", black.0);struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
// Method (takes self)
fn area(&self) -> u32 {
self.width * self.height
}
// Method with parameters
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
// Associated function (like static method)
fn square(size: u32) -> Self {
Self { width: size, height: size }
}
}
let rect = Rectangle { width: 30, height: 50 };
println!("Area: {}", rect.area());
let square = Rectangle::square(10);#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct Point {
x: i32,
y: i32,
}enum IpAddr {
V4(String),
V6(String),
}
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(u8, u8, u8),
}
// With methods
impl Message {
fn call(&self) {
// method body
}
}enum Option<T> {
Some(T),
None,
}
let some_number = Some(5);
let some_string = Some("hello");
let absent_number: Option<i32> = None;
// Using Option
match some_number {
Some(i) => println!("{}", i),
None => println!("none"),
}enum Result<T, E> {
Ok(T),
Err(E),
}
let result = std::fs::read_to_string("file.txt");
match result {
Ok(content) => println!("{}", content),
Err(error) => eprintln!("Error: {}", error),
}// Option methods
Some(5).unwrap(); // returns value or panics
Some(5).unwrap_or(0); // returns value or default
Some(5).expect("message"); // panic with custom message
Some(5).is_some(); // true if Some
None.is_none(); // true if None
// Result methods
Ok(5).unwrap(); // returns value or panics
Ok(5).unwrap_or(0); // returns value or default
Ok(5).is_ok(); // true if Ok
Err(5).is_err(); // true if Err
Ok(5).ok(); // convert to Optionlet x = Some(5);
match x {
Some(y) if y < 5 => println!("less than 5"),
Some(y) => println!("{}", y),
None => println!("none"),
}
// Match guards
match value {
Some(x) if x < 5 => println!("less"),
Some(x) => println!("{}", x),
None => (),
}
// @ bindings
match value {
Some(x @ 1..=5) => println!("{} in range", x),
Some(x) => println!("{} outside range", x),
None => (),
}// Creation
let mut v: Vec<i32> = Vec::new();
let v = vec![1, 2, 3];
// Adding
v.push(4);
// Access
let third = &v[2]; // panics if out of bounds
let third = v.get(2); // returns Option
// Iteration
for i in &v {
println!("{}", i);
}
for i in &mut v {
*i += 10; // mutate values
}
// Removing
v.pop(); // removes last element
v.remove(1); // removes element at index
// Utilities
v.len(); // length
v.is_empty(); // check empty
v.contains(&2); // check if contains
v.sort(); // sort
v.reverse(); // reverse
v.dedup(); // remove consecutive duplicatesuse std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
// Access
let blue_score = scores.get("Blue"); // Option<&V>
let blue_score = scores["Blue"]; // panics if not found
// Iterate
for (key, value) in &scores {
println!("{}: {}", key, value);
}
// Update
scores.entry(String::from("Blue")).or_insert(25);
scores.entry(String::from("Red")).or_insert(100);
// Remove
scores.remove("Blue");use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(1);
set.insert(2);
set.contains(&1); // check membership
set.remove(&1); // removelet mut s = String::new();
let s = "hello".to_string();
let s = String::from("hello");
// Concatenation
let s1 = String::from("Hello");
let s2 = String::from("World");
let s3 = s1 + &s2; // s1 moved, can't use further
// Format macro
let s = format!("{}-{}-{}", a, b, c);
// Manipulation
s.push('c'); // add char
s.push_str("har"); // add string
s.pop(); // remove last char
// Slicing (can panic on char boundaries)
let hello = "hello";
let slice = &hello[0..4]; // "hell"
// Iteration
for c in "नमस्ते".chars() { // characters
println!("{}", c);
}
for b in "नमस्ते".bytes() { // raw bytes
println!("{}", b);
}panic!("crash and burn");
// Debug assertions
debug_assert!(condition);
assert_eq!(a, b);
assert_ne!(a, b);use std::fs::File;
use std::io::ErrorKind;
let file = File::open("hello.txt");
let file = match file {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(e) => panic!("Problem creating file: {:?}", e),
},
other_error => panic!("Problem opening file: {:?}", other_error),
},
};// unwrap - panics if Err
let file = File::open("hello.txt").unwrap();
// expect - panics with custom message
let file = File::open("hello.txt").expect("Failed to open file");
// ? operator - propagate error
fn read_file() -> Result<String, io::Error> {
let mut s = String::new();
File::open("hello.txt")?.read_to_string(&mut s)?;
Ok(s)
}use std::fmt;
#[derive(Debug)]
struct AppError {
message: String,
}
impl fmt::Display for AppError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for AppError {}
fn do_something() -> Result<(), AppError> {
Err(AppError { message: "Something went wrong".to_string() })
}fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}struct Point<T, U> {
x: T,
y: U,
}
let integer = Point { x: 5, y: 10 };
let float = Point { x: 1.0, y: 4.0 };
let mixed = Point { x: 5, y: 4.0 };enum Result<T, E> {
Ok(T),
Err(E),
}impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
// Specific implementation
impl Point<f32> {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}fn add<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {
a + b
}trait Summary {
fn summarize(&self) -> String;
// Default implementation
fn summarize_author(&self) -> String {
String::from("Unknown")
}
}
struct NewsArticle {
headline: String,
location: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {}", self.headline, self.location)
}
}// Syntax 1
fn notify(item: &impl Summary) {
println!("{}", item.summarize());
}
// Syntax 2 (trait bound)
fn notify<T: Summary>(item: &T) {
println!("{}", item.summarize());
}
// Multiple traits
fn notify(item: &(impl Summary + Display)) {}
fn notify<T: Summary + Display>(item: &T) {}
// where clause
fn some_function<T, U>(t: &T, u: &U) -> i32
where
T: Display + Clone,
U: Clone + Debug,
{
42
}fn returns_summarizable() -> impl Summary {
NewsArticle {
headline: String::from("News"),
location: String::from("NYC"),
}
}#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct MyStruct {
value: i32,
}| Trait | Purpose |
|---|---|
Debug |
Formatting with {:?} |
Clone |
Explicit deep copy |
Copy |
Implicit shallow copy |
PartialEq |
Equality comparison (==, !=) |
Eq |
Full equivalence |
PartialOrd |
Partial ordering |
Ord |
Total ordering |
Hash |
Hashing for HashMap |
Default |
Default values |
Display |
Formatted output ({}) |
From/Into |
Type conversions |
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}struct ImportantExcerpt<'a> {
part: &'a str,
}
impl<'a> ImportantExcerpt<'a> {
fn level(&self) -> i32 {
3
}
fn announce_and_return_part(&self, announcement: &str) -> &str {
println!("{}", announcement);
self.part
}
}// Single input -> output gets same lifetime
fn first_word(s: &str) -> &str {}
// Multiple inputs, one is self or &self
fn method(&self, s: &str) -> &str {}let s: &'static str = "I live forever";// Full syntax
let add_one = |x: i32| -> i32 { x + 1 };
// Inferred types
let add_one = |x| x + 1;
// Multiple parameters
let add = |x, y| x + y;
// No parameters
let random = || 42;let x = 4;
let equal_to_x = |z| z == x;
// Move ownership
let y = vec![1, 2, 3];
let move_closure = move |z| z == y;fn call_with_one<F>(some_closure: F) -> i32
where
F: Fn(i32) -> i32,
{
some_closure(1)
}
// Different traits
// Fn: borrows immutably
// FnMut: borrows mutably
// FnOnce: takes ownershiplet numbers = vec![1, 2, 3];
let doubled: Vec<_> = numbers.iter().map(|x| x * 2).collect();
let mut counter = 0;
let mut increment = || counter += 1;
increment();let v = vec![1, 2, 3];
let iter = v.iter(); // Iterator over &T
let iter_mut = v.iter_mut(); // Iterator over &mut T
let into_iter = v.into_iter(); // Iterator over T (consumes)// map - transform each element
let doubled: Vec<_> = v.iter().map(|x| x * 2).collect();
// filter - keep elements satisfying condition
let evens: Vec<_> = v.iter().filter(|&&x| x % 2 == 0).collect();
// enumerate - add index
for (i, val) in v.iter().enumerate() {
println!("{}: {}", i, val);
}
// zip - combine two iterators
let sum_pairs: Vec<_> = v1.iter().zip(v2.iter()).collect();
// take - first n elements
let first_two: Vec<_> = v.iter().take(2).collect();
// skip - skip first n elements
let rest: Vec<_> = v.iter().skip(2).collect();
// rev - reverse
let reversed: Vec<_> = v.iter().rev().collect();
// chain - concatenate iterators
let chain = a.iter().chain(b.iter());let v = vec![1, 2, 3];
let sum: i32 = v.iter().sum();
let product: i32 = v.iter().product();
let min = v.iter().min();
let max = v.iter().max();
let any_even = v.iter().any(|&x| x % 2 == 0);
let all_positive = v.iter().all(|&x| x > 0);
let first = v.iter().find(|&&x| x > 1);
let position = v.iter().position(|&x| x == 2);
let count = v.iter().count();
let folded = v.iter().fold(0, |acc, &x| acc + x);struct Counter {
count: u32,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
self.count += 1;
if self.count < 6 {
Some(self.count)
} else {
None
}
}
}let b = Box::new(5);
println!("b = {}", b);
// Recursive type (cons list)
enum List {
Cons(i32, Box<List>),
Nil,
}
use List::{Cons, Nil};
let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));use std::rc::Rc;
let a = Rc::new(String::from("hello"));
let b = Rc::clone(&a); // increase ref count
let c = Rc::clone(&a);
println!("count: {}", Rc::strong_count(&a));use std::cell::RefCell;
let data = RefCell::new(5);
*data.borrow_mut() = 10; // mutate through immutable reference
println!("{}", data.borrow());use std::rc::Rc;
use std::cell::RefCell;
// Multiple ownership of mutable data
let shared = Rc::new(RefCell::new(5));
let a = Rc::clone(&shared);
let b = Rc::clone(&shared);
*a.borrow_mut() += 1;
println!("{}", b.borrow());use std::rc::{Rc, Weak};
struct Node {
value: i32,
parent: RefCell<Weak<Node>>,
children: RefCell<Vec<Rc<Node>>>,
}use std::ops::{Deref, Drop};
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> Drop for MyBox<T> {
fn drop(&mut self) {
println!("Dropping!");
}
}use std::thread;
use std::time::Duration;
// Spawn thread
let handle = thread::spawn(|| {
for i in 1..10 {
println!("number {} from spawned thread", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("number {} from main thread", i);
thread::sleep(Duration::from_millis(1));
}
handle.join().unwrap(); // wait for threadlet v = vec![1, 2, 3];
let handle = thread::spawn(move || {
println!("{:?}", v);
});
handle.join().unwrap();
// v no longer accessibleuse std::sync::mpsc;
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(String::from("hello")).unwrap();
});
let received = rx.recv().unwrap(); // blocking
println!("Got: {}", received);
// Multiple producers
let tx1 = tx.clone();use std::sync::{Arc, Mutex};
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());use std::sync::atomic::{AtomicUsize, Ordering};
let atomic = AtomicUsize::new(0);
atomic.fetch_add(1, Ordering::SeqCst);
atomic.store(42, Ordering::SeqCst);
println!("{}", atomic.load(Ordering::SeqCst));Send: Types that can be transferred between threadsSync: Types that can be shared between threads
// lib.rs or main.rs
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
fn seat_at_table() {}
}
mod serving {
fn take_order() {}
fn serve_order() {}
}
}// Absolute path
crate::front_of_house::hosting::add_to_waitlist();
// Relative path
front_of_house::hosting::add_to_waitlist();
// super (parent module)
fn serve_order() {}
mod back_of_house {
fn fix_incorrect_order() {
super::serve_order();
}
}pub fn public_function() {} // public
fn private_function() {} // private
pub mod module { // public module
pub fn public() {} // public function
fn private() {} // private function
}
pub struct PublicStruct {
pub public_field: i32, // public field
private_field: i32, // private field
}
pub enum PublicEnum {
Variant1, // all variants public
Variant2,
}use std::collections::HashMap;
// Multiple imports
use std::fmt::{self, Display, Debug};
// Nested paths
use std::{
collections::HashMap,
fs::File,
io::{self, Read},
};
// Glob import
use std::collections::*;
// Renaming (as)
use std::fmt::Result as FmtResult;[dependencies]
serde = "1.0"
rand = "0.8"
tokio = { version = "1.0", features = ["full"] }pub use self::hosting::add_to_waitlist; // re-export#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
#[test]
fn another_test() {
panic!("This test fails!");
}
}assert!(condition);
assert_eq!(a, b);
assert_ne!(a, b);
// With custom messages
assert!(condition, "Custom message: {}", value);
assert_eq!(a, b, "Expected {} but got {}", b, a);#[test]
#[ignore] // ignore this test
fn expensive_test() {
// code
}
#[test]
#[should_panic(expected = "specific error message")]
fn test_panic() {
panic!("specific error message");
}
#[test]
#[should_panic]
fn test_generic_panic() {
panic!("any error");
}#[test]
fn test_result() -> Result<(), String> {
if 2 + 2 == 4 {
Ok(())
} else {
Err(String::from("two plus two does not equal four"))
}
}// tests/integration_test.rs
use my_crate;
#[test]
fn integration_test() {
assert_eq!(my_crate::add(2, 2), 4);
}cargo test # run all tests
cargo test -- --nocapture # show println! output
cargo test test_name # run specific test
cargo test -- --ignored # run ignored tests
cargo test --test integration_test # specific integration test// Dereference raw pointers
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);
}
// Call unsafe functions
unsafe fn dangerous() {}
unsafe { dangerous(); }
// Access/modify mutable static variables
static mut COUNTER: u32 = 0;
unsafe { COUNTER += 1; }
// Implement unsafe trait
unsafe trait Foo {}
unsafe impl Foo for i32 {}macro_rules! vec {
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
};
}
// Usage
let v = vec![1, 2, 3];// In a separate crate
use proc_macro::TokenStream;
#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
// implementation
}trait Iterator {
type Item; // associated type
fn next(&mut self) -> Option<Self::Item>;
}use std::ops::Add;
#[derive(Debug, PartialEq)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}impl From<String> for MyType {
fn from(s: String) -> Self {
MyType { value: s }
}
}
let my = MyType::from(String::from("hello"));
// Into is automatic when From is implemented
let my: MyType = String::from("hello").into();| Macro | Purpose |
|---|---|
println!() |
Print with newline |
print!() |
Print without newline |
format!() |
Format string |
vec![] |
Create vector |
assert!() |
Assert condition |
assert_eq!() |
Assert equality |
unreachable!() |
Mark unreachable code |
todo!() |
Mark incomplete code |
unimplemented!() |
Mark unimplemented code |
panic!() |
Panic with message |
include_str!() |
Include file as string |
include_bytes!() |
Include file as bytes |
concat!() |
Concatenate literals |
stringify!() |
Stringify expression |
cfg!() |
Compile-time configuration |
env!() |
Environment variable |
file!() |
Current file |
line!() |
Current line |
column!() |
Current column |
module_path!() |
Current module path |
cargo new project_name # create new binary project
cargo new --lib project_name # create new library
cargo build # build project
cargo build --release # build with optimizations
cargo run # build and run
cargo check # check without building
cargo test # run tests
cargo doc # generate documentation
cargo doc --open # open docs in browser
cargo clean # remove target directory
cargo update # update dependenciescargo add crate_name # add dependency
cargo remove crate_name # remove dependency
cargo tree # show dependency tree
cargo fmt # format code
cargo clippy # lint code
cargo bench # run benchmarks
cargo install crate_name # install binary crate
cargo uninstall crate_name # uninstall
cargo publish # publish to crates.io
cargo login # login to crates.iocargo new my-workspace --bin
# Create Cargo.toml workspace
[workspace]
members = ["adder", "subtractor"][build]
rustflags = ["-C", "target-cpu=native"]
[target.x86_64-unknown-linux-gnu]
linker = "clang"
[alias]
a = "run --release"
t = "test"Read file contents:
use std::fs;
let contents = fs::read_to_string("file.txt")?;Write to file:
use std::fs::File;
use std::io::Write;
let mut file = File::create("file.txt")?;
file.write_all(b"Hello")?;Parse string to number:
let num: i32 = "42".parse()?;Match multiple patterns:
match value {
1 | 2 | 3 => println!("1-3"),
4..=10 => println!("4-10"),
_ => (),
}String to Vec:
let chars: Vec<char> = "hello".chars().collect();Vec to String:
let s: String = vec!['h', 'e', 'l', 'l', 'o'].into_iter().collect();Sleep/delay:
use std::thread;
use std::time::Duration;
thread::sleep(Duration::from_secs(1));
thread::sleep(Duration::from_millis(100));Time measurement:
use std::time::Instant;
let start = Instant::now();
// code
println!("{:?}", start.elapsed());This cheatsheet covers the most essential Rust programming concepts. For more details, refer to The Rust Book and Rust by Example.