rust-coding-standards
Master Rust's ownership system, type safety, and zero-cost abstractions for building safe, concurrent, and performant systems. Covers borrowing, lifetimes, traits, error handling, async/await, and testing patterns.
$ Installieren
git clone https://github.com/williamzujkowski/standards /tmp/standards && cp -r /tmp/standards/skills/coding-standards/rust ~/.claude/skills/standards// tip: Run this command in your terminal to install the skill
name: rust-coding-standards description: >- Master Rust's ownership system, type safety, and zero-cost abstractions for building safe, concurrent, and performant systems. Covers borrowing, lifetimes, traits, error handling, async/await, and testing patterns. category: coding-standards difficulty: intermediate estimated_time: 45 minutes version: 1.0.0 tags:
- rust
- ownership
- borrowing
- memory-safety
- performance dependencies: []
Rust Coding Standards
Purpose: Master Rust's ownership system, type safety, and zero-cost abstractions for building safe, concurrent, and performant systems.
Level 1: Quick Reference
Core Principles
- Ownership: Each value has exactly one owner
- Borrowing: References allow multiple readers XOR one writer
- Zero-cost abstractions: High-level code compiles to optimal machine code
- Explicit over implicit: No hidden allocations or control flow
Ownership & Borrowing Cheat Sheet
// Ownership transfer (move)
let s1 = String::from("hello");
let s2 = s1; // s1 is now invalid
// Immutable borrow (multiple allowed)
let s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2); // OK
// Mutable borrow (exclusive)
let mut s = String::from("hello");
let r1 = &mut s;
r1.push_str(" world");
// Copy types (stack-only)
let x = 5;
let y = x; // x is still valid (i32 implements Copy)
Result & Option
// Option: value may be absent
let name = find_user(42).map(|u| u.name).unwrap_or("Anonymous".into());
// Early return with ?
fn process() -> Result<(), Error> {
let config = parse_config("app.toml")?;
Ok(())
}
Essential Checklist
-
cargo clippy -- -D warnings -
cargo fmt -- --check -
cargo test -
cargo doc --no-deps -
cargo audit - Document all
unsafeblocks
Memory Safety Rules
- No data races: Compiler enforces at compile time
- No null pointers: Use
Option<T>instead - No dangling pointers: Borrow checker prevents
- No use-after-free: Ownership system prevents
- No buffer overflows: Bounds checking
Level 2: Implementation Guide
Ownership System
The Three Rules
- Each value has a variable that's its owner
- There can only be one owner at a time
- When the owner goes out of scope, the value is dropped
fn takes_ownership(s: String) {
println!("{}", s);
} // s dropped here
fn main() {
let s = String::from("hello");
takes_ownership(s); // s moved
// println!("{}", s); // Error: value borrowed after move
}
// Return ownership
fn gives_ownership() -> String {
String::from("hello")
}
Borrowing & References
// Multiple immutable borrows allowed
fn calculate_length(s: &String) -> usize {
s.len()
}
// Only one mutable borrow allowed
fn change(s: &mut String) {
s.push_str(", world");
}
// Non-lexical lifetimes
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2); // last use of r1 and r2
let r3 = &mut s; // OK: r1 and r2 no longer used
Lifetime Annotations
// Specify reference relationships
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
// Struct with lifetime
struct Excerpt<'a> {
part: &'a str,
}
// Lifetime elision: compiler infers in common patterns
fn first_word(s: &str) -> &str { /* elided lifetimes */ }
Traits & Generics
pub trait Summary {
fn summarize(&self) -> String;
// Default implementation
fn full_summary(&self) -> String {
format!("Read more: {}", self.summarize())
}
}
impl Summary for Article {
fn summarize(&self) -> String {
format!("{} by {}", self.headline, self.author)
}
}
// Trait bounds
pub fn notify<T: Summary + Display>(item: &T) {
println!("Breaking: {}", item.summarize());
}
// where clause for readability
pub fn process<T, U>(t: &T, u: &U) -> String
where
T: Display + Clone,
U: Clone + Debug,
{
format!("{:?}", u)
}
Common Derived Traits
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct User {
pub id: u32,
pub name: String,
}
Error Handling
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AppError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Database error: {0}")]
Database(#[from] sqlx::Error),
#[error("Not found: {0}")]
NotFound(String),
}
pub type Result<T> = std::result::Result<T, AppError>;
// With anyhow for context
use anyhow::Context;
fn read_config() -> anyhow::Result<Config> {
let content = fs::read_to_string("config.toml")
.context("Failed to read config file")?;
Ok(toml::from_str(&content)?)
}
Async/Await
use tokio;
#[tokio::main]
async fn main() -> Result<()> {
let result = fetch_data().await?;
process(result).await?;
Ok(())
}
// Concurrent execution
let futures = urls.iter().map(|url| fetch_url(url));
let results = futures::future::join_all(futures).await;
// Spawn tasks
let handle = tokio::spawn(async move {
expensive_computation().await
});
let result = handle.await?;
Channels
use tokio::sync::mpsc;
let (tx, mut rx) = mpsc::channel(32);
// Producer
tokio::spawn(async move {
tx.send(work).await.unwrap();
});
// Consumer
while let Some(result) = rx.recv().await {
process(result).await;
}
Shared State
use std::sync::Arc;
use tokio::sync::{Mutex, RwLock};
#[derive(Clone)]
struct AppState {
counter: Arc<Mutex<u64>>,
cache: Arc<RwLock<HashMap<String, String>>>,
}
async fn increment(state: AppState) {
let mut counter = state.counter.lock().await;
*counter += 1;
}
Testing
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic() {
assert_eq!(2 + 2, 4);
}
#[test]
#[should_panic(expected = "divide by zero")]
fn test_panic() {
divide(10, 0);
}
#[test]
fn test_result() -> Result<()> {
let result = parse_number("42")?;
assert_eq!(result, 42);
Ok(())
}
#[tokio::test]
async fn test_async() {
let result = fetch_data().await;
assert!(result.is_ok());
}
}
Performance Patterns
// Prefer slices over owned strings
fn count_words(text: &str) -> usize {
text.split_whitespace().count()
}
// Use Cow for conditional cloning
use std::borrow::Cow;
fn process_text(text: &str) -> Cow<str> {
if text.contains("bad") {
Cow::Owned(text.replace("bad", "good"))
} else {
Cow::Borrowed(text)
}
}
// Reuse buffers
let mut buffer = String::with_capacity(1024);
for item in items {
buffer.clear();
write!(&mut buffer, "{}", item)?;
send(&buffer)?;
}
Iterators
// Transformation pipeline (zero-cost)
let sum: i32 = vec![1, 2, 3, 4, 5]
.iter()
.filter(|&x| x % 2 == 0)
.map(|x| x * 2)
.sum();
// Collect into different types
let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
let set: HashSet<i32> = numbers.into_iter().collect();
Level 3: Deep Dive Resources
For comprehensive coverage of advanced topics, see REFERENCE.md:
Advanced Patterns
- Newtype Pattern: Type safety via wrapper types
- Typestate Pattern: Encode state machines in types
- Builder Pattern: Fluent API construction
Unsafe Code Guidelines
- Documenting safety invariants
- Minimizing unsafe scope
- Testing with Miri
Complete Examples
- Full async service implementation
- Property-based testing with proptest
- Mocking with mockall
- Integration test patterns
Configuration Files
config/rustfmt.toml- Formatter configurationconfig/clippy.toml- Linter rulestemplates/- Project templates
Performance Deep Dive
- Profiling with flamegraph
- Compiler optimization flags
- Memory profiling with valgrind
Learning Path
- Start: Rust Book
- Practice: Rustlings
- Patterns: Rust Design Patterns
- Async: Tokio Tutorial
Common Pitfalls
- Fighting the borrow checker - design with ownership in mind
- Over-using
.clone()- profile before optimizing - Ignoring Clippy warnings - they're usually right
- Not using
?operator - makes error handling cleaner - Premature unsafe - try safe abstractions first
- String vs &str confusion - prefer &str for parameters
Skill Complete: Comprehensive Rust coding standards covering ownership, traits, error handling, concurrency, testing, and performance. See REFERENCE.md for advanced patterns and complete examples.
Repository
