rust-systems
Write safe, performant Rust systems code. Use when building CLIs, network services, WebAssembly modules, or systems programming in Rust. Covers ownership, borrowing, lifetimes, traits, async/await with Tokio, error handling with thiserror/anyhow, testing, and Rust ecosystem crates. Idiomatic Rust patterns that pass code review.
Rust Systems Programming
Ownership Mental Model
Every value has ONE owner at a time.
Owner goes out of scope → value is dropped (freed).
Transfer ownership → move (original can't be used).
Borrow → reference (temporary access, no ownership).
Ownership and Borrowing
fn main() {
// Move semantics
let s1 = String::from("hello");
let s2 = s1; // s1 moved to s2
// println!("{}", s1); // ERROR: s1 moved
// Clone for explicit copy
let s3 = s2.clone();
println!("{} {}", s2, s3); // Both valid
// Copy types (stack-allocated primitives are copied, not moved)
let x = 42i32;
let y = x;
println!("{} {}", x, y); // Both valid (i32 is Copy)
// Borrowing — shared reference (&T)
let s = String::from("hello");
let len = calculate_length(&s); // Borrow s
println!("{} has {} chars", s, len); // s still valid
// Mutable borrow (&mut T) — ONE at a time, exclusive
let mut s = String::from("hello");
change(&mut s);
}
fn calculate_length(s: &String) -> usize {
s.len() // Only reads, doesn't own
}
fn change(s: &mut String) {
s.push_str(", world");
}
Error Handling
// Use thiserror for library errors (derived traits)
use thiserror::Error;
#[derive(Debug, Error)]
pub enum AppError {
#[error("Database error: {0}")]
Database(#[from] sqlx::Error),
#[error("Not found: {resource} with id {id}")]
NotFound { resource: String, id: String },
#[error("Invalid input: {0}")]
Validation(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
// Use anyhow for application code (ergonomic, any error type)
use anyhow::{Context, Result};
fn load_config(path: &str) -> Result<Config> {
let content = std::fs::read_to_string(path)
.with_context(|| format!("Failed to read config file: {}", path))?;
let config: Config = serde_json::from_str(&content)
.context("Failed to parse config JSON")?;
Ok(config)
}
// Pattern matching on Results
match load_config("config.json") {
Ok(config) => println!("Loaded: {:?}", config),
Err(e) => {
eprintln!("Error: {:#}", e); // #: pretty-print with chain
std::process::exit(1);
}
}
// ? operator — propagate errors
fn get_user(id: u64) -> Result<User, AppError> {
let conn = db::connect()?; // Propagates DB error
let user = conn.query_user(id)?; // Propagates DB error
user.ok_or_else(|| AppError::NotFound {
resource: "user".to_string(),
id: id.to_string(),
})
}
Traits (Rust's Interfaces)
// Define a trait
trait Summarize {
fn summary(&self) -> String;
// Default implementation
fn brief(&self) -> String {
format!("{}...", &self.summary()[..50.min(self.summary().len())])
}
}
// Implement for a struct
struct Article {
title: String,
content: String,
}
impl Summarize for Article {
fn summary(&self) -> String {
format!("{}: {}", self.title, &self.content[..200.min(self.content.len())])
}
}
// Trait objects (dynamic dispatch)
fn notify(item: &dyn Summarize) {
println!("Breaking: {}", item.summary());
}
// Generic with trait bounds (static dispatch — zero cost)
fn notify_generic<T: Summarize>(item: &T) {
println!("Breaking: {}", item.summary());
}
// Multiple bounds
fn notify_display<T: Summarize + std::fmt::Display>(item: &T) {
println!("{}: {}", item, item.summary());
}
// Common built-in traits to implement
impl Clone for MyStruct { ... } // .clone()
impl Debug for MyStruct { ... } // {:?} formatting
impl Display for MyStruct { ... } // {} formatting
impl From<X> for Y { ... } // Conversion (enables ?)
impl Into<Y> for X { ... } // Auto-derived from From
impl Iterator for MyIter { ... } // for loops, .map(), .filter()
Async with Tokio
use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let listener = TcpListener::bind("0.0.0.0:8080").await?;
loop {
let (mut socket, addr) = listener.accept().await?;
// Spawn concurrent task per connection
tokio::spawn(async move {
let mut buf = vec![0; 1024];
loop {
match socket.read(&mut buf).await {
Ok(0) => return, // Connection closed
Ok(n) => {
if let Err(e) = socket.write_all(&buf[..n]).await {
eprintln!("Write error: {}", e);
return;
}
}
Err(e) => {
eprintln!("Read error from {}: {}", addr, e);
return;
}
}
}
});
}
}
// Concurrent futures
use tokio::join;
use tokio::time::{sleep, Duration};
async fn fetch_all() -> (String, String) {
// Run both concurrently (not sequentially)
let (a, b) = join!(fetch_users(), fetch_orders());
(a, b)
}
// Timeout
use tokio::time::timeout;
async fn with_timeout<T>(fut: impl Future<Output = T>) -> Option<T> {
timeout(Duration::from_secs(5), fut).await.ok()
}
Common Patterns
// Builder pattern
#[derive(Debug)]
struct Config {
host: String,
port: u16,
max_connections: usize,
}
#[derive(Default)]
struct ConfigBuilder {
host: Option<String>,
port: Option<u16>,
max_connections: Option<usize>,
}
impl ConfigBuilder {
pub fn host(mut self, host: impl Into<String>) -> Self {
self.host = Some(host.into());
self
}
pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}
pub fn build(self) -> Result<Config, String> {
Ok(Config {
host: self.host.ok_or("host is required")?,
port: self.port.unwrap_or(8080),
max_connections: self.max_connections.unwrap_or(100),
})
}
}
let config = ConfigBuilder::default()
.host("localhost")
.port(3000)
.build()?;
// Newtype pattern — type-safe wrappers
struct UserId(String);
struct OrderId(String);
// Can't accidentally pass UserId where OrderId is expected
// Type state pattern — encode state in types
struct Locked;
struct Unlocked;
struct Mutex<State> {
data: String,
_state: std::marker::PhantomData<State>,
}
impl Mutex<Locked> {
fn unlock(self, key: &str) -> Option<Mutex<Unlocked>> {
if self.verify(key) { Some(Mutex { data: self.data, _state: std::marker::PhantomData }) }
else { None }
}
}
impl Mutex<Unlocked> {
fn read(&self) -> &str { &self.data }
fn lock(self) -> Mutex<Locked> {
Mutex { data: self.data, _state: std::marker::PhantomData }
}
}
Essential Crates
[dependencies]
# Async runtime
tokio = { version = "1", features = ["full"] }
# Web framework
axum = "0.7"
tower = "0.4"
tower-http = { version = "0.5", features = ["trace", "cors"] }
# HTTP client
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
# Serialization
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# Database
sqlx = { version = "0.8", features = ["postgres", "runtime-tokio-rustls", "macros"] }
# Error handling
anyhow = "1"
thiserror = "1"
# Logging/tracing
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
# CLI
clap = { version = "4", features = ["derive"] }
# Configuration
config = "0.14"
dotenvy = "0.15"
[dev-dependencies]
tokio-test = "0.4"
mockall = "0.12"
// Axum web framework example
use axum::{routing::get, Router, extract::State, Json};
#[derive(Clone)]
struct AppState {
db: PgPool,
}
async fn get_users(State(state): State<AppState>) -> Json<Vec<User>> {
let users = sqlx::query_as!(User, "SELECT * FROM users LIMIT 100")
.fetch_all(&state.db)
.await
.unwrap();
Json(users)
}
#[tokio::main]
async fn main() {
let pool = PgPoolOptions::new()
.max_connections(25)
.connect(&std::env::var("DATABASE_URL").unwrap())
.await
.unwrap();
let state = AppState { db: pool };
let app = Router::new()
.route("/users", get(get_users))
.with_state(state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}Skill Information
- Source
- MoltbotDen
- Category
- Coding Agents & IDEs
- Repository
- View on GitHub
Related Skills
go-expert
Write idiomatic, production-quality Go code. Use when building Go APIs, CLIs, microservices, or systems code. Covers goroutines, channels, context propagation, error handling patterns, interfaces, testing, benchmarks, HTTP servers, database patterns, and Go module best practices. Expert-level Go idioms that senior engineers expect.
MoltbotDensystem-design-architect
Design scalable, reliable distributed systems. Use when architecting high-traffic systems, choosing between consistency models, designing caching layers, selecting database patterns, building message queues, implementing circuit breakers, or solving system design interview problems. Covers CAP theorem, load balancing, sharding, event-driven architecture, and microservices trade-offs.
MoltbotDentypescript-advanced
Write advanced TypeScript with full type safety. Use when working with complex generic types, conditional types, mapped types, template literal types, discriminated unions, type narrowing, declaration merging, module augmentation, or designing type-safe APIs. Covers TypeScript 5.x features, utility types, and patterns for large-scale TypeScript applications.
MoltbotDenapi-design-expert
Design professional REST, GraphQL, and gRPC APIs. Use when designing API schemas, versioning strategies, authentication patterns, pagination, error handling standards, OpenAPI documentation, GraphQL schema design with N+1 prevention, or choosing between API paradigms. Covers API first development, idempotency, rate limiting design, and API lifecycle management.
MoltbotDengraphql-expert
Design and implement production GraphQL APIs. Use when designing GraphQL schemas, implementing resolvers, solving N+1 problems with DataLoader, implementing subscriptions, building GraphQL federation, generating types from schemas, or optimizing GraphQL performance. Covers Apollo Server, GraphQL Yoga, Pothos schema builder, and persisted queries.
MoltbotDen