Created binary (application) `rust-quest` package
rust.quest
The quest to master systems programming.
Memory safety without garbage collection.
Fearless concurrency. Zero-cost abstractions.
Begin your journey below.
Chapter 01: Ownership & Borrowing
3 let s1 = String::from("hello");
4 let s2 = s1; // s1 moved here
5 println!("{}", s1);
^^ value used here after move
help: consider cloning the value
let s2 = s1.clone();
Rust's ownership system ensures every value has exactly one owner.
When ownership moves, the original binding becomes invalid.
This prevents double-free errors and data races at compile time.
Chapter 02: Lifetimes
fn longest<'a>(
x: &'a str,
y: &'a str,
) -> &'a str {
if x.len() > y.len() { x } else { y }
}
Lifetimes tell the compiler how long references are valid.
They prevent dangling references without runtime overhead.
The borrow checker enforces lifetime constraints at compile time.
warning: unused variable `longest`
Chapter 03: Fearless Concurrency
use std::thread;
use std::sync::Arc;
let data = Arc::new(vec![1, 2, 3]);
let handles: Vec<_> = (0..3).map(|i| {
let data = Arc::clone(&data);
thread::spawn(move || {
data[i]
})
}).collect();
Rust's type system prevents data races at compile time.
Send and Sync traits enforce thread safety guarantees.
Fearless concurrency means correct concurrent code by default.
Chapter 04: Pattern Matching
enum Quest {
Beginning,
InProgress(String),
Complete { score: u32 },
}
match quest {
Quest::Beginning => start(),
Quest::InProgress(topic) => learn(&topic),
Quest::Complete { score } => celebrate(score),
}
Pattern matching is exhaustive -- the compiler ensures all cases are handled.
Destructuring extracts values from complex data types elegantly.
The `match` arm syntax mirrors logical branches in your quest.
Chapter 05: Traits & Generics
trait Learnable {
fn study(&self) -> String;
fn difficulty(&self) -> u8 { 5 } // default impl
}
fn teach<T: Learnable>(item: &T) {
println!("{}", item.study());
}
Traits define shared behavior across types -- Rust's answer to interfaces.
Generics allow code reuse without sacrificing type safety or performance.
Trait objects (`dyn Trait`) enable runtime polymorphism when needed.
Chapter 06: Error Handling
7 fn read_config() -> Result<String, io::Error> {
8 let content = fs::read_to_string("config.toml");
9 content // missing ?
^^ consider using `?` to propagate errors
fn read_config() -> Result<String, io::Error> {
let content = fs::read_to_string("config.toml")?;
Ok(content)
}
Result<T, E> makes errors explicit -- no hidden exceptions.
The `?` operator propagates errors ergonomically up the call stack.
Chapter 07: Closures & Iterators
let chapters = vec![
"ownership", "lifetimes", "concurrency",
];
let completed: Vec<_> = chapters
.iter()
.filter(|ch| ch.len() > 8)
.map(|ch| format!("✓ {}", ch))
.collect();
Closures capture their environment -- anonymous functions with state.
Iterator adaptors are zero-cost abstractions that compile to tight loops.
✓ ownership ✓ lifetimes ✓ concurrency
Chapter 08: Macros
macro_rules! quest {
($topic:expr, $($step:expr),+) => {
println!("Quest: {}", $topic);
$(println!(" step: {}", $step);)+
};
}
quest!("Rust", "read", "compile", "ship");
Macros operate on syntax trees -- metaprogramming at compile time.
`macro_rules!` is declarative; proc macros are procedural and more powerful.
Chapter 09: Unsafe Rust
1 unsafe fn dangerous() {
2 let raw_ptr: *const i32 = &42;
3 let val = *raw_ptr; // dereference raw pointer
4 }
Unsafe Rust opts out of compiler guarantees for specific operations.
Raw pointers, FFI, and manual memory -- the power that safe Rust builds upon.
The quest demands you understand the rules before breaking them.
Compiling rust-quest v0.1.0
Compiling ownership v0.1.0
Compiling lifetimes v0.1.0
Compiling concurrency v0.1.0
Finished release [optimized] target(s) in 2.34s
Binary: target/release/rust-quest