Skip to main content

Agent Skills Framework Extension

Rust Development Patterns Skill

When to Use This Skill

Use this skill when implementing rust development patterns patterns in your codebase.

How to Use This Skill

  1. Review the patterns and examples below
  2. Apply the relevant patterns to your implementation
  3. Follow the best practices outlined in this skill

Production Rust patterns for async programming, memory safety, and high-performance systems.

Core Capabilities

  1. Async Programming - Tokio runtime, async/await, concurrent patterns
  2. Memory Safety - Ownership, lifetimes, borrowing, zero-copy
  3. Error Handling - Result types, custom errors, error propagation
  4. Trait System - Generic programming, trait bounds, associated types
  5. Performance - Zero-cost abstractions, SIMD, cache efficiency

Async Web Service Pattern

// src/main.rs - Production async web service
use actix_web::{web, App, HttpServer, Result, middleware};
use sqlx::PgPool;
use std::sync::Arc;
use tokio::signal;

#[derive(Clone)]
pub struct AppState {
db: Arc<PgPool>,
config: Arc<AppConfig>,
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
tracing_subscriber::fmt::init();

let config = AppConfig::from_env().expect("Failed to load config");
let db = create_db_pool(&config.database_url).await
.expect("Failed to create database pool");

let app_state = AppState {
db: Arc::new(db),
config: Arc::new(config.clone()),
};

let server = HttpServer::new(move || {
App::new()
.app_data(web::Data::new(app_state.clone()))
.wrap(middleware::Logger::default())
.wrap(middleware::Compress::default())
.configure(configure_routes)
})
.bind(("0.0.0.0", config.port))?
.run();

tokio::select! {
res = server => res,
_ = signal::ctrl_c() => {
tracing::info!("Shutting down gracefully");
Ok(())
}
}
}

async fn create_db_pool(database_url: &str) -> Result<PgPool, sqlx::Error> {
sqlx::postgres::PgPoolOptions::new()
.max_connections(20)
.acquire_timeout(std::time::Duration::from_secs(30))
.connect(database_url)
.await
}

Advanced Error Handling

// src/errors.rs - Comprehensive error system
use thiserror::Error;
use actix_web::{ResponseError, HttpResponse, http::StatusCode};
use serde::Serialize;

#[derive(Error, Debug)]
pub enum AppError {
#[error("Database error: {0}")]
Database(#[from] sqlx::Error),

#[error("Validation error: {0}")]
Validation(String),

#[error("Not found: {entity_type} with id {id}")]
NotFound {
entity_type: String,
id: String,
},

#[error("Authentication error: {0}")]
Authentication(String),

#[error("Authorization error: user {user_id} cannot {action} {resource}")]
Authorization {
user_id: String,
action: String,
resource: String,
},

#[error("External service error: {0}")]
ExternalService(#[from] reqwest::Error),

#[error("Internal error")]
Internal(#[from] anyhow::Error),
}

#[derive(Serialize)]
struct ErrorResponse {
error: String,
message: String,
#[serde(skip_serializing_if = "Option::is_none")]
details: Option<serde_json::Value>,
}

impl ResponseError for AppError {
fn error_response(&self) -> HttpResponse {
let (status, error_type) = match self {
AppError::Validation(_) => (StatusCode::BAD_REQUEST, "validation_error"),
AppError::NotFound { .. } => (StatusCode::NOT_FOUND, "not_found"),
AppError::Authentication(_) => (StatusCode::UNAUTHORIZED, "authentication_error"),
AppError::Authorization { .. } => (StatusCode::FORBIDDEN, "authorization_error"),
AppError::Database(_) | AppError::Internal(_) =>
(StatusCode::INTERNAL_SERVER_ERROR, "internal_error"),
AppError::ExternalService(_) =>
(StatusCode::BAD_GATEWAY, "external_service_error"),
};

HttpResponse::build(status).json(ErrorResponse {
error: error_type.to_string(),
message: self.to_string(),
details: None,
})
}

fn status_code(&self) -> StatusCode {
match self {
AppError::Validation(_) => StatusCode::BAD_REQUEST,
AppError::NotFound { .. } => StatusCode::NOT_FOUND,
AppError::Authentication(_) => StatusCode::UNAUTHORIZED,
AppError::Authorization { .. } => StatusCode::FORBIDDEN,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
}

Repository Pattern with Traits

// src/repository.rs - Generic repository pattern
use async_trait::async_trait;
use sqlx::PgPool;
use uuid::Uuid;
use std::marker::PhantomData;

#[async_trait]
pub trait Repository<T>: Send + Sync {
async fn find_by_id(&self, id: Uuid) -> Result<Option<T>, AppError>;
async fn find_all(&self, limit: i64, offset: i64) -> Result<Vec<T>, AppError>;
async fn create(&self, entity: T) -> Result<T, AppError>;
async fn update(&self, id: Uuid, entity: T) -> Result<T, AppError>;
async fn delete(&self, id: Uuid) -> Result<bool, AppError>;
}

pub struct PostgresRepository<T> {
pool: Arc<PgPool>,
_phantom: PhantomData<T>,
}

impl<T> PostgresRepository<T> {
pub fn new(pool: Arc<PgPool>) -> Self {
Self {
pool,
_phantom: PhantomData,
}
}
}

#[async_trait]
impl Repository<User> for PostgresRepository<User> {
async fn find_by_id(&self, id: Uuid) -> Result<Option<User>, AppError> {
let user = sqlx::query_as!(
User,
"SELECT id, email, name, created_at FROM users WHERE id = $1",
id
)
.fetch_optional(&*self.pool)
.await?;

Ok(user)
}

async fn create(&self, user: User) -> Result<User, AppError> {
let created = sqlx::query_as!(
User,
r#"
INSERT INTO users (id, email, name, created_at)
VALUES ($1, $2, $3, NOW())
RETURNING id, email, name, created_at
"#,
user.id,
user.email,
user.name
)
.fetch_one(&*self.pool)
.await?;

Ok(created)
}

// ... other methods
}

Concurrent Stream Processing

// src/stream_processor.rs - High-performance async streams
use tokio_stream::{StreamExt, Stream};
use tokio::sync::mpsc;
use futures::stream::{FuturesUnordered, StreamExt as _};

pub struct StreamProcessor {
concurrency: usize,
}

impl StreamProcessor {
pub async fn process_batch<T, F, Fut, R>(
&self,
items: Vec<T>,
processor: F,
) -> Vec<Result<R, AppError>>
where
T: Send + 'static,
F: Fn(T) -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<R, AppError>> + Send,
R: Send + 'static,
{
let mut futures = FuturesUnordered::new();

for item in items {
let processor = processor.clone();
futures.push(tokio::spawn(async move {
processor(item).await
}));
}

let mut results = Vec::new();
while let Some(result) = futures.next().await {
match result {
Ok(res) => results.push(res),
Err(e) => results.push(Err(AppError::Internal(e.into()))),
}
}

results
}

pub async fn process_stream<S, T, F, Fut, R>(
&self,
stream: S,
processor: F,
) -> impl Stream<Item = Result<R, AppError>>
where
S: Stream<Item = T> + Send,
T: Send + 'static,
F: Fn(T) -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<R, AppError>> + Send,
R: Send + 'static,
{
stream
.map(move |item| {
let processor = processor.clone();
tokio::spawn(async move {
processor(item).await
})
})
.buffer_unordered(self.concurrency)
.map(|result| {
result.unwrap_or_else(|e| Err(AppError::Internal(e.into())))
})
}
}

Zero-Copy Optimization

// src/zero_copy.rs - Memory-efficient patterns
use bytes::{Bytes, BytesMut, BufMut};
use std::io::Write;

pub struct ZeroCopyBuffer {
inner: BytesMut,
}

impl ZeroCopyBuffer {
pub fn new() -> Self {
Self {
inner: BytesMut::with_capacity(4096),
}
}

pub fn write_slice(&mut self, data: &[u8]) {
self.inner.put_slice(data);
}

pub fn freeze(self) -> Bytes {
self.inner.freeze()
}

pub fn as_slice(&self) -> &[u8] {
&self.inner
}
}

// Avoid unnecessary allocations
pub fn process_large_file(path: &str) -> Result<Vec<String>, std::io::Error> {
use std::fs::File;
use std::io::{BufReader, BufRead};

let file = File::open(path)?;
let reader = BufReader::new(file);

// Process line-by-line without loading entire file
let mut results = Vec::new();
for line in reader.lines() {
let line = line?;
if line.starts_with("ERROR") {
results.push(line);
}
}

Ok(results)
}

Usage Examples

Async Web Service

Apply rust-development-patterns skill to create production Actix-web service with async handlers

Error Handling

Apply rust-development-patterns skill to implement comprehensive error system with custom types

Repository Pattern

Apply rust-development-patterns skill to design generic repository with async trait

Integration Points

  • rust-qa-patterns - Testing strategies
  • error-debugging-patterns - Error analysis
  • cicd-automation-patterns - Build automation

Success Output

When successful, this skill MUST output:

✅ SKILL COMPLETE: rust-development-patterns

Completed:
- [x] Async runtime configured (Tokio/async-std)
- [x] Error handling implemented with custom error types
- [x] Memory safety verified (no unsafe blocks or documented justification)
- [x] Repository pattern implemented with traits
- [x] Zero-copy optimizations applied where appropriate
- [x] All code passes clippy with no warnings
- [x] Cargo.toml dependencies locked with specific versions

Outputs:
- src/*.rs files with async handlers
- Custom error types in src/errors.rs
- Repository traits in src/repository.rs
- Cargo.toml with dependency specifications
- clippy.toml configuration

Completion Checklist

Before marking this skill as complete, verify:

  • cargo build --release completes without errors
  • cargo clippy -- -D warnings passes with zero warnings
  • cargo fmt --check passes (code is formatted)
  • All async functions use proper error propagation (? operator)
  • Custom error types implement Error + Display + From traits
  • No unwrap() or expect() in production code paths
  • Trait bounds are minimal and necessary
  • Lifetimes are explicit only where needed
  • Database connections use connection pooling
  • Graceful shutdown implemented for async runtimes

Failure Indicators

This skill has FAILED if:

  • ❌ Code contains unsafe blocks without safety documentation
  • ❌ clippy warnings present (especially clippy::unwrap_used)
  • ❌ Async runtime not configured properly (missing #[tokio::main])
  • ❌ Error types don't implement proper trait bounds
  • ❌ Memory leaks detected in long-running processes
  • ❌ Blocking I/O in async context without spawn_blocking
  • ❌ Database queries not using prepared statements/query macros
  • ❌ No graceful shutdown handling (SIGTERM/SIGINT)
  • ❌ Dependencies using wildcard versions (*) in Cargo.toml

When NOT to Use

Do NOT use this skill when:

  • Writing Python/JavaScript/Go services (use language-specific patterns)
  • Building simple CLI tools without async requirements (skip Tokio complexity)
  • Prototyping without production requirements (Python/Node.js faster for POCs)
  • Working with embedded systems requiring no_std (use embedded-rust-patterns)
  • Building WebAssembly modules only (use wasm-rust-patterns)
  • Creating FFI bindings to C libraries (use rust-ffi-patterns)
  • Learning Rust basics (start with simpler synchronous patterns first)

Anti-Patterns (Avoid)

Anti-PatternProblemSolution
Using .unwrap() in productionPanics crash entire processUse ? operator and proper error handling
Cloning unnecessarilyPerformance overheadUse references (&) and lifetimes
String concatenation in loopsO(n²) allocationsUse format!() or String::with_capacity()
Blocking I/O in async contextBlocks entire runtime threadUse spawn_blocking() for blocking calls
Not using type aliasesVerbose generic typesCreate type aliases for complex generics
Ignoring Clippy warningsMisses Rust best practicesFix all warnings before production
Overly complex lifetimesHard to maintainSimplify with owned types or refactor
Not using match exhaustivenessRuntime errors missedEnable all match arms, use _ carefully

Principles

This skill embodies:

  • #2 First Principles - Rust ownership, borrowing, and lifetime principles
  • #3 Keep It Simple - Zero-cost abstractions, no unnecessary complexity
  • #4 Separation of Concerns - Trait-based architecture, repository pattern
  • #5 Eliminate Ambiguity - Explicit error types, type safety
  • #9 Self-Documenting - Rust's type system documents intent
  • #10 Quality Over Speed - Memory safety and correctness first

Full Principles: CODITECT-STANDARD-AUTOMATION.md