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
123: Common &str Methods
By now, you're comfortable with the difference between String and &str. But in the real world, you spend a huge amount of your time just poking and prodding at string slices to see if they contain what you expect. I've found that instead of reaching for a heavy regex crate for every little thing, most of the time, the built-in &str methods are all you actually need.
Let's build a simple username validator. I want to make sure a username isn't empty, doesn't start with a forbidden character, and doesn't contain any illegal whitespace. This is a perfect playground for string slices.
Cleaning up the raw input
Usually, when you get a string from a user or an API, it's messy. There are trailing spaces or accidental newlines. I always start by trimming the input. The .trim() method is great because it doesn't allocate a new string; it just returns a sub-slice of the original that excludes the whitespace.
let raw_input = " rust_ace_99 \n";
let username = raw_input.trim();
if username.is_empty() {
println!("Username cannot be blank!");
}
Notice how I used .is_empty(). I could have checked if username.len() == 0, but is_empty() is more idiomatic and arguably more readable. It tells the next developer exactly what you're checking for.
Setting some boundary rules
In my imaginary system, usernames can't start with an underscore—it's just a stylistic choice I'm making for this example. This is where starts_with and ends_with come in handy. They return a simple boolean, making them perfect for if statements.
if username.starts_with('_') {
println!("Usernames cannot start with an underscore.");
}
if username.ends_with('!') {
println!("No exclamation points at the end, please.");
}
Hunting for forbidden characters
Next, I want to make sure there aren't any spaces inside the username. Even though we trimmed the ends, we could still have "rust ace". The .contains() method is my go-to here.
if username.contains(' ') {
println!("Usernames cannot contain spaces.");
}
I prefer passing a char (single quotes) to contains rather than a string slice when I'm looking for a single character. It's a tiny bit more efficient and makes it clear I'm looking for one specific glyph.
Oops, I forgot how split works
Now, I want to check if the username has too many segments. I've decided that usernames are separated by dots (like dev.rust.user), and I only want a maximum of three segments. Here is where I usually trip up when I'm rushing.
// My first attempt (This won't work!)
let segments = username.split('.');
if segments.len() > 3 {
println!("Too many segments!");
}
I just tried to call .len() on the result of split(). Rust compiler immediately yelled at me. Why? Because split() doesn't return a Vec or a slice; it returns a Split iterator. Iterators in Rust are lazy—they don't know how many elements they have until they actually traverse them.
To fix this, I have two choices: I can collect the iterator into a Vec, or I can use the count() method. Since I just need the number, count() is cleaner.
// The corrected version
let segment_count = username.split('.').count();
if segment_count > 3 {
println!("Too many segments! Max 3 allowed.");
}
Just a heads up: count() consumes the iterator. If you needed to actually use those segments later, you'd be better off using .collect::>().
📋 Practical Task
Build a URL Slug Sanitizer
Your task is to write a function that takes a raw page title (a &str) and converts it into a URL-friendly "slug".
Implement a function fn create_slug(title: &str) -> String that does the following:
- Trims leading and trailing whitespace.
- Converts the entire string to lowercase.
- Replaces all spaces with hyphens (
-). - Checks if the resulting slug starts with a hyphen; if it does, remove it (you can use
.strip_prefix("-")or a similar slice method).
Test your function with: " My First Rust Blog Post ".
Expected Output: "my-first-rust-blog-post"
There are no comments for now.