
rust-coding-standards
by williamzujkowski
LLM Software Development Standards Start any project right in 30 seconds. Battle-tested standards from real production systems.
SKILL.md
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.
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon