rust
Write Rust code following best practices. Use when developing Rust applications. Covers ownership, error handling, and async patterns.
When & Why to Use This Skill
This Claude skill is a comprehensive assistant for Rust development, designed to help engineers build high-performance, memory-safe applications. It provides expert guidance on idiomatic Rust patterns, including strict ownership and borrowing rules, advanced error handling with the thiserror crate, and high-concurrency asynchronous programming using the Tokio runtime. By following industry best practices, it streamlines the development of robust, production-ready Rust codebases.
Use Cases
- Case 1: Building scalable and high-performance web backends using the Axum framework and SQLx for database integration.
- Case 2: Implementing complex system logic that requires precise memory management and lifetime annotations to ensure safety without a garbage collector.
- Case 3: Architecting asynchronous services to handle high-concurrency workloads using Tokio's async/await patterns and task spawning.
- Case 4: Designing robust error handling architectures using custom enums and the Result type to create maintainable and predictable applications.
- Case 5: Scaffolding new Rust projects with standardized directory structures and configuring essential tooling like Cargo fmt, Clippy, and automated testing suites.
| name | rust |
|---|---|
| description | Write Rust code following best practices. Use when developing Rust applications. Covers ownership, error handling, and async patterns. |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep |
Rust Development
Project Structure
my-project/
├── Cargo.toml
├── src/
│ ├── main.rs
│ ├── lib.rs
│ └── handlers/
│ └── mod.rs
└── tests/
└── integration.rs
Error Handling
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AppError {
#[error("User not found: {0}")]
NotFound(String),
#[error("Database error: {0}")]
Database(#[from] sqlx::Error),
#[error("Validation error: {0}")]
Validation(String),
}
// Using Result
async fn get_user(id: &str) -> Result<User, AppError> {
let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
.fetch_optional(&pool)
.await?
.ok_or_else(|| AppError::NotFound(id.to_string()))?;
Ok(user)
}
// Using ? operator
fn process() -> Result<(), AppError> {
let user = get_user("123")?;
validate(&user)?;
save(&user)?;
Ok(())
}
Ownership & Borrowing
// Ownership transfer
fn take_ownership(s: String) {
println!("{}", s);
} // s is dropped here
// Borrowing (immutable)
fn borrow(s: &String) {
println!("{}", s);
}
// Mutable borrowing
fn mutate(s: &mut String) {
s.push_str(" world");
}
// Lifetimes
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
Async with Tokio
use tokio;
#[tokio::main]
async fn main() {
let result = fetch_data().await;
}
async fn fetch_all(urls: Vec<String>) -> Vec<Response> {
let futures: Vec<_> = urls
.into_iter()
.map(|url| tokio::spawn(async move { fetch(&url).await }))
.collect();
let results = futures::future::join_all(futures).await;
results.into_iter().filter_map(|r| r.ok()).collect()
}
Axum Web Handler
use axum::{
extract::{Path, State},
http::StatusCode,
Json,
};
async fn get_user(
State(pool): State<PgPool>,
Path(id): Path<String>,
) -> Result<Json<User>, (StatusCode, String)> {
let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
.fetch_optional(&pool)
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?
.ok_or((StatusCode::NOT_FOUND, "User not found".to_string()))?;
Ok(Json(user))
}
Testing
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validation() {
let result = validate("valid@email.com");
assert!(result.is_ok());
}
#[tokio::test]
async fn test_async_operation() {
let result = fetch_data().await;
assert!(result.is_ok());
}
}
Tooling
# Format
cargo fmt
# Lint
cargo clippy -- -D warnings
# Test
cargo test
# Build release
cargo build --release