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
145: Timed Mock Assessment on Core Rust
A few years ago, I was mentoring a developer named Sarah who was brilliant at theory. She could explain the difference between Box and Rc in her sleep and could whiteboard a trait hierarchy that would make a senior architect weep with joy. But during our first real-time pairing session to fix a race condition in a production middleware, she froze. It wasn't that she didn't know the language; it was that she had never practiced the "synthesis" phase—the act of pulling five different core concepts together while the clock is ticking and the pressure is on. She knew the notes, but she hadn't played the song.
That's why we're doing this mock assessment. By now, you've spent over a hundred lessons diving into the weeds of ownership, lifetimes, generics, and the standard library. You're comfortable with the syntax. But there is a distinct mental shift that happens when you stop following a guided tutorial and start solving a problem from scratch with a timer running. It forces you to stop overthinking the "perfect" architecture and start implementing the "correct" one.
Bridging the Gap Between Knowledge and Execution
The goal here isn't to trick you with obscure edge cases. I'm not interested in whether you remember the exact signature of a niche function in std::iter. Instead, I want to see if you can instinctively navigate the borrow checker when you're rushing. When we're relaxed, we're patient with the compiler. When we're under pressure, we tend to start throwing .clone() everywhere just to make the red lines go away. I want you to resist that urge. Use this session to see where your "reflexes" fail. If you find yourself fighting a lifetime error for twenty minutes, that's not a failure—it's a diagnostic. It tells us exactly where your mental model of memory management is still a bit fuzzy.
Managing Your Mental Stack During the Clock
In a timed environment, your biggest enemy isn't the code; it's your own anxiety about the time remaining. I've seen developers spend half their allotted time trying to implement a perfectly generic trait for a problem that only requires a simple concrete type. My advice? Build the "ugly" version that works first. In Rust, it's much easier to refactor a working, concrete implementation into a generic one than it is to debug a complex generic system that doesn't compile. Get the logic flowing, ensure the ownership transfers are correct, and only then start polishing the abstractions.
The Strategy for this Assessment
You'll be tasked with building a small but cohesive system. You'll need to handle error propagation using Result, manage shared state—likely requiring an Arc or a Mutex—and implement a trait to ensure extensibility. I suggest you spend the first five minutes just reading the requirements and sketching the data ownership on a piece of paper. Who owns the data? Who is borrowing it? If you can answer those two questions before you type a single character of struct definition, you've already won half the battle.
📋 Practical Task
Implement a Thread-Safe Multi-Producer Single-Consumer (MPSC) Event Logger
Your task is to build a simplified event logging system that can receive messages from multiple threads and write them to a central "log" (a Vec<String>) in a thread-safe manner. You must complete this without using high-level logging crates.
Requirements:
- Create a
Loggerstruct that holds the shared log state. It must be wrapped in a way that allows multiple threads to mutate the log (thinkArcandMutex). - Implement a trait called
Loggablewith a methodto_log_string(&self) -> String. - Implement
Loggablefor at least two different types (e.g., aSystemEventstruct and aUserEventstruct). - Create a function
process_eventsthat takes a vector ofBox<dyn Loggable + Send>and moves them into separate threads, where each thread logs its event to the sharedLogger. - The final output should be the
Loggerprinting the entire list of accumulated messages in the order they were successfully locked and written.
Constraints:
Try to complete this in 60 minutes. Focus on correct ownership transfers and ensuring that no deadlocks occur when multiple threads attempt to access the Mutex.
There are no comments for now.