Today I discovered excellent resources for learning Rust systematically, from beginner-friendly interactive tutorials to advanced concepts that highlight why Rust is becoming the go-to systems programming language.

Interactive Rust Learning

Tour of Rust - Interactive Learning

Tour of Rust provides an interactive way to learn Rust similar to Go’s famous tour. It covers almost the entire Rust Book content through hands-on exercises:

đź“‹ Tour of Rust Coverage
  • Basics: Variables, functions, control flow
  • Ownership: Borrowing, references, lifetimes
  • Types: Structs, enums, traits, generics
  • Error Handling: Result types and error propagation
  • Memory Management: Stack vs heap, smart pointers
  • Concurrency: Threads, channels, async/await
  • Advanced Features: Macros, unsafe code, FFI

The interactive format allows you to run Rust code directly in the browser, making it perfect for learning without setting up a local development environment.

Rust by Example

Rust by Example takes a hands-on approach to learning Rust concepts:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Pattern matching with enums
enum WebEvent {
    PageLoad,
    PageUnload,
    KeyPress(char),
    Paste(String),
    Click { x: i64, y: i64 },
}

fn inspect(event: WebEvent) {
    match event {
        WebEvent::PageLoad => println!("page loaded"),
        WebEvent::PageUnload => println!("page unloaded"),
        WebEvent::KeyPress(c) => println!("pressed '{}'", c),
        WebEvent::Paste(s) => println!("pasted \"{}\"", s),
        WebEvent::Click { x, y } => {
            println!("clicked at x={}, y={}", x, y);
        },
    }
}

fn main() {
    let pressed = WebEvent::KeyPress('x');
    let pasted = WebEvent::Paste("my text".to_owned());
    let click = WebEvent::Click { x: 20, y: 80 };
    
    inspect(pressed);
    inspect(pasted);
    inspect(click);
}

Advanced Rust Resources

Learn Rust the Dangerous Way

Learn Rust the Dangerous Way by Cliff Biffle teaches Rust from the perspective of a C programmer, highlighting dangerous practices and how Rust prevents them:

⚠️ Common Dangerous Patterns

C/C++ Problems that Rust Solves:

  • Buffer overflows - Rust’s bounds checking prevents array access violations
  • Use-after-free - Ownership system ensures memory safety
  • Double-free - RAII and ownership prevent double deallocations
  • Data races - Type system enforces thread safety at compile time
  • Null pointer dereferences - Option types eliminate null pointer errors
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Rust prevents dangerous memory access
fn safe_array_access() {
    let arr = [1, 2, 3, 4, 5];
    
    // This would panic at runtime, not cause undefined behavior
    // let value = arr[10]; // panic: index out of bounds
    
    // Safe alternative using get()
    match arr.get(10) {
        Some(value) => println!("Value: {}", value),
        None => println!("Index out of bounds"),
    }
}

// Ownership prevents use-after-free
fn ownership_safety() {
    let data = String::from("Hello");
    let reference = &data;
    
    // drop(data); // This would cause compile error
    // println!("{}", reference); // Can't use reference after data is dropped
    
    println!("{}", reference); // Safe because data is still alive
}

Little Book of Rust Macros

Little Book of Rust Macros provides comprehensive coverage of Rust’s macro system:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Declarative macros (macro_rules!)
macro_rules! vec {
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
            )*
            temp_vec
        }
    };
}

// Usage
let v = vec![1, 2, 3, 4, 5];

// Custom debug macro
macro_rules! debug_print {
    ($($arg:tt)*) => {
        #[cfg(debug_assertions)]
        println!("[DEBUG] {}", format_args!($($arg)*));
    };
}

// Only prints in debug builds
debug_print!("Processing item: {}", item_id);

Rust Adoption Challenges

Problems in Rust Adoption discusses real-world challenges when adopting Rust:

📝 Rust Adoption Considerations

Learning Curve Challenges:

  • Ownership system - Requires fundamental shift in thinking
  • Lifetime annotations - Complex for beginners coming from GC languages
  • Compiler strictness - Initially frustrating but prevents runtime errors
  • Ecosystem maturity - Some libraries still emerging compared to C++ or Python

Migration Strategies:

  • Start with new components rather than rewriting existing code
  • Use Rust for performance-critical or safety-critical parts
  • Leverage FFI to integrate with existing C/C++ codebases
  • Invest in team training and mentorship

Development Tools and Performance

Py-Spy for Python Profiling

Py-Spy is a sampling profiler for Python programs, written in Rust for minimal overhead:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Install py-spy
pip install py-spy

# Profile a running Python process
py-spy record -o profile.svg --pid 12345

# Profile a Python script
py-spy record -o profile.svg -- python myscript.py

# Top-like interface for live profiling
py-spy top --pid 12345
đź’ˇ Why Py-Spy is Special

Unlike traditional Python profilers, py-spy:

  • Zero overhead when not profiling
  • Works with any Python program without modification
  • Minimal impact on the target process (written in Rust)
  • Rich output formats including flame graphs and call trees
  • Works with C extensions and shows full stack traces

The fact that py-spy is written in Rust demonstrates Rust’s effectiveness for building high-performance tools that interact with other language runtimes.

Modern Command Line Tools

Several excellent command-line tools are written in Rust, showcasing its performance and ergonomics:

Tokei - Better Code Counting

tokei is a faster, more accurate alternative to cloc:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Count lines of code in a project
tokei

# Specific languages only
tokei --languages rust,python

# Exclude test files
tokei --exclude '*.test.*'

# JSON output for automation
tokei --output json

Bat - Enhanced Cat

bat provides syntax highlighting and Git integration:

1
2
3
4
5
6
7
8
# View file with syntax highlighting
bat src/main.rs

# Show line numbers and git changes
bat --number --show-all src/main.rs

# Use as pager replacement
export PAGER="bat --plain"

Ripgrep - Superior Grep

ripgrep offers incredible search performance:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Basic search
rg "pattern" 

# Search specific file types
rg "TODO" --type rust

# Case insensitive with context
rg -i "error" -C 3

# Regular expressions
rg "fn\s+\w+\(" --type rust
đź“‹ Rust CLI Tool Benefits

These Rust-based tools demonstrate key advantages:

  • Performance: Significantly faster than traditional Unix tools
  • Safety: Memory safety prevents crashes and undefined behavior
  • Ergonomics: Better defaults and user-friendly output
  • Cross-platform: Work consistently across Linux, macOS, and Windows
  • Modern features: Git integration, syntax highlighting, smart defaults

Systems Programming Insights

Linux From Scratch

Linux From Scratch teaches Linux system internals by building a complete Linux system from source code:

The project helps understand:

  • Boot process and system initialization
  • Package management and dependency resolution
  • System libraries and their interactions
  • Kernel compilation and configuration
  • Development toolchain creation

This knowledge is invaluable when working with Rust for systems programming, as it provides deep understanding of the runtime environment where Rust programs execute.

Memory Management Fundamentals

Understanding how Rust’s ownership system maps to actual memory management:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Stack allocation - automatic cleanup
fn stack_example() {
    let x = 42;           // Stored on stack
    let y = [1, 2, 3];    // Array on stack
} // x and y automatically cleaned up

// Heap allocation - controlled by ownership
fn heap_example() {
    let data = String::from("Hello");  // Heap allocated
    let moved_data = data;             // Ownership transfer
    // println!("{}", data);           // Compile error - data moved
    println!("{}", moved_data);        // OK - new owner
} // moved_data automatically freed

// Borrowing - temporary access without ownership transfer
fn borrowing_example() {
    let data = String::from("World");
    let len = calculate_length(&data); // Borrow, don't move
    println!("Length of '{}' is {}", data, len); // data still valid
}

fn calculate_length(s: &String) -> usize {
    s.len() // Can read, but can't modify without &mut
}

Integration and Interoperability

Foreign Function Interface (FFI)

Rust’s FFI capabilities make it excellent for:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Calling C code from Rust
extern "C" {
    fn abs(input: i32) -> i32;
    fn strlen(s: *const c_char) -> size_t;
}

// Exposing Rust code to C
#[no_mangle]
pub extern "C" fn add_numbers(a: i32, b: i32) -> i32 {
    a + b
}

// Python extension using PyO3
use pyo3::prelude::*;

#[pyfunction]
fn fibonacci_rust(n: u64) -> u64 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci_rust(n - 1) + fibonacci_rust(n - 2),
    }
}

#[pymodule]
fn rust_extensions(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(fibonacci_rust, m)?)?;
    Ok(())
}

Learning Strategy and Resources

  1. Start with Tour of Rust - Interactive, hands-on introduction
  2. Read Rust by Example - Practical code patterns and idioms
  3. Study The Rust Book - Comprehensive language reference
  4. Practice with Rustlings - Small exercises to reinforce concepts
  5. Explore Little Book of Rust Macros - Advanced metaprogramming
  6. Read “Learn Rust the Dangerous Way” - Systems programming perspective

Key Concepts to Master

đź’ˇ Essential Rust Concepts
  1. Ownership and Borrowing - Core memory safety guarantees
  2. Pattern Matching - Exhaustive case analysis with match
  3. Error Handling - Result and Option types for safe error management
  4. Traits - Rust’s interface system for polymorphism
  5. Lifetimes - Ensuring references remain valid
  6. Concurrency - Safe parallel programming with ownership
  7. Macros - Code generation and domain-specific languages

Why Rust Matters

Rust addresses fundamental problems in systems programming:

  1. Memory Safety: Eliminates entire classes of bugs at compile time
  2. Performance: Zero-cost abstractions with C/C++ level performance
  3. Concurrency: Fearless concurrency through type system guarantees
  4. Tooling: Excellent package manager (Cargo) and development experience
  5. Ecosystem: Growing collection of high-quality libraries (crates)
đź’¬ Rust Philosophy
Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.

This exploration of Rust learning resources demonstrates why Rust has become essential for modern systems programming, offering both safety and performance without compromise.


These Rust learning resources from my archive showcase the language’s evolution from experimental to production-ready, with a rich ecosystem of educational content and powerful development tools.