# Rust

Ownership, borrowing, async, and idiomatic patterns for safe, performant Rust systems.

---

## Core Concepts

### Ownership & Borrowing
```rust
// Ownership transfer (move)
let s1 = String::from("hello");
let s2 = s1; // s1 no longer valid

// Borrowing (references)
fn len(s: &String) -> usize { s.len() } // immutable borrow
fn append(s: &mut String) { s.push_str(" world") } // mutable borrow

// Rules:
// 1. One mutable reference OR any number of immutable references
// 2. References must always be valid (no dangling)
```

### Lifetimes
```rust
// Explicit lifetime annotation
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

// Struct with borrowed data
struct Config<'a> {
    name: &'a str,
    version: &'a str,
}

// 'static = lives for entire program
fn takes_static(s: &'static str) { }
```

### Option / Result (No Null, No Exceptions)
```rust
// Option<T> — value or nothing
fn find_user(id: u64) -> Option<User> { ... }

// Result<T, E> — success or error
fn save_user(user: User) -> Result<(), DbError> { ... }

// Pattern matching
match find_user(42) {
    Some(user) => println!("Found: {}", user.name),
    None => println!("Not found"),
}

// Combinators
let user = find_user(42).ok_or(NotFound)?;
let name = user.name.clone().unwrap_or_default();
```

---

## Type System Patterns

### Newtype Pattern (Type Safety)
```rust
struct UserId(u64);
struct Email(String);

impl Email {
    fn new(s: String) -> Result<Self, ValidationError> {
        if s.contains('@') { Ok(Self(s)) } else { Err(ValidationError) }
    }
}

// Prevents mixing UserId with OrderId, etc.
fn get_user(id: UserId) -> Option<User> { ... }
```

### State Machines with Enums
```rust
enum OrderState {
    Pending,
    Confirmed { confirmed_at: DateTime<Utc> },
    Shipped { tracking: String },
    Delivered { delivered_at: DateTime<Utc> },
    Cancelled { reason: String },
}

impl OrderState {
    fn ship(self, tracking: String) -> Result<Self, InvalidTransition> {
        match self {
            OrderState::Confirmed { .. } => Ok(OrderState::Shipped { tracking }),
            _ => Err(InvalidTransition),
        }
    }
}
```

### Traits as Interfaces
```rust
// Domain traits (ports)
#[async_trait]
trait UserRepository: Send + Sync {
    async fn find_by_id(&self, id: UserId) -> Result<Option<User>, RepoError>;
    async fn save(&self, user: User) -> Result<(), RepoError>;
}

// Multiple implementations
struct PostgresRepo { pool: PgPool }
struct InMemoryRepo { users: DashMap<UserId, User> }

#[async_trait]
impl UserRepository for PostgresRepo { ... }
#[async_trait]
impl UserRepository for InMemoryRepo { ... }
```

---

## Error Handling

### thiserror / anyhow
```rust
// Library errors — thiserror
#[derive(Error, Debug)]
pub enum DomainError {
    #[error("user not found: {0}")]
    NotFound(UserId),
    #[error("invalid email: {0}")]
    InvalidEmail(String),
    #[error(transparent)]
    Db(#[from] sqlx::Error),
}

// Application errors — anyhow
use anyhow::{Context, Result};

async fn create_user(cmd: CreateUser) -> Result<User> {
    let email = Email::new(cmd.email).context("invalid email")?;
    let user = User::new(cmd.name, email);
    repo.save(&user).await.context("failed to save user")?;
    Ok(user)
}
```

### Error Handling in Async
```rust
// Graceful degradation
async fn get_dashboard(user_id: UserId) -> Result<Dashboard> {
    let (profile, orders, recommendations) = tokio::join!(
        profile_service.get(user_id),
        order_service.recent(user_id),
        recommendation_service.for_user(user_id)
    );

    Ok(Dashboard {
        profile: profile?,
        orders: orders.unwrap_or_default(), // non-critical
        recommendations: recommendations.unwrap_or_default(),
    })
}
```

---

## Async Rust

### Tokio Runtime
```rust
#[tokio::main]
async fn main() -> Result<()> {
    // Multi-threaded runtime by default
    let server = HttpServer::new(|| App::new().configure(routes))
        .bind("0.0.0.0:8080")?
        .run();
    server.await?;
    Ok(())
}
```

### Structured Concurrency (tokio::task)
```rust
use tokio::task::JoinSet;

async fn process_all(items: Vec<Item>) -> Vec<Result<Output>> {
    let mut set = JoinSet::new();
    for item in items {
        set.spawn(async move { process_item(item).await });
    }
    let mut results = Vec::new();
    while let Some(res) = set.join_next().await {
        results.push(res.unwrap_or_else(|e| Err(e.into())));
    }
    results
}

// With semaphore for backpressure
use tokio::sync::Semaphore;

async fn bounded_process(items: Vec<Item>, limit: usize) -> Vec<Result<Output>> {
    let sem = Arc::new(Semaphore::new(limit));
    let mut set = JoinSet::new();
    for item in items {
        let permit = sem.clone().acquire_owned().await.unwrap();
        set.spawn(async move {
            let _permit = permit; // held until end
            process_item(item).await
        });
    }
    // ... collect
}
```

### Channels (mpsc, oneshot, watch)
```rust
// MPSC — multiple producers, single consumer
let (tx, mut rx) = tokio::sync::mpsc::channel(100);

tokio::spawn(async move {
    for item in items {
        tx.send(item).await.unwrap();
    }
});

while let Some(item) = rx.recv().await {
    process(item).await;
}

// oneshot — single value (async/await bridge)
let (tx, rx) = tokio::sync::oneshot::channel();
spawn_blocking(move || { tx.send(heavy_computation()).unwrap(); });
let result = rx.await.unwrap();
```

### Cancellation & Timeouts
```rust
use tokio::time::{timeout, Duration};
use tokio_util::sync::CancellationToken;

let token = CancellationToken::new();
let child_token = token.child_token();

tokio::select! {
    _ = long_running_task(child_token) => {},
    _ = timeout(Duration::from_secs(30), wait_for_signal()) => {
        token.cancel(); // propagate cancellation
    }
}
```

---

## Project Structure (Clean Architecture)

```
.
├── Cargo.toml
├── Cargo.lock
├── src/
│   ├── main.rs                 # Binary entry
│   ├── lib.rs                  # Library root
│   ├── domain/
│   │   ├── mod.rs
│   │   ├── entities/
│   │   ├── value_objects/
│   │   ├── services/
│   │   ├── events/
│   │   └── repositories/       # Traits (ports)
│   ├── application/
│   │   ├── commands/
│   │   ├── queries/
│   │   └── dto/
│   ├── infrastructure/
│   │   ├── persistence/        # sqlx, sea-orm, diesel
│   │   ├── http/               # axum, actix-web, poem
│   │   ├── messaging/          # lapin, rdkafka, async-nats
│   │   └── config.rs           # figment, config
│   └── platform/               # logging, metrics, tracing
├── tests/                      # Integration tests
├── benches/                    # Criterion benchmarks
└── migrations/                 # sqlx migrate
```

---

## Tooling Stack (2024+)

| Category | Recommended | Alternatives |
|---|---|---|
| **Build** | `cargo` (workspace support) | — |
| **Linting** | **clippy** (built-in) | — |
| **Formatting** | `rustfmt` (built-in) | — |
| **Testing** | `cargo test` + **proptest** | **criterion** (bench) |
| **Async Runtime** | **tokio** (full) / **async-std** | glommio (io_uring) |
| **Web Framework** | **axum** (modular, tower-based) | actix-web, poem, salvo |
| **Database** | **sqlx** (compile-time checked) | sea-orm, diesel, surrealdb |
| **Serialization** | **serde** + **serde_json** | rmp-serde (msgpack) |
| **Config** | **figment** / **config** | envy (env-only) |
| **Observability** | **tracing** + **opentelemetry** | slog, log |
| **Error Handling** | **thiserror** (libs) / **anyhow** (apps) | eyre |
| **Validation** | **validator** derive | garde |
| **Mocking** | **mockall** (auto) / manual impls | — |
| **Vulnerability Scan** | **cargo-audit** / **cargo-deny** | Trivy |

### Cargo.toml (Workspace)
```toml
[workspace]
resolver = "2"
members = ["domain", "application", "infrastructure", "api"]

[workspace.dependencies]
tokio = { version = "1.38", features = ["full", "rt-multi-thread"] }
axum = "0.7"
sqlx = { version = "0.7", features = ["runtime-tokio", "postgres", "uuid", "chrono", "json"] }
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
anyhow = "1.0"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
opentelemetry = { version = "0.27", features = ["trace"] }
opentelemetry-otlp = { version = "0.22", features = ["grpc"] }
validator = { version = "0.18", features = ["derive"] }
uuid = { version = "1.7", features = ["v4", "serde", "sqlx"] }
chrono = { version = "0.4", features = ["serde", "sqlx"] }
```

### rustfmt.toml
```toml
edition = "2021"
max_width = 100
use_small_heuristics = "Max"
imports_granularity = "Module"
group_imports = "StdExternalCrate"
```

---

## Database (sqlx)

### Compile-Time Checked Queries
```rust
// migrations/20240101_create_users.sql
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email TEXT NOT NULL UNIQUE,
    name TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- src/infrastructure/persistence/user_repo.rs
#[derive(sqlx::FromRow)]
struct UserRow {
    id: Uuid,
    email: String,
    name: String,
    created_at: DateTime<Utc>,
}

#[sqlx::query("SELECT id, email, name, created_at FROM users WHERE id = $1")]
async fn find_by_id(pool: &PgPool, id: Uuid) -> Result<Option<UserRow>, sqlx::Error>;

#[sqlx::query(
    "INSERT INTO users (id, email, name) VALUES ($1, $2, $3)
     RETURNING id, email, name, created_at"
)]
async fn insert(pool: &PgPool, id: Uuid, email: &str, name: &str) -> Result<UserRow, sqlx::Error>;
```

### Repository Implementation
```rust
pub struct PostgresUserRepo { pool: PgPool }

#[async_trait]
impl UserRepository for PostgresUserRepo {
    async fn find_by_id(&self, id: UserId) -> Result<Option<User>, RepoError> {
        let row = find_by_id(&self.pool, id.0).await?;
        Ok(row.map(User::from))
    }

    async fn save(&self, user: User) -> Result<(), RepoError> {
        insert(&self.pool, user.id.0, &user.email.0, &user.name).await?;
        Ok(())
    }
}
```

---

## HTTP (axum)

```rust
use axum::{routing::{get, post}, Router, Json, extract::{Path, State}};
use tower::ServiceBuilder;
use tower_http::trace::TraceLayer;

#[derive(Clone)]
struct AppState { user_service: Arc<dyn UserService> }

async fn get_user(State(state): State<AppState>, Path(id): Path<UserId>) -> Result<Json<User>, AppError> {
    let user = state.user_service.get_user(id).await?;
    Ok(Json(user))
}

async fn create_user(State(state): State<AppState>, Json(cmd): Json<CreateUserCmd>) -> Result<Json<User>, AppError> {
    let user = state.user_service.create_user(cmd).await?;
    Ok(Json(user))
}

fn router(state: AppState) -> Router {
    Router::new()
        .route("/users/:id", get(get_user))
        .route("/users", post(create_user))
        .layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()))
        .with_state(state)
}
```

---

## Observability (tracing + OpenTelemetry)

```rust
use tracing::{info, error, instrument};
use tracing_subscriber::{fmt, EnvFilter};
use opentelemetry_otlp::WithExportConfig;

fn init_tracing() -> Result<()> {
    let otlp = opentelemetry_otlp::new_pipeline()
        .tracing()
        .with_exporter(opentelemetry_otlp::new_exporter().grpc())
        .install_batch(opentelemetry::runtime::Tokio)?;

    tracing_subscriber::registry()
        .with(EnvFilter::from_default_env())
        .with(fmt::layer().json())
        .with(otlp)
        .init();
    Ok(())
}

#[instrument(skip(service), fields(user_id = %id))]
async fn get_user(service: &UserService, id: UserId) -> Result<User> {
    info!("fetching user");
    service.find_by_id(id).await
}
```

---

## Testing

### Unit Tests
```rust
#[cfg(test)]
mod tests {
    use super::*;
    use mockall::predicate::*;

    #[tokio::test]
    async fn test_create_user() {
        let mut mock_repo = MockUserRepository::new();
        mock_repo.expect_save()
            .with(eq(UserId(Uuid::nil())), always())
            .returning(|_, _| Ok(()));

        let service = UserService::new(Arc::new(mock_repo));
        let result = service.create_user(CreateUserCmd { ... }).await;
        assert!(result.is_ok());
    }
}
```

### Property-Based Testing (proptest)
```rust
use proptest::prelude::*;

proptest! {
    #[test]
    fn email_roundtrip(s in "[a-z]+@[a-z]+\\.[a-z]+") {
        let email = Email::new(s.to_string()).unwrap();
        prop_assert_eq!(email.as_str(), s);
    }
}
```

### Integration Tests (testcontainers)
```rust
#[tokio::test]
async fn test_postgres_repo() {
    let container = testcontainers::clients::Cli::default();
    let pg = container.run(testcontainers::images::postgres::Postgres::default());
    let pool = PgPool::connect(&pg.connection_string()).await.unwrap();
    // ... test with real DB
}
```

---

## Performance

- **Zero-cost abstractions** — Generics monomorphized; no runtime overhead
- **Stack allocation by default** — `Box`/`Arc` only when needed
- **Inline** — `#[inline]`, `#[inline(always)]` for hot paths
- **SIMD** — `std::simd` (nightly) or `packed_simd`
- **Profiling** — `cargo flamegraph`, `perf`, `instruments`
- **Benchmarking** — `criterion` crate

---

## Security

- **cargo-audit** — `cargo install cargo-audit` → `cargo audit`
- **cargo-deny** — License, bans, sources, advisories policy
- **No unsafe** — Avoid; if needed, document with `// SAFETY:`
- **Dependencies** — Minimize; audit with `cargo tree -d`

---

## Related Notes

- [[Languages/Language-Agnostic-Principles]] — Universal patterns
- [[Languages/TypeScript-JavaScript]] — JS/TS patterns
- [[Languages/Python]] — Python patterns
- [[Languages/Go]] — Go patterns
- [[Patterns/Concurrency-Patterns]] — Concurrency deep dive
- [[Patterns/Resilience-Patterns]] — Circuit breaker, retry in Rust
- [[DevOps/CI-CD-Best-Practices]] — Pipeline for Rust
- [[Architecture/Architectural-Styles]] — Hexagonal in Rust

---

*Sources: The Rust Book, Rust by Example, Effective Rust, Jon Gjengset (YouTube), Rust API Guidelines, Tokio Docs, Axum Docs, sqlx Docs, OpenTelemetry Rust, clippy, rustfmt, cargo-audit, proptest, criterion, mockall*