rust

Pattern matching with match for exhaustive case handling

Rust's match expression is like a switch statement on steroids. It requires exhaustive handling of all cases, and the compiler enforces this. You can match on enums, tuples, references, ranges, and destructure nested data. Guards (if condition) add ex

cargo-expand to inspect macro expansions

cargo expand is a subcommand that shows the output of macro expansion. It's invaluable for debugging derive macros, understanding what declarative macros produce, or learning how async functions desugar. I run cargo expand --lib to see the entire crat

HashMap<K, V> for key-value lookups

HashMap&lt;K, V&gt; provides O(1) average-case lookups, inserts, and deletes. Keys must implement Hash + Eq. I use it for caches, indexing, and associative data. Common methods: .insert(k, v) adds/updates, .get(&amp;k) returns Option&lt;&amp;V&gt;, .r

Result and ? operator for clean error propagation

Rust's Result&lt;T, E&gt; forces you to handle errors explicitly, but the ? operator makes it ergonomic. When a function returns Result, using ? automatically returns early with the error if it's Err, or unwraps the value if it's Ok. This replaces ver

File I/O with std::fs for reading and writing files

Rust's std::fs module provides file I/O. fs::read_to_string() reads a file into a String, fs::write() writes bytes. For larger files or streaming, use File::open() and BufReader/BufWriter for buffered I/O. Always handle errors with Result and ?. For p

BufReader and BufWriter for efficient I/O buffering

BufReader and BufWriter wrap readers/writers with an in-memory buffer, reducing system calls. For example, reading a file line-by-line with BufReader::new(file).lines() is much faster than unbuffered reads. I use them for parsing large files, log proc

String vs &str for owned vs borrowed text

String is an owned, growable UTF-8 string on the heap. &amp;str is a borrowed string slice, often a view into a String or a string literal. I use String when I need to own, modify, or build strings. I use &amp;str for function parameters (accepting bo

color-eyre for beautiful error reports with backtraces

color-eyre enhances eyre (an anyhow alternative) with colored, human-readable error messages and backtraces. It automatically captures panic backtraces and suggestion hints. I use it in CLI tools where error UX matters. The setup is minimal: color_eyr

std::mem helpers for low-level memory manipulation

The std::mem module provides utilities for working with memory: size_of, align_of, swap, replace, take, drop, forget, and transmute. I use mem::swap to exchange values without cloning, mem::replace to take a value out of a mutable reference, and mem::

Rc and RefCell for shared ownership with interior mutability

When you need multiple ownership without threads, Rc&lt;T&gt; (reference counted) is the answer. It tracks the number of owners at runtime and frees the data when the count reaches zero. For mutability, combine it with RefCell&lt;T&gt;, which enforces

Drop trait for custom cleanup logic

The Drop trait runs when a value goes out of scope, similar to destructors in C++. I implement Drop for resource handles: closing file descriptors, releasing locks, or logging cleanup. The drop method takes &amp;mut self and can't fail (no Result). Ru

Cargo.lock for reproducible builds

Cargo generates Cargo.lock to pin exact dependency versions. For binaries, commit the lock file so everyone builds the same dependencies. For libraries, don't commit it (users should resolve their own). The lock file enables reproducible builds: cargo