Rust
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Ownership and Borrowing
-
Section 4: Structuring Data
-
Section 5: Collections and Error Handling
-
Section 6: Traits and Generics
-
Section 7: Concurrency
-
Section 8: Building for the Web
-
Section 9: Memory and Performance
-
Section 10: More Standard Library and Ecosystem
-
Section 11: Advanced Rust
-
Section 12: Rust for Systems and WebAssembly
-
Section 13: Tooling and Best Practices
-
Section 14: Data Structures and Algorithms in Rust
-
Section 15: Practical Projects
-
Section 16: Interview Practice
-
Section 17: std::collections In Depth
-
Section 18: std::io and std::fs In Depth
-
Section 19: std::net
-
Section 20: std::option and std::result In Depth
-
Section 21: std::iter In Depth
-
Section 22: std::sync In Depth
-
Section 23: std::string and std::str
-
Section 24: Cargo and Crates.io Ecosystem
-
Section 25: Popular Crates Ecosystem
-
Section 26: Rust Memory Model Deep Dive
-
Section 27: More Practice Exercises
-
Section 28: More Interview Practice
-
Section 29: Async Rust Deep Dive
-
Section 30: Tokio Ecosystem In Depth
-
Section 31: Error Handling Ecosystem Deep Dive
-
Section 32: Serde In Depth
-
Section 33: Web Development with Rust Deep Dive
-
Section 34: Database Access Ecosystem
-
Section 35: Rust for Embedded Systems Deep Dive
-
Section 36: Rust Macros In Depth
-
Section 37: Advanced Trait System
-
Section 38: Unsafe Rust In Depth
-
Section 39: Rust CLI Development
-
Section 40: Testing Ecosystem Deep Dive
-
Section 41: WebAssembly Deep Dive
-
Section 42: Rust Design Patterns
-
Section 43: More Data Structures in Rust
-
Section 44: Final Practice Projects
-
Section 45: Rust Performance Optimization
-
Section 46: Rust Ecosystem Tooling
-
Section 47: More Interview and Review
3: Cargo Projects and Dependencies
Think of starting a Rust project without Cargo like trying to build a custom dining table by forging your own nails and sawing your own planks from a fallen tree. Sure, you could do it, but why would you? In the real world, you'd go to a hardware store, buy pre-cut lumber, and use a set of standardized tools. You'd have a blueprint that lists exactly what materials you need so that if someone else wanted to build the same table, they could just follow your list.
In Rust, Cargo is that hardware store, the blueprint, and the assembly line all rolled into one. Your Cargo.toml file is the blueprint—it tells Rust exactly what "materials" (dependencies) your project needs to function. The src folder is your workbench where the actual building happens, and the cargo command is the power tool that puts it all together.
Setting up your workspace
Until now, you've probably been running rustc on single files. It's fine for snippets, but it falls apart the moment you have multiple files or need a library. To start a real project, I always use cargo new.
cargo new password_gen
cd password_gen
When you do this, Cargo doesn't just make a folder; it scaffolds a whole environment. You'll see a Cargo.toml file and a src/main.rs. I want you to pay close attention to that .toml file. It's written in Tom's Obvious, Minimal Language, and it's where you'll spend a lot of your time managing how your project is configured.
Borrowing code from the community
The real magic of Cargo is crates.io. A "crate" is just a Rust package. Instead of writing a random number generator from scratch—which is actually surprisingly hard to do correctly—you can just borrow a crate that someone else has already perfected.
Let's say we want to build a simple password generator. We need a way to pick random characters. I'd use the rand crate for this. To add it, you don't download a zip file or move folders around; you just add one line to your Cargo.toml under the [dependencies] section:
[dependencies]
rand = "0.8.5"
The moment you run cargo build or cargo run, Cargo looks at that line, reaches out to the internet, downloads the exact version of rand you asked for, and links it to your project. It also creates a Cargo.lock file. Don't touch that file manually—it's Cargo's way of remembering the exact version of every single sub-dependency used, ensuring that if you send your code to a teammate, it builds exactly the same way on their machine as it does on yours.
Putting it all together
Now that we've told Cargo we need rand, we can actually use it in our code. I'll keep this simple: we'll define a string of possible characters and use the crate to pick from them.
use rand::Rng; // Import the trait that gives us the random functionality
fn main() {
let charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*";
let mut rng = rand::thread_rng();
let mut password = String::new();
for _ in 0..12 {
let idx = rng.gen_range(0..charset.len());
password.push(charset.as_bytes()[idx] as char);
}
println!("Your new secure password is: {}", password);
}
To run this, you just type cargo run. This one command handles everything: it compiles your dependencies, compiles your code, and executes the resulting binary. It's a massive quality-of-life improvement over calling the compiler manually every time you make a typo.
📋 Practical Task
Build a Randomized Dice-Roll Simulator
Your goal is to create a new Cargo project that simulates rolling two six-sided dice. This will test your ability to initialize a project, manage a dependency, and implement the logic in the src folder.
Requirements:
- Create a new project named
dice_rollerusing Cargo. - Add the
randcrate to yourCargo.toml. - In
main.rs, generate two random integers between 1 and 6 (inclusive). - Print the result of each die and the total sum of the roll to the console.
- Run the program using
cargo runand verify that the output changes each time you execute it.
There are no comments for now.