{"id":25409605,"url":"https://github.com/bluntbrain/rust-notes-and-projects","last_synced_at":"2025-04-14T01:17:48.430Z","repository":{"id":277378178,"uuid":"931750343","full_name":"bluntbrain/rust-notes-and-projects","owner":"bluntbrain","description":"My RUST learning journey, detailed notes and practical game projects (Guessing Game and Tic Tac Toe)","archived":false,"fork":false,"pushed_at":"2025-04-09T21:46:29.000Z","size":396,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-14T01:17:39.358Z","etag":null,"topics":["rust","rust-lang"],"latest_commit_sha":null,"homepage":"https://bluntbrain.vercel.app/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bluntbrain.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-12T19:46:42.000Z","updated_at":"2025-04-09T21:46:32.000Z","dependencies_parsed_at":"2025-04-08T13:36:23.146Z","dependency_job_id":null,"html_url":"https://github.com/bluntbrain/rust-notes-and-projects","commit_stats":null,"previous_names":["bluntbrain/my-rust-notes","bluntbrain/rust-notes-and-projects"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluntbrain%2Frust-notes-and-projects","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluntbrain%2Frust-notes-and-projects/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluntbrain%2Frust-notes-and-projects/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluntbrain%2Frust-notes-and-projects/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bluntbrain","download_url":"https://codeload.github.com/bluntbrain/rust-notes-and-projects/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248804824,"owners_count":21164135,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rust","rust-lang"],"created_at":"2025-02-16T09:21:07.295Z","updated_at":"2025-04-14T01:17:48.411Z","avatar_url":"https://github.com/bluntbrain.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rust Notes and Projects\n\n## Projects\n1. [Guessing Game](guessing_game/src/game.rs) - A simple fruit guessing game using random selection\n2. [Tic Tac Toe](tic_tac_toe/src/game.rs) - A command-line implementation of Tic Tac Toe\n\n## Table of Contents\n- [Introduction \u0026 Setup](#introduction--setup)\n- [Basic Concepts](#basic-concepts)\n  - [Variables and Mutability](#variables-and-mutability)\n  - [Shadowing](#shadowing)\n  - [Data Types](#data-types)\n  - [Control Flow](#control-flow)\n  - [Functions](#functions)\n- [Memory Management](#memory-management-fundamentals)\n- [Ownership System](#ownership-system)\n- [References \u0026 Borrowing](#references--borrowing)\n- [Collections](#collections)\n  - [Vectors](#vectors-vec)\n  - [Strings](#strings)\n  - [HashMaps](#hashmaps)\n- [Compound Types](#compound-types)\n  - [Structs](#structs)\n  - [Enums](#enums)\n- [Pattern Matching](#pattern-matching)\n- [Error Handling](#error-handling)\n- [Generic Types \u0026 Traits](#generic-types--traits)\n- [Modules \u0026 Project Organization](#modules--project-organization)\n- [Concurrency](#concurrency)\n- [Testing](#testing)\n- [Smart Pointers](#smart-pointers)\n- [Macros](#macros)\n\n---\n\n## Introduction \u0026 Setup\n\n### What is Rust?\nRust is a systems programming language that focuses on:\n- Memory safety without garbage collection\n- Concurrency without data races\n- Zero-cost abstractions\n- Performance\n\n### Installation\n```bash\n# Unix-based systems\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n\n# Verify installation\nrustc --version\ncargo --version\n```\n\n### Essential Cargo Commands\n```bash\ncargo new project_name    # Create new project\ncargo build              # Compile project\ncargo run               # Run project\ncargo test              # Run tests\ncargo check             # Check if code compiles\ncargo doc --open        # Generate and view documentation\n```\n\n### Your First Program\n```rust\n// src/main.rs\nfn main() {\n    println!(\"Hello, Rust!\");\n}\n```\n\n---\n\n## Basic Concepts\n\n### Variables and Mutability\n\u003e Summary: Variables are immutable by default. Use `mut` to make them mutable.\n\n```rust\nfn main() {\n    let x = 5;          // Immutable\n    // x = 6;           // Error!\n    \n    let mut y = 5;      // Mutable\n    y = 6;              // OK\n    \n    // Constants\n    const MAX_POINTS: u32 = 100_000;\n}\n```\n\n### Shadowing\n\u003e Summary: A new variable can be declared with the same name as a previous variable, effectively shadowing it.\n\n```rust\nfn main() {\n    // Basic shadowing\n    let x = 5;\n    let x = x + 1;        // Creates new variable, shadows previous x\n    let x = x * 2;        // Creates another new variable\n    println!(\"x is: {}\", x);  // Prints: x is: 12\n    \n    // Shadowing with different types\n    let spaces = \"   \";           // String type\n    let spaces = spaces.len();    // Number type\n    \n    // Shadowing in different scopes\n    let y = 5;\n    {\n        let y = 12;      // Only shadows within this scope\n        println!(\"Inner y: {}\", y);  // Prints: Inner y: 12\n    }\n    println!(\"Outer y: {}\", y);  // Prints: Outer y: 5\n    \n    // Shadowing vs mut\n    let mut z = 5;\n    // let z = \"hello\";  // OK with shadowing\n    // z = \"hello\";      // Error! Can't change type with mut\n}\n```\n\n#### Key Differences from mut\n1. Shadowing creates a new variable\n2. Can change type\n3. Maintains immutability\n4. Scope-based\n\n```rust\nfn main() {\n    // With shadowing - OK\n    let data = \"   \";\n    let data = data.len();\n    \n    // With mut - Error!\n    let mut value = \"   \";\n    // value = value.len();  // Type mismatch error\n    \n    // Shadowing preserves immutability\n    let number = 5;\n    let number = number + 5;  // Creates new immutable binding\n    // number += 1;          // Error! number is immutable\n}\n```\n\n### Data Types\n\n#### Scalar Types\n1. **Integers**\n```rust\nlet i: i32 = -42;       // Signed 32-bit integer\nlet u: u32 = 42;        // Unsigned 32-bit integer\nlet b: i8 = -128;       // Signed 8-bit integer\nlet big: i128 = 123;    // Signed 128-bit integer\n```\n\n2. **Floating-Point**\n```rust\nlet f: f64 = 3.14159;   // 64-bit float (default)\nlet f: f32 = 3.14;      // 32-bit float\n```\n\n3. **Boolean**\n```rust\nlet t: bool = true;\nlet f: bool = false;\n```\n\n4. **Character**\n```rust\nlet c: char = 'z';\nlet emoji: char = '😀';  // Unicode character\n```\n\n### Strings and String Slices\n\u003e Summary: Rust has two main string types: String (owned) and \u0026str (borrowed string slice).\n\n```rust\nfn main() {\n    // String type (owned, growable)\n    let mut s = String::from(\"hello\");  // Heap allocated\n    s.push_str(\", world!\");            // Can modify\n    println!(\"{}\", s);\n    \n    // String literal (\u0026str type)\n    let s1: \u0026str = \"hello world\";      // Fixed size, immutable\n    \n    // String slices\n    let hello: \u0026str = \u0026s[0..5];        // Slice of String\n    let world: \u0026str = \u0026s[7..12];       // Another slice\n    \n    // Converting between String and \u0026str\n    let owned: String = \"hello\".to_string();  // \u0026str to String\n    let owned: String = String::from(\"hello\"); // Another way\n    let borrowed: \u0026str = \u0026owned;              // String to \u0026str\n    \n    // String concatenation\n    let s1 = String::from(\"Hello, \");\n    let s2 = String::from(\"world!\");\n    let s3 = s1 + \u0026s2;  // s1 is moved here, s2 is borrowed\n    \n    // Format macro\n    let s = format!(\"{}-{}-{}\", \"Hello\", \"world\", \"!\");\n}\n```\n\n#### Key Differences\n```rust\nfn main() {\n    // Memory allocation\n    let s1 = String::from(\"hello\");  // Heap allocated\n    let s2 = \"hello\";                // Stored in binary\n    \n    // Mutability\n    let mut s = String::from(\"hello\");\n    s.push_str(\" world\");           // OK with String\n    // \"hello\".push_str(\" world\");  // Error with \u0026str\n    \n    // Function parameters\n    fn takes_slice(s: \u0026str) {       // Can accept both String and \u0026str\n        println!(\"{}\", s);\n    }\n    \n    fn takes_string(s: String) {    // Only accepts String\n        println!(\"{}\", s);\n    }\n    \n    // Common operations\n    let len = \"hello\".len();        // Length\n    let chars = \"hello\".chars();    // Iterator over chars\n    let bytes = \"hello\".as_bytes(); // As byte slice\n    \n    // UTF-8\n    let hello = String::from(\"Здравствуйте\");\n    let s = \u0026hello[0..2];  // Takes 2 bytes (1 character)\n}\n```\n\n#### Best Practices\n```rust\n// Use \u0026str for function parameters\nfn greet(name: \u0026str) {\n    println!(\"Hello, {}!\", name);\n}\n\n// Use String when you need to own and modify\nfn build_greeting() -\u003e String {\n    let mut greeting = String::from(\"Hello\");\n    greeting.push_str(\", world!\");\n    greeting\n}\n\n// String interning\nfn main() {\n    let s1: \u0026str = \"Hello\";  // Single allocation in binary\n    let s2: \u0026str = \"Hello\";  // Points to same memory\n    assert!(std::ptr::eq(s1, s2));\n}\n```\n\n### Control Flow\n\n#### Conditionals\n```rust\nfn main() {\n    let number = 6;\n\n    // If expression\n    if number % 4 == 0 {\n        println!(\"number is divisible by 4\");\n    } else if number % 3 == 0 {\n        println!(\"number is divisible by 3\");\n    } else {\n        println!(\"number is not divisible by 4 or 3\");\n    }\n\n    // If in a let statement\n    let condition = true;\n    let number = if condition { 5 } else { 6 };\n}\n```\n\n#### Loops\n```rust\nfn main() {\n    // Loop (infinite)\n    let mut counter = 0;\n    let result = loop {\n        counter += 1;\n        if counter == 10 {\n            break counter * 2;\n        }\n    };\n\n    // While loop\n    let mut number = 3;\n    while number != 0 {\n        println!(\"{}!\", number);\n        number -= 1;\n    }\n\n    // For loop\n    for number in (1..4).rev() {\n        println!(\"{}!\", number);\n    }\n}\n```\n\n### Functions\n```rust\nfn main() {\n    println!(\"Sum: {}\", add(5, 6));\n}\n\nfn add(x: i32, y: i32) -\u003e i32 {\n    x + y  // Implicit return (no semicolon)\n}\n\n// Function with multiple parameters\nfn print_labeled_measurement(value: i32, unit_label: char) {\n    println!(\"The measurement is: {}{}\", value, unit_label);\n}\n```\n\n---\n\n## Memory Management\n\n### Stack vs Heap Memory\n\n| Characteristic | Stack | Heap |\n|---------------|--------|-------|\n| Speed | Faster (push/pop) | Slower (allocation/deallocation) |\n| Size | Limited, fixed-size data | Dynamic, flexible size data |\n| Organization | LIFO (Last In, First Out) | Unordered, accessed via pointers |\n| Memory Management | Automatic | Manual (handled by ownership in Rust) |\n| Data Types | Known size at compile time | Unknown size at compile time |\n| Access Pattern | Direct, sequential | Random access via pointers |\n| Common Uses | - Local variables\u003cbr\u003e- Function parameters\u003cbr\u003e- Fixed-size arrays | - Strings\u003cbr\u003e- Vectors\u003cbr\u003e- Boxes\u003cbr\u003e- Other dynamic data |\n\n#### Example\n```rust\nfn main() {\n    // Stack allocation\n    let x = 42;                    // Integer on stack\n    let y = true;                  // Boolean on stack\n    \n    // Heap allocation\n    let s = String::from(\"hello\"); // String data on heap, pointer on stack\n    let v = vec![1, 2, 3];        // Vector data on heap, pointer on stack\n}\n```\n\n---\n\n## Ownership System\n\u003e Summary: Ownership is Rust's most unique feature, ensuring memory safety at compile time without garbage collection.\n\n### Core Ownership Rules\n1. Each value has exactly one owner\n2. There can only be one owner at a time\n3. When the owner goes out of scope, the value is dropped\n\n### Basic Ownership Examples\n```rust\nfn main() {\n    // Simple ownership\n    let s1 = String::from(\"hello\");\n    let s2 = s1;                // s1 is moved to s2\n    // println!(\"{}\", s1);      // Error! s1 is no longer valid\n    println!(\"{}\", s2);         // Works fine\n\n    // Clone for deep copy\n    let s3 = String::from(\"hello\");\n    let s4 = s3.clone();       // Creates a deep copy\n    println!(\"{} {}\", s3, s4); // Both valid\n}\n```\n\n### Ownership with Functions\n```rust\nfn main() {\n    let s = String::from(\"hello\");\n    takes_ownership(s);        // s is moved into the function\n    // println!(\"{}\", s);      // Error! s is no longer valid\n\n    let x = 5;\n    makes_copy(x);            // i32 is Copy, so x is still valid\n    println!(\"{}\", x);        // Works fine\n}\n\nfn takes_ownership(string: String) {\n    println!(\"{}\", string);\n}   // string is dropped here\n\nfn makes_copy(integer: i32) {\n    println!(\"{}\", integer);\n}   // integer goes out of scope (copy is dropped)\n```\n\n### Return Values and Scope\n```rust\nfn main() {\n    let s1 = gives_ownership();         // Move return value into s1\n    \n    let s2 = String::from(\"hello\");     // s2 comes into scope\n    \n    let s3 = takes_and_gives_back(s2);  // s2 moved into function\n                                        // return value moved into s3\n}\n\nfn gives_ownership() -\u003e String {\n    String::from(\"yours\")               // Return value moves out\n}\n\nfn takes_and_gives_back(a_string: String) -\u003e String {\n    a_string                            // Return value moves out\n}\n```\n\n---\n\n## References \u0026 Borrowing\n\u003e Summary: References allow you to refer to a value without taking ownership.\n\n### Basic References\n```rust\nfn main() {\n    let s1 = String::from(\"hello\");\n    \n    let len = calculate_length(\u0026s1);    // Pass reference to s1\n    println!(\"Length of '{}' is {}.\", s1, len);  // s1 is still valid\n}\n\nfn calculate_length(s: \u0026String) -\u003e usize {\n    s.len()\n}   // s goes out of scope, but doesn't drop the value it refers to\n```\n\n### Mutable References\n```rust\nfn main() {\n    let mut s = String::from(\"hello\");\n    \n    change(\u0026mut s);                     // Pass mutable reference\n    println!(\"{}\", s);                  // Prints: hello world\n}\n\nfn change(some_string: \u0026mut String) {\n    some_string.push_str(\" world\");\n}\n```\n\n### Reference Rules\n1. You can have either:\n   - One mutable reference\n   - Any number of immutable references\n2. References must always be valid (no dangling references)\n\n```rust\nfn main() {\n    let mut s = String::from(\"hello\");\n\n    let r1 = \u0026s;         // OK - immutable reference\n    let r2 = \u0026s;         // OK - multiple immutable references allowed\n    println!(\"{} {}\", r1, r2);\n    // r1 and r2 are no longer used after this point\n\n    let r3 = \u0026mut s;     // OK - no other references are active\n    println!(\"{}\", r3);\n}\n```\n\n### Slice Type\n\u003e Summary: Slices let you reference a contiguous sequence of elements rather than the whole collection.\n\n```rust\nfn main() {\n    let s = String::from(\"hello world\");\n\n    let hello = \u0026s[0..5];  // Slice from index 0 to 4\n    let world = \u0026s[6..11]; // Slice from index 6 to 10\n    \n    println!(\"{} {}\", hello, world);\n\n    // String slice parameter\n    let word = first_word(\u0026s);\n    println!(\"First word: {}\", word);\n}\n\nfn first_word(s: \u0026str) -\u003e \u0026str {\n    let bytes = s.as_bytes();\n\n    for (i, \u0026item) in bytes.iter().enumerate() {\n        if item == b' ' {\n            return \u0026s[0..i];\n        }\n    }\n\n    \u0026s[..]\n}\n```\n\n---\n\n## Collections\n\u003e Summary: Collections are data structures that can contain multiple values. The most common are Vec, String, and HashMap.\n\n### Vectors (Vec\u003cT\u003e)\n\u003e Summary: A vector is a growable array type that can hold any type T.\n\n#### Creating and Updating Vectors\n```rust\nfn main() {\n    // Creating vectors\n    let mut v1: Vec\u003ci32\u003e = Vec::new();        // Empty vector\n    let v2 = vec![1, 2, 3];                   // Using vec! macro\n    \n    // Adding elements\n    v1.push(1);\n    v1.push(2);\n    v1.push(3);\n    \n    // Accessing elements\n    let third: \u0026i32 = \u0026v2[2];                 // Direct indexing (may panic)\n    let safe_third: Option\u003c\u0026i32\u003e = v2.get(2); // Safe access with get()\n    \n    // Using match with safe access\n    match v2.get(2) {\n        Some(third) =\u003e println!(\"Third element is {}\", third),\n        None =\u003e println!(\"No third element\"),\n    }\n}\n```\n\n#### Iterating Over Vectors\n```rust\nfn main() {\n    let mut v = vec![100, 32, 57];\n    \n    // Immutable iteration\n    for i in \u0026v {\n        println!(\"{}\", i);\n    }\n    \n    // Mutable iteration\n    for i in \u0026mut v {\n        *i += 50;  // Dereference to modify\n    }\n}\n```\n\n#### Vector Memory Management\n```rust\nfn main() {\n    // Preallocating space\n    let mut v = Vec::with_capacity(10);\n    println!(\"Length: {}, Capacity: {}\", v.len(), v.capacity());\n    \n    // Growing beyond capacity\n    for i in 0..16 {\n        v.push(i);\n        println!(\"Length: {}, Capacity: {}\", v.len(), v.capacity());\n    }\n}\n```\n\n### Strings\n\u003e Summary: Strings in Rust come in two forms: String and \u0026str.\n\n#### String vs \u0026str\n```rust\nfn main() {\n    // String type (owned)\n    let mut s = String::from(\"hello\");\n    s.push_str(\" world\");    // Can modify String\n    \n    // String slice (\u0026str)\n    let s1: \u0026str = \"hello world\";  // String literal - immutable\n    let s2: \u0026str = \u0026s[..];         // Whole slice of String\n    let s3: \u0026str = \u0026s[0..5];       // Partial slice\n}\n```\n\n#### String Operations\n```rust\nfn main() {\n    // Concatenation\n    let s1 = String::from(\"Hello, \");\n    let s2 = String::from(\"world!\");\n    let s3 = s1 + \u0026s2;  // Note: s1 has been moved here\n    \n    // Format macro\n    let s = format!(\"{}-{}-{}\", \"Hello\", \"world\", \"!\");\n    \n    // Iteration\n    for c in \"नमस्ते\".chars() {\n        println!(\"{}\", c);\n    }\n    \n    for b in \"hello\".bytes() {\n        println!(\"{}\", b);\n    }\n}\n```\n\n### HashMaps\n\u003e Summary: HashMap\u003cK, V\u003e stores key-value pairs with O(1) lookup.\n\n#### Basic HashMap Usage\n```rust\nuse std::collections::HashMap;\n\nfn main() {\n    // Creating\n    let mut scores = HashMap::new();\n    \n    // Inserting\n    scores.insert(String::from(\"Blue\"), 10);\n    scores.insert(String::from(\"Yellow\"), 50);\n    \n    // Accessing\n    let team_name = String::from(\"Blue\");\n    let score = scores.get(\u0026team_name);\n    \n    // Iterating\n    for (key, value) in \u0026scores {\n        println!(\"{}: {}\", key, value);\n    }\n}\n```\n\n#### Updating HashMap Values\n```rust\nuse std::collections::HashMap;\n\nfn main() {\n    let mut scores = HashMap::new();\n    \n    // Overwriting\n    scores.insert(String::from(\"Blue\"), 10);\n    scores.insert(String::from(\"Blue\"), 25);  // Value is 25\n    \n    // Insert if key has no value\n    scores.entry(String::from(\"Yellow\")).or_insert(50);\n    \n    // Update based on old value\n    let text = \"hello world wonderful world\";\n    let mut map = HashMap::new();\n    \n    for word in text.split_whitespace() {\n        let count = map.entry(word).or_insert(0);\n        *count += 1;\n    }\n}\n```\n\n---\n\n## Compound Types\n\u003e Summary: Compound types can group multiple values into one type. The main compound types are structs and enums.\n\n### Structs\n\u003e Summary: Structs are custom data types that let you package related values together.\n\n#### Defining and Instantiating Structs\n```rust\n// Define a struct\nstruct User {\n    username: String,\n    email: String,\n    sign_in_count: u64,\n    active: bool,\n}\n\nfn main() {\n    // Create an instance\n    let mut user1 = User {\n        email: String::from(\"someone@example.com\"),\n        username: String::from(\"someusername123\"),\n        active: true,\n        sign_in_count: 1,\n    };\n\n    // Modify a field (if instance is mutable)\n    user1.email = String::from(\"newemail@example.com\");\n    \n    // Create instance from other instance\n    let user2 = User {\n        email: String::from(\"another@example.com\"),\n        username: String::from(\"anotherusername567\"),\n        ..user1  // Use remaining fields from user1\n    };\n}\n```\n\n#### Tuple Structs\n```rust\nstruct Color(i32, i32, i32);\nstruct Point(i32, i32, i32);\n\nfn main() {\n    let black = Color(0, 0, 0);\n    let origin = Point(0, 0, 0);\n    \n    // Access tuple struct fields\n    println!(\"First value: {}\", black.0);\n}\n```\n\n#### Methods and Associated Functions\n```rust\n#[derive(Debug)]\nstruct Rectangle {\n    width: u32,\n    height: u32,\n}\n\nimpl Rectangle {\n    // Associated function (like a static method)\n    fn square(size: u32) -\u003e Rectangle {\n        Rectangle {\n            width: size,\n            height: size,\n        }\n    }\n    \n    // Method\n    fn area(\u0026self) -\u003e u32 {\n        self.width * self.height\n    }\n    \n    // Method that takes ownership\n    fn can_hold(\u0026self, other: \u0026Rectangle) -\u003e bool {\n        self.width \u003e other.width \u0026\u0026 self.height \u003e other.height\n    }\n}\n\nfn main() {\n    let rect1 = Rectangle {\n        width: 30,\n        height: 50,\n    };\n    \n    // Call method\n    println!(\"Area: {}\", rect1.area());\n    \n    // Call associated function\n    let square = Rectangle::square(20);\n}\n```\n\n### Enums\n\u003e Summary: Enums allow you to define a type by enumerating its possible variants.\n\n#### Basic Enum Definition\n```rust\nenum IpAddrKind {\n    V4(u8, u8, u8, u8),\n    V6(String),\n}\n\nfn main() {\n    let home = IpAddrKind::V4(127, 0, 0, 1);\n    let loopback = IpAddrKind::V6(String::from(\"::1\"));\n}\n```\n\n#### Complex Enum Example\n```rust\nenum Message {\n    Quit,                       // No data\n    Move { x: i32, y: i32 },   // Anonymous struct\n    Write(String),             // Single value\n    ChangeColor(i32, i32, i32),// Tuple\n}\n\nimpl Message {\n    fn call(\u0026self) {\n        // Method implementation\n        match self {\n            Message::Quit =\u003e println!(\"Quit\"),\n            Message::Move { x, y } =\u003e println!(\"Move to {}, {}\", x, y),\n            Message::Write(text) =\u003e println!(\"Text message: {}\", text),\n            Message::ChangeColor(r, g, b) =\u003e println!(\"Change color to: {}, {}, {}\", r, g, b),\n        }\n    }\n}\n\nfn main() {\n    let msg = Message::Write(String::from(\"hello\"));\n    msg.call();\n}\n```\n\n#### Option Enum\n```rust\nfn main() {\n    // Some value\n    let some_number = Some(5);\n    let some_string = Some(\"a string\");\n    \n    // No value\n    let absent_number: Option\u003ci32\u003e = None;\n    \n    // Working with Option\n    let x: i8 = 5;\n    let y: Option\u003ci8\u003e = Some(5);\n    \n    // Must handle the None case\n    match y {\n        None =\u003e println!(\"No value\"),\n        Some(i) =\u003e println!(\"Value is {}\", i),\n    }\n    \n    // Or use if let\n    if let Some(value) = y {\n        println!(\"Value is {}\", value);\n    }\n}\n```\n\n### Type Aliases\n```rust\n// Simple type alias\ntype Board = [[char; 3]; 3];\n```\n\n### Deriving Traits\n```rust\n// Automatically implement traits\n#[derive(Clone, Debug)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n```\n\n### Implementing Display Trait\n```rust\nuse std::fmt;\n\nstruct Rectangle {\n    width: u32,\n    height: u32,\n}\n\nimpl fmt::Display for Rectangle {\n    fn fmt(\u0026self, f: \u0026mut fmt::Formatter) -\u003e fmt::Result {\n        write!(f, \"Rectangle of {}x{}\", self.width, self.height)\n    }\n}\n\nfn main() {\n    let rect = Rectangle { width: 30, height: 50 };\n    println!(\"{}\", rect);  // Uses Display trait\n}\n```\n\n### Iterator Methods\n```rust\nfn main() {\n    let numbers = vec![1, 2, 3, 4, 5];\n    \n    // all() checks if all elements satisfy predicate\n    let all_positive = numbers.iter().all(|\u0026x| x \u003e 0);\n    \n    // filter_map combines filter and map\n    let parsed: Vec\u003ci32\u003e = \"1 2 3\"\n        .split_whitespace()\n        .filter_map(|s| s.parse().ok())\n        .collect();\n        \n    // iter() for immutable references\n    for \u0026num in numbers.iter() {\n        println!(\"{}\", num);\n    }\n}\n```\n\n### Method Chaining\n```rust\nfn main() {\n    let numbers: Vec\u003ci32\u003e = (0..10)          // Range\n        .filter(|x| x % 2 == 0)   // Keep even numbers\n        .map(|x| x * x)           // Square them\n        .collect();               // Collect into Vec\n}\n```\n\n### Result with the ? Operator\n```rust\nuse std::fmt::Write;\n\nfn write_formatted(f: \u0026mut fmt::Formatter) -\u003e fmt::Result {\n    writeln!(f, \"Line 1\")?;  // Returns early if error\n    writeln!(f, \"Line 2\")?;  // Same as match or if let\n    Ok(())\n}\n```\n\n### Error Handling with eprintln!\n```rust\nfn process_input() {\n    if let Err(e) = std::io::stdin().read_line(\u0026mut String::new()) {\n        eprintln!(\"Error reading input: {}\", e);  // Prints to stderr\n    }\n}\n```\n\n---\n\n## Pattern Matching\n\u003e Summary: Pattern matching is a powerful feature for checking and destructuring values.\n\n### Match Expression\n```rust\nfn main() {\n    let number = 13;\n    \n    match number {\n        // Match a single value\n        1 =\u003e println!(\"One!\"),\n        \n        // Match multiple values\n        2 | 3 | 5 | 7 | 11 | 13 =\u003e println!(\"This is a prime\"),\n        \n        // Match a range\n        13..=19 =\u003e println!(\"A teen\"),\n        \n        // Default case\n        _ =\u003e println!(\"Ain't special\"),\n    }\n}\n```\n\n### Pattern Types\n```rust\nfn main() {\n    // Matching literals\n    let x = 1;\n    match x {\n        1 =\u003e println!(\"one\"),\n        2 =\u003e println!(\"two\"),\n        _ =\u003e println!(\"anything\"),\n    }\n    \n    // Matching named variables\n    let x = Some(5);\n    let y = 10;\n    match x {\n        Some(50) =\u003e println!(\"Got 50\"),\n        Some(y) =\u003e println!(\"Matched, y = {y}\"),\n        _ =\u003e println!(\"Default case, x = {:?}\", x),\n    }\n    \n    // Matching multiple patterns\n    let x = 1;\n    match x {\n        1 | 2 =\u003e println!(\"one or two\"),\n        3 =\u003e println!(\"three\"),\n        _ =\u003e println!(\"anything\"),\n    }\n}\n```\n\n### Destructuring\n```rust\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nenum Color {\n    Rgb(i32, i32, i32),\n    Hsv(i32, i32, i32),\n}\n\nfn main() {\n    // Destructuring structs\n    let p = Point { x: 0, y: 7 };\n    let Point { x: a, y: b } = p;\n    println!(\"a = {}, b = {}\", a, b);\n    \n    // Shorter struct destructuring\n    let Point { x, y } = p;\n    println!(\"x = {}, y = {}\", x, y);\n    \n    // Destructuring enums\n    let color = Color::Rgb(0, 160, 255);\n    match color {\n        Color::Rgb(r, g, b) =\u003e {\n            println!(\"Red: {}, green: {}, blue: {}\", r, g, b);\n        }\n        Color::Hsv(h, s, v) =\u003e {\n            println!(\"Hue: {}, saturation: {}, value: {}\", h, s, v);\n        }\n    }\n}\n```\n\n### Match Guards\n```rust\nfn main() {\n    let num = Some(4);\n    \n    match num {\n        Some(x) if x \u003c 5 =\u003e println!(\"less than five: {}\", x),\n        Some(x) =\u003e println!(\"{}\", x),\n        None =\u003e (),\n    }\n    \n    // Multiple conditions\n    let x = 4;\n    let y = false;\n    \n    match x {\n        4 | 5 | 6 if y =\u003e println!(\"yes\"),\n        _ =\u003e println!(\"no\"),\n    }\n}\n```\n\n### if let Expression\n```rust\nfn main() {\n    let config_max = Some(3u8);\n    \n    // Using match\n    match config_max {\n        Some(max) =\u003e println!(\"Maximum is configured to be {}\", max),\n        _ =\u003e (),\n    }\n    \n    // Same using if let (more concise)\n    if let Some(max) = config_max {\n        println!(\"Maximum is configured to be {}\", max);\n    }\n    \n    // if let with else\n    let mut count = 0;\n    if let Some(max) = config_max {\n        println!(\"Maximum is {}\", max);\n    } else {\n        count += 1;\n    }\n}\n```\n\n### while let Conditional Loop\n```rust\nfn main() {\n    let mut stack = Vec::new();\n    \n    stack.push(1);\n    stack.push(2);\n    stack.push(3);\n    \n    // Pop values until stack is empty\n    while let Some(top) = stack.pop() {\n        println!(\"{}\", top);\n    }\n}\n```\n\n---\n\n## Error Handling\n\u003e Summary: Rust has no exceptions. Instead, it uses the Result enum for recoverable errors and panic! for unrecoverable errors.\n\n### Unrecoverable Errors with panic!\n```rust\nfn main() {\n    // Basic panic\n    panic!(\"crash and burn\");\n\n    // Panic from array access\n    let v = vec![1, 2, 3];\n    v[99]; // This will panic!\n}\n```\n\n### Recoverable Errors with Result\n```rust\nuse std::fs::File;\nuse std::io::ErrorKind;\n\nfn main() {\n    // Basic Result handling\n    let file_result = File::open(\"hello.txt\");\n    \n    let file = match file_result {\n        Ok(file) =\u003e file,\n        Err(error) =\u003e match error.kind() {\n            ErrorKind::NotFound =\u003e match File::create(\"hello.txt\") {\n                Ok(fc) =\u003e fc,\n                Err(e) =\u003e panic!(\"Problem creating file: {:?}\", e),\n            },\n            other_error =\u003e panic!(\"Problem opening file: {:?}\", other_error),\n        },\n    };\n}\n```\n\n### Shortcuts for Error Handling\n\n#### The ? Operator\n```rust\nuse std::fs::File;\nuse std::io;\nuse std::io::Read;\n\nfn read_username_from_file() -\u003e Result\u003cString, io::Error\u003e {\n    let mut username = String::new();\n    File::open(\"hello.txt\")?.read_to_string(\u0026mut username)?;\n    Ok(username)\n}\n\n// Even shorter using fs::read_to_string\nuse std::fs;\n\nfn read_username_from_file_short() -\u003e Result\u003cString, io::Error\u003e {\n    fs::read_to_string(\"hello.txt\")\n}\n```\n\n#### unwrap and expect\n```rust\nfn main() {\n    // unwrap will panic! if the Result is an Err\n    let file = File::open(\"hello.txt\").unwrap();\n    \n    // expect lets us choose the panic! message\n    let file = File::open(\"hello.txt\")\n        .expect(\"Failed to open hello.txt\");\n}\n```\n\n### Custom Error Types\n```rust\nuse std::error::Error;\nuse std::fmt;\n\n#[derive(Debug)]\nstruct AppError {\n    kind: String,\n    message: String,\n}\n\n// Implement Display for AppError\nimpl fmt::Display for AppError {\n    fn fmt(\u0026self, f: \u0026mut fmt::Formatter) -\u003e fmt::Result {\n        write!(f, \"{}:{}\", self.kind, self.message)\n    }\n}\n\n// Implement Error for AppError\nimpl Error for AppError {}\n\nfn main() -\u003e Result\u003c(), AppError\u003e {\n    Err(AppError {\n        kind: String::from(\"IO\"),\n        message: String::from(\"Failed to read file\"),\n    })\n}\n```\n\n### Propagating Errors\n```rust\nuse std::error::Error;\nuse std::fs::File;\nuse std::io::{self, Read};\n\n// Using Box\u003cdyn Error\u003e for different error types\nfn read_and_process() -\u003e Result\u003cString, Box\u003cdyn Error\u003e\u003e {\n    let mut file = File::open(\"hello.txt\")?;\n    let mut content = String::new();\n    file.read_to_string(\u0026mut content)?;\n    \n    Ok(content)\n}\n\nfn main() {\n    match read_and_process() {\n        Ok(content) =\u003e println!(\"File content: {}\", content),\n        Err(e) =\u003e println!(\"Error: {}\", e),\n    }\n}\n```\n\n### Error Handling Guidelines\n```rust\nfn main() {\n    // Use Result when:\n    // 1. The error is expected and recoverable\n    // 2. You want to give the caller choice in handling the error\n    let result = std::fs::read_to_string(\"config.txt\");\n    \n    // Use panic! when:\n    // 1. The error is unexpected or unrecoverable\n    // 2. You're writing examples or tests\n    // 3. You're prototyping\n    assert!(result.is_ok(), \"Config file must exist!\");\n    \n    // Use expect when:\n    // 1. You're sure the operation will succeed\n    // 2. You want a better error message than unwrap()\n    let config = result.expect(\"Config file must be readable\");\n}\n```\n\n---\n\n## Generic Types \u0026 Traits\n\u003e Summary: Generics provide abstraction over types, while traits define shared behavior.\n\n### Generic Types\n\u003e Summary: Generics allow you to write code that works with multiple types.\n\n#### Generic Functions\n```rust\nfn largest\u003cT: PartialOrd\u003e(list: \u0026[T]) -\u003e \u0026T {\n    let mut largest = \u0026list[0];\n    \n    for item in list {\n        if item \u003e largest {\n            largest = item;\n        }\n    }\n    \n    largest\n}\n\nfn main() {\n    let numbers = vec![34, 50, 25, 100, 65];\n    println!(\"Largest number: {}\", largest(\u0026numbers));\n    \n    let chars = vec!['y', 'm', 'a', 'q'];\n    println!(\"Largest char: {}\", largest(\u0026chars));\n}\n```\n\n#### Generic Structs\n```rust\nstruct Point\u003cT\u003e {\n    x: T,\n    y: T,\n}\n\nstruct MixedPoint\u003cT, U\u003e {\n    x: T,\n    y: U,\n}\n\nfn main() {\n    let integer = Point { x: 5, y: 10 };\n    let float = Point { x: 1.0, y: 4.0 };\n    let mixed = MixedPoint { x: 5, y: 4.0 };\n}\n```\n\n### Traits\n\u003e Summary: Traits define shared behavior between types.\n\n#### Defining and Implementing Traits\n```rust\ntrait Summary {\n    // Default implementation\n    fn summarize_author(\u0026self) -\u003e String;\n    \n    fn summarize(\u0026self) -\u003e String {\n        format!(\"(Read more from {}...)\", self.summarize_author())\n    }\n}\n\nstruct NewsArticle {\n    headline: String,\n    location: String,\n    author: String,\n    content: String,\n}\n\nimpl Summary for NewsArticle {\n    fn summarize_author(\u0026self) -\u003e String {\n        format!(\"@{}\", self.author)\n    }\n    \n    fn summarize(\u0026self) -\u003e String {\n        format!(\"{}, by {} ({})\", self.headline, self.author, self.location)\n    }\n}\n\nstruct Tweet {\n    username: String,\n    content: String,\n    reply: bool,\n    retweet: bool,\n}\n\nimpl Summary for Tweet {\n    fn summarize_author(\u0026self) -\u003e String {\n        format!(\"@{}\", self.username)\n    }\n}\n```\n\n#### Trait Bounds\n```rust\n// Single trait bound\npub fn notify\u003cT: Summary\u003e(item: \u0026T) {\n    println!(\"Breaking news! {}\", item.summarize());\n}\n\n// Multiple trait bounds\npub fn notify\u003cT: Summary + Display\u003e(item: \u0026T) {\n    println!(\"Breaking news! {}\", item.summarize());\n}\n\n// Where clauses for cleaner syntax\nfn some_function\u003cT, U\u003e(t: \u0026T, u: \u0026U) -\u003e i32\n    where T: Display + Clone,\n          U: Clone + Debug\n{\n    // Function body\n    42\n}\n```\n\n#### Trait Objects\n```rust\npub trait Draw {\n    fn draw(\u0026self);\n}\n\npub struct Screen {\n    pub components: Vec\u003cBox\u003cdyn Draw\u003e\u003e,\n}\n\nimpl Screen {\n    pub fn run(\u0026self) {\n        for component in self.components.iter() {\n            component.draw();\n        }\n    }\n}\n\n// Implementing for different types\nstruct Button {\n    width: u32,\n    height: u32,\n    label: String,\n}\n\nimpl Draw for Button {\n    fn draw(\u0026self) {\n        // Draw button\n    }\n}\n\nstruct SelectBox {\n    width: u32,\n    height: u32,\n    options: Vec\u003cString\u003e,\n}\n\nimpl Draw for SelectBox {\n    fn draw(\u0026self) {\n        // Draw select box\n    }\n}\n```\n\n### Generic Type Constraints\n```rust\nuse std::fmt::Display;\n\nstruct Pair\u003cT\u003e {\n    x: T,\n    y: T,\n}\n\nimpl\u003cT\u003e Pair\u003cT\u003e {\n    fn new(x: T, y: T) -\u003e Self {\n        Self { x, y }\n    }\n}\n\n// Implementation only for types that implement Display + PartialOrd\nimpl\u003cT: Display + PartialOrd\u003e Pair\u003cT\u003e {\n    fn cmp_display(\u0026self) {\n        if self.x \u003e= self.y {\n            println!(\"The largest member is x = {}\", self.x);\n        } else {\n            println!(\"The largest member is y = {}\", self.y);\n        }\n    }\n}\n```\n\n---\n\n## Modules \u0026 Project Organization\n\u003e Summary: Modules help you organize code and control privacy. A package can contain multiple binary crates and optionally one library crate.\n\n### Module System\n```rust\n// In src/lib.rs\nmod front_of_house {\n    pub mod hosting {\n        pub fn add_to_waitlist() {}\n        fn seat_at_table() {}\n    }\n    \n    mod serving {\n        fn take_order() {}\n        fn serve_order() {}\n        fn take_payment() {}\n    }\n}\n\npub fn eat_at_restaurant() {\n    // Absolute path\n    crate::front_of_house::hosting::add_to_waitlist();\n    \n    // Relative path\n    front_of_house::hosting::add_to_waitlist();\n}\n```\n\n### Project Structure\n```\nmy_project/\n├── Cargo.toml\n├── src/\n│   ├── main.rs       // Binary crate root\n│   ├── lib.rs        // Library crate root\n│   └── bin/          // Additional binaries\n│       └── another_binary.rs\n```\n\n### Modules in Separate Files\n```rust\n// src/lib.rs\nmod front_of_house;  // Declares the module\npub use crate::front_of_house::hosting;  // Re-export\n\n// src/front_of_house.rs\npub mod hosting;  // Declares the submodule\n\n// src/front_of_house/hosting.rs\npub fn add_to_waitlist() {}\n```\n\n### Visibility and Privacy\n```rust\nmod back_of_house {\n    // Public struct with some private fields\n    pub struct Breakfast {\n        pub toast: String,\n        seasonal_fruit: String,  // Private field\n    }\n    \n    impl Breakfast {\n        pub fn summer(toast: \u0026str) -\u003e Breakfast {\n            Breakfast {\n                toast: String::from(toast),\n                seasonal_fruit: String::from(\"peaches\"),\n            }\n        }\n    }\n    \n    // Public enum with all variants public\n    pub enum Appetizer {\n        Soup,\n        Salad,\n    }\n}\n\npub fn eat_at_restaurant() {\n    let mut meal = back_of_house::Breakfast::summer(\"Rye\");\n    meal.toast = String::from(\"Wheat\");\n    // meal.seasonal_fruit = String::from(\"blueberries\"); // Error!\n    \n    let order1 = back_of_house::Appetizer::Soup;\n    let order2 = back_of_house::Appetizer::Salad;\n}\n```\n\n### Using External Packages\n```toml\n# Cargo.toml\n[package]\nname = \"my_project\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\nrand = \"0.8.5\"\nserde = { version = \"1.0\", features = [\"derive\"] }\n```\n\n```rust\n// src/main.rs\nuse rand::Rng;\nuse serde::{Serialize, Deserialize};\n\n#[derive(Serialize, Deserialize)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nfn main() {\n    let mut rng = rand::thread_rng();\n    let random_number: i32 = rng.gen_range(1..=100);\n    println!(\"Random number: {}\", random_number);\n}\n```\n\n### Workspaces\n```toml\n# Cargo.toml in workspace root\n[workspace]\nmembers = [\n    \"adder\",\n    \"add_one\",\n]\n```\n\n```\nworkspace_root/\n├── Cargo.toml\n├── adder/\n│   ├── Cargo.toml\n│   └── src/\n│       └── main.rs\n└── add_one/\n    ├── Cargo.toml\n    └── src/\n        └── lib.rs\n```\n\n### Re-exporting Names\n```rust\n// In src/lib.rs\nmod front_of_house {\n    pub mod hosting {\n        pub fn add_to_waitlist() {}\n    }\n}\n\n// Re-export for easier access\npub use crate::front_of_house::hosting;\n\n// Users can now use:\n// restaurant::hosting::add_to_waitlist();\n// Instead of:\n// restaurant::front_of_house::hosting::add_to_waitlist();\n```\n\n---\n\n## Concurrency\n\u003e Summary: Rust's ownership and type systems guarantee thread safety and prevent data races at compile time.\n\n### Threads\n```rust\nuse std::thread;\nuse std::time::Duration;\n\nfn main() {\n    // Spawn a new thread\n    let handle = thread::spawn(|| {\n        for i in 1..10 {\n            println!(\"hi number {} from the spawned thread!\", i);\n            thread::sleep(Duration::from_millis(1));\n        }\n    });\n    \n    // Main thread work\n    for i in 1..5 {\n        println!(\"hi number {} from the main thread!\", i);\n        thread::sleep(Duration::from_millis(1));\n    }\n    \n    // Wait for spawned thread to finish\n    handle.join().unwrap();\n}\n```\n\n### Message Passing\n```rust\nuse std::sync::mpsc;\nuse std::thread;\n\nfn main() {\n    // Create a channel\n    let (tx, rx) = mpsc::channel();\n    \n    // Clone transmitter for multiple senders\n    let tx1 = tx.clone();\n    \n    // Spawn thread with one sender\n    thread::spawn(move || {\n        tx.send(\"hello from first thread\").unwrap();\n    });\n    \n    // Spawn thread with cloned sender\n    thread::spawn(move || {\n        tx1.send(\"hello from second thread\").unwrap();\n    });\n    \n    // Receive messages\n    for received in rx {\n        println!(\"Got: {}\", received);\n    }\n}\n```\n\n### Shared State\n```rust\nuse std::sync::{Arc, Mutex};\nuse std::thread;\n\nfn main() {\n    // Create a mutex wrapped in an Arc (Atomic Reference Counting)\n    let counter = Arc::new(Mutex::new(0));\n    let mut handles = vec![];\n    \n    for _ in 0..10 {\n        let counter = Arc::clone(\u0026counter);\n        let handle = thread::spawn(move || {\n            let mut num = counter.lock().unwrap();\n            *num += 1;\n        });\n        handles.push(handle);\n    }\n    \n    // Wait for all threads\n    for handle in handles {\n        handle.join().unwrap();\n    }\n    \n    println!(\"Result: {}\", *counter.lock().unwrap());\n}\n```\n\n### Thread Safety with Send and Sync\n```rust\n// Send: Type can be transferred between threads\n// Sync: Type can be shared between threads\n\nuse std::marker::{Send, Sync};\n\n// Custom type that is both Send and Sync\n#[derive(Debug)]\nstruct ThreadSafeCounter {\n    count: u32,\n}\n\n// Implementing Send and Sync is unsafe\nunsafe impl Send for ThreadSafeCounter {}\nunsafe impl Sync for ThreadSafeCounter {}\n\nfn main() {\n    let counter = ThreadSafeCounter { count: 0 };\n    \n    // This works because ThreadSafeCounter is Send\n    thread::spawn(move || {\n        println!(\"Counter in thread: {:?}\", counter);\n    }).join().unwrap();\n}\n```\n\n### Async/Await\n```rust\nuse tokio;\n\n#[tokio::main]\nasync fn main() {\n    // Spawn async tasks\n    let handle = tokio::spawn(async {\n        // Async work here\n        println!(\"Hello from async task!\");\n    });\n    \n    // Wait for task to complete\n    handle.await.unwrap();\n    \n    // Multiple concurrent tasks\n    let handles = vec![\n        tokio::spawn(async { /* task 1 */ }),\n        tokio::spawn(async { /* task 2 */ }),\n    ];\n    \n    // Wait for all tasks\n    for handle in handles {\n        handle.await.unwrap();\n    }\n}\n```\n\n### Parallel Iterator Operations\n```rust\nuse rayon::prelude::*;\n\nfn main() {\n    let numbers: Vec\u003ci32\u003e = (0..1000).collect();\n    \n    // Sequential sum\n    let sum: i32 = numbers.iter().sum();\n    \n    // Parallel sum\n    let parallel_sum: i32 = numbers.par_iter().sum();\n    \n    // Parallel filter and map\n    let result: Vec\u003ci32\u003e = numbers\n        .par_iter()\n        .filter(|\u0026\u0026x| x % 2 == 0)\n        .map(|\u0026x| x * x)\n        .collect();\n}\n```\n\n---\n\n## Testing\n\u003e Summary: Rust has built-in support for unit tests, integration tests, and documentation tests.\n\n### Unit Tests\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = 2 + 2;\n        assert_eq!(result, 4);\n    }\n    \n    #[test]\n    fn larger_can_hold_smaller() {\n        let larger = Rectangle {\n            width: 8,\n            height: 7,\n        };\n        let smaller = Rectangle {\n            width: 5,\n            height: 1,\n        };\n        \n        assert!(larger.can_hold(\u0026smaller));\n    }\n    \n    #[test]\n    #[should_panic(expected = \"Guess value must be less than or equal to 100\")]\n    fn greater_than_100() {\n        Guess::new(200);\n    }\n}\n```\n\n### Test Organization\n```rust\n// src/lib.rs\npub fn add_two(a: i32) -\u003e i32 {\n    a + 2\n}\n\n// Unit tests in the same file\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_adds_two() {\n        assert_eq!(4, add_two(2));\n    }\n}\n\n// Integration tests in tests directory\n// tests/integration_test.rs\nuse my_crate;\n\n#[test]\nfn it_adds_two() {\n    assert_eq!(4, my_crate::add_two(2));\n}\n```\n\n### Test Attributes\n```rust\n#[test]            // Marks function as a test\n#[ignore]          // Marks test to be ignored unless specifically requested\n#[should_panic]    // Test should panic\n#[bench]           // Marks function as a benchmark (nightly only)\n\n#[test]\n#[ignore = \"too slow\"]\nfn expensive_test() {\n    // ...\n}\n```\n\n### Assertions\n```rust\nfn main() {\n    // Basic assertions\n    assert!(true);\n    assert_eq!(2 + 2, 4);\n    assert_ne!(2 + 2, 5);\n    \n    // Custom messages\n    assert!(\n        true,\n        \"This is a custom error message: {} {}\",\n        \"formatted\", \"arguments\"\n    );\n    \n    // Floating point comparisons\n    assert!((0.1 + 0.2 - 0.3).abs() \u003c f64::EPSILON);\n}\n```\n\n### Running Tests\n```bash\n# Run all tests\ncargo test\n\n# Run specific test\ncargo test it_works\n\n# Run tests whose names contain a string\ncargo test add\n\n# Run ignored tests\ncargo test -- --ignored\n\n# Run tests with output\ncargo test -- --nocapture\n\n# Run tests in parallel or sequentially\ncargo test -- --test-threads=1\n```\n\n### Documentation Tests\n```rust\n/// Adds one to the number given.\n///\n/// # Examples\n///\n/// ```\n/// let arg = 5;\n/// let answer = my_crate::add_one(arg);\n///\n/// assert_eq!(6, answer);\n/// ```\npub fn add_one(x: i32) -\u003e i32 {\n    x + 1\n}\n```\n\n### Test Driven Development Example\n```rust\n// First, write the test\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_stack_push() {\n        let mut stack = Stack::new();\n        stack.push(1);\n        assert_eq!(stack.pop(), Some(1));\n    }\n\n    #[test]\n    fn test_stack_pop_empty() {\n        let mut stack = Stack::new();\n        assert_eq!(stack.pop(), None);\n    }\n}\n\n// Then implement the functionality\npub struct Stack\u003cT\u003e {\n    items: Vec\u003cT\u003e,\n}\n\nimpl\u003cT\u003e Stack\u003cT\u003e {\n    pub fn new() -\u003e Self {\n        Stack { items: Vec::new() }\n    }\n\n    pub fn push(\u0026mut self, item: T) {\n        self.items.push(item);\n    }\n\n    pub fn pop(\u0026mut self) -\u003e Option\u003cT\u003e {\n        self.items.pop()\n    }\n}\n```\n\n### Integration Tests\n```rust\n// tests/integration_test.rs\nuse my_crate;\n\nmod common;  // Load common test utilities\n\n#[test]\nfn integration_test() {\n    common::setup();\n    assert_eq!(my_crate::add_two(2), 4);\n}\n\n// tests/common/mod.rs\npub fn setup() {\n    // Setup code used by multiple test files\n}\n```\n\n---\n\n## Smart Pointers\n\u003e Summary: Smart pointers are data structures that act like pointers but have additional metadata and capabilities.\n\n### Box\u003cT\u003e\n\u003e Summary: Box\u003cT\u003e provides heap allocation and ownership of data.\n\n```rust\nfn main() {\n    // Allocating on the heap\n    let b = Box::new(5);\n    println!(\"b = {}\", b);\n    \n    // Recursive types with Box\n    #[derive(Debug)]\n    enum List {\n        Cons(i32, Box\u003cList\u003e),\n        Nil,\n    }\n    \n    let list = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));\n    println!(\"{:?}\", list);\n}\n```\n\n### Rc\u003cT\u003e\n\u003e Summary: Reference Counting allows multiple ownership in single-threaded scenarios.\n\n```rust\nuse std::rc::Rc;\n\nenum List {\n    Cons(i32, Rc\u003cList\u003e),\n    Nil,\n}\n\nfn main() {\n    let a = Rc::new(List::Cons(5, Rc::new(List::Nil)));\n    println!(\"Reference count after creating a = {}\", Rc::strong_count(\u0026a));\n    \n    let b = List::Cons(3, Rc::clone(\u0026a));\n    println!(\"Reference count after creating b = {}\", Rc::strong_count(\u0026a));\n    \n    {\n        let c = List::Cons(4, Rc::clone(\u0026a));\n        println!(\"Reference count after creating c = {}\", Rc::strong_count(\u0026a));\n    }\n    \n    println!(\"Reference count after c goes out of scope = {}\", Rc::strong_count(\u0026a));\n}\n```\n\n### RefCell\u003cT\u003e\n\u003e Summary: Interior mutability pattern allows mutable borrowing in immutable contexts.\n\n```rust\nuse std::cell::RefCell;\n\nfn main() {\n    let data = RefCell::new(5);\n    \n    // Multiple mutable borrows (at different times)\n    {\n        let mut m1 = data.borrow_mut();\n        *m1 += 1;\n    }   // m1 is dropped here\n    \n    let mut m2 = data.borrow_mut();\n    *m2 += 1;\n    \n    println!(\"Data = {:?}\", data.borrow());\n}\n```\n\n### Combining Rc\u003cT\u003e and RefCell\u003cT\u003e\n```rust\nuse std::rc::Rc;\nuse std::cell::RefCell;\n\n#[derive(Debug)]\nstruct Node {\n    value: i32,\n    children: RefCell\u003cVec\u003cRc\u003cNode\u003e\u003e\u003e,\n}\n\nfn main() {\n    let leaf = Rc::new(Node {\n        value: 3,\n        children: RefCell::new(vec![]),\n    });\n    \n    let branch = Rc::new(Node {\n        value: 5,\n        children: RefCell::new(vec![Rc::clone(\u0026leaf)]),\n    });\n    \n    println!(\"leaf = {:?}\", leaf);\n    println!(\"branch = {:?}\", branch);\n}\n```\n\n### Weak\u003cT\u003e\n\u003e Summary: Weak references that don't prevent deallocation, useful for preventing reference cycles.\n\n```rust\nuse std::rc::{Rc, Weak};\nuse std::cell::RefCell;\n\n#[derive(Debug)]\nstruct Node {\n    value: i32,\n    parent: RefCell\u003cWeak\u003cNode\u003e\u003e,\n    children: RefCell\u003cVec\u003cRc\u003cNode\u003e\u003e\u003e,\n}\n\nfn main() {\n    let leaf = Rc::new(Node {\n        value: 3,\n        parent: RefCell::new(Weak::new()),\n        children: RefCell::new(vec![]),\n    });\n    \n    println!(\"leaf parent = {:?}\", leaf.parent.borrow().upgrade());\n    \n    let branch = Rc::new(Node {\n        value: 5,\n        parent: RefCell::new(Weak::new()),\n        children: RefCell::new(vec![Rc::clone(\u0026leaf)]),\n    });\n    \n    *leaf.parent.borrow_mut() = Rc::downgrade(\u0026branch);\n    \n    println!(\"leaf parent = {:?}\", leaf.parent.borrow().upgrade());\n}\n```\n\n### Custom Smart Pointer\n```rust\nuse std::ops::Deref;\n\nstruct MyBox\u003cT\u003e(T);\n\nimpl\u003cT\u003e MyBox\u003cT\u003e {\n    fn new(x: T) -\u003e MyBox\u003cT\u003e {\n        MyBox(x)\n    }\n}\n\nimpl\u003cT\u003e Deref for MyBox\u003cT\u003e {\n    type Target = T;\n    \n    fn deref(\u0026self) -\u003e \u0026Self::Target {\n        \u0026self.0\n    }\n}\n\nfn main() {\n    let x = 5;\n    let y = MyBox::new(x);\n    \n    assert_eq!(5, x);\n    assert_eq!(5, *y);  // Deref coercion\n}\n```\n\n---\n\n## Macros\n\u003e Summary: Macros are a way of writing code that writes other code, known as metaprogramming.\n\n### Declarative Macros\n```rust\n// Simple macro\n#[macro_export]\nmacro_rules! vec2 {\n    ( $( $x:expr ),* ) =\u003e {\n        {\n            let mut temp_vec = Vec::new();\n            $(\n                temp_vec.push($x);\n            )*\n            temp_vec\n        }\n    };\n}\n\nfn main() {\n    let v = vec2![1, 2, 3];  // Creates: let v = {let mut temp_vec = Vec::new(); temp_vec.push(1); temp_vec.push(2); temp_vec.push(3); temp_vec};\n}\n```\n\n### Macro Patterns\n```rust\nmacro_rules! my_macro {\n    // Match zero arguments\n    () =\u003e {\n        println!(\"No arguments\");\n    };\n    \n    // Match one argument\n    ($x:expr) =\u003e {\n        println!(\"One argument: {}\", $x);\n    };\n    \n    // Match multiple arguments\n    ($( $x:expr ),*) =\u003e {\n        {\n            $(\n                println!(\"Multiple arguments: {}\", $x);\n            )*\n        }\n    };\n    \n    // Match specific patterns\n    (key: $key:expr, value: $val:expr) =\u003e {\n        println!(\"Key: {}, Value: {}\", $key, $val);\n    };\n}\n```\n\n### Procedural Macros\n```rust\nuse proc_macro;\n\n// Derive macro\n#[proc_macro_derive(MyTrait)]\npub fn my_trait_derive(input: proc_macro::TokenStream) -\u003e proc_macro::TokenStream {\n    // Implementation\n}\n\n// Attribute macro\n#[proc_macro_attribute]\npub fn route(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -\u003e proc_macro::TokenStream {\n    // Implementation\n}\n\n// Function-like macro\n#[proc_macro]\npub fn sql(input: proc_macro::TokenStream) -\u003e proc_macro::TokenStream {\n    // Implementation\n}\n```\n\n### Common Macro Use Cases\n```rust\n// Debug printing\nprintln!(\"Debug: {:?}\", value);\n\n// Format strings\nformat!(\"Hello, {}!\", name);\n\n// Vector creation\nlet v = vec![1, 2, 3];\n\n// Error handling\npanic!(\"Error message\");\n\n// Testing\nassert!(condition);\nassert_eq!(left, right);\n\n// Custom error messages\nassert!(\n    condition,\n    \"Error occurred with value: {}\",\n    value\n);\n```\n\n### Building Complex Macros\n```rust\n#[macro_export]\nmacro_rules! hash_map {\n    // Empty map\n    () =\u003e {\n        {\n            use std::collections::HashMap;\n            HashMap::new()\n        }\n    };\n    \n    // Map with key-value pairs\n    ( $($key:expr =\u003e $value:expr),* $(,)? ) =\u003e {\n        {\n            use std::collections::HashMap;\n            let mut map = HashMap::new();\n            $(\n                map.insert($key, $value);\n            )*\n            map\n        }\n    };\n}\n\nfn main() {\n    let map = hash_map! {\n        \"one\" =\u003e 1,\n        \"two\" =\u003e 2,\n        \"three\" =\u003e 3,\n    };\n}\n```\n\n### Debugging Macros\n```rust\n// Use trace_macros! to see macro expansion\n#![feature(trace_macros)]\ntrace_macros!(true);\nmy_macro!(some args);\ntrace_macros!(false);\n\n// Use log_syntax! to see what tokens are passed\n#![feature(log_syntax)]\nlog_syntax!(true);\nmy_macro!(some args);\nlog_syntax!(false);\n\n// Expand macro without running\ncargo expand\n```\n\n### Best Practices\n```rust\n// Document macros\n/// Creates a vector containing the arguments.\n///\n/// # Examples\n///\n/// ```\n/// let v = vec![1, 2, 3];\n/// assert_eq!(v[0], 1);\n/// ```\n#[macro_export]\nmacro_rules! vec {\n    ( $( $x:expr ),* ) =\u003e {\n        {\n            let mut temp_vec = Vec::new();\n            $(\n                temp_vec.push($x);\n            )*\n            temp_vec\n        }\n    };\n}\n\n// Use proper hygiene\nmacro_rules! hygienic {\n    ($i:ident) =\u003e {\n        let $i = 42;  // Won't conflict with external variables\n    };\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbluntbrain%2Frust-notes-and-projects","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbluntbrain%2Frust-notes-and-projects","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbluntbrain%2Frust-notes-and-projects/lists"}