217 lines
9.0 KiB
Markdown
217 lines
9.0 KiB
Markdown
---
|
|
trigger: model_decision
|
|
description: When working on a Rust or Cargo project, setting up Rust project structure, or organizing Rust crates and workspaces
|
|
---
|
|
|
|
## Rust/Cargo Layout
|
|
|
|
Use these structures for Rust projects. The vertical slice principle applies — features are modules, not layers.
|
|
|
|
### Single Binary Crate
|
|
|
|
For CLI tools, standalone servers, and single-purpose applications.
|
|
|
|
```
|
|
project-root/
|
|
Cargo.toml # Package manifest + dependencies
|
|
build.rs # Build script (optional — for FFI, codegen)
|
|
src/
|
|
main.rs # Entry point: CLI parsing, server startup, wires dependencies
|
|
lib.rs # Library root — re-exports public modules (enables integration testing)
|
|
|
|
# --- Foundational Concerns (The "Platform") ---
|
|
config.rs # Configuration loading (env vars, config files)
|
|
error.rs # Application-wide error types (thiserror enum)
|
|
telemetry.rs # Tracing/logging setup (tracing, tracing-subscriber)
|
|
|
|
# --- Business Features (Vertical Slices) ---
|
|
features/
|
|
mod.rs # Re-exports feature modules
|
|
task/
|
|
mod.rs # Public API of this feature — re-exports types + service
|
|
service.rs # Feature service (business logic orchestration)
|
|
logic.rs # Pure business rules (no I/O, easily testable)
|
|
models.rs # Domain structs (Task, NewTaskRequest)
|
|
error.rs # Feature-specific error types
|
|
repository.rs # Storage trait definition
|
|
postgres.rs # Postgres implementation of repository trait
|
|
mock.rs # Mock implementation for testing
|
|
auth/
|
|
mod.rs
|
|
service.rs
|
|
logic.rs
|
|
models.rs
|
|
...
|
|
|
|
# --- Delivery Layer (HTTP/gRPC) ---
|
|
handlers/
|
|
mod.rs
|
|
task_handler.rs # HTTP handlers for task feature (axum/actix extractors)
|
|
auth_handler.rs
|
|
router.rs # Route definitions, middleware stack
|
|
|
|
tests/ # Integration tests (compiled as separate crate, access only pub API)
|
|
common/
|
|
mod.rs # Shared test fixtures, helpers, test database setup
|
|
task_api_test.rs # Full API integration tests
|
|
auth_flow_test.rs
|
|
|
|
benches/ # Benchmarks (criterion)
|
|
task_benchmark.rs
|
|
```
|
|
|
|
**Key Rust conventions:**
|
|
- `src/lib.rs` + `src/main.rs` — enables integration testing against `lib.rs` public API
|
|
- `mod.rs` re-exports — each feature's `mod.rs` is its public boundary
|
|
- `error.rs` per feature — typed errors with `thiserror`, composed at app level with `#[from]`
|
|
- `tests/` directory — integration tests see only the public API, enforcing encapsulation
|
|
- No `controllers/` or `services/` at the top level — features are the top-level organization
|
|
|
|
---
|
|
|
|
### Library Crate
|
|
|
|
For publishable libraries, SDKs, and reusable components.
|
|
|
|
```
|
|
project-root/
|
|
Cargo.toml # Package manifest (lib target)
|
|
src/
|
|
lib.rs # Crate root — public API surface, module re-exports
|
|
parser.rs # Public module
|
|
ast.rs # Public module
|
|
error.rs # Public error types (thiserror)
|
|
internal/ # Private implementation details
|
|
mod.rs
|
|
optimizer.rs
|
|
cache.rs
|
|
|
|
examples/ # Runnable examples (cargo run --example)
|
|
basic_usage.rs
|
|
advanced_config.rs
|
|
|
|
tests/ # Integration tests
|
|
parsing_test.rs
|
|
|
|
benches/ # Benchmarks
|
|
parser_benchmark.rs
|
|
```
|
|
|
|
---
|
|
|
|
### Cargo Workspace (Multi-Crate)
|
|
|
|
For complex projects with multiple internal crates. This is the recommended structure for projects where distinct subsystems benefit from separate compilation units and explicit dependency boundaries.
|
|
|
|
```
|
|
project-root/
|
|
Cargo.toml # [workspace] manifest — lists all members
|
|
Cargo.lock # Locked dependency versions (committed for binaries)
|
|
|
|
crates/
|
|
myapp/ # Main binary crate (entry point, wiring)
|
|
Cargo.toml # Depends on other workspace crates
|
|
src/
|
|
main.rs # CLI parsing, server setup
|
|
lib.rs
|
|
config.rs
|
|
error.rs
|
|
api/ # API / protocol handling
|
|
mod.rs
|
|
routes.rs # Route definitions
|
|
handlers.rs # Request handlers
|
|
|
|
myapp-parser/ # Domain-specific engine crate
|
|
Cargo.toml
|
|
build.rs # Build script (optional — for FFI, codegen)
|
|
src/
|
|
lib.rs
|
|
parser.rs # Core parsing logic
|
|
transform.rs # Data transformations
|
|
cache.rs # Caching layer
|
|
tests/ # Per-crate integration tests (public API only)
|
|
parser_integration.rs
|
|
|
|
myapp-client/ # External service client crate
|
|
Cargo.toml
|
|
src/
|
|
lib.rs
|
|
client.rs # Client implementation
|
|
lifecycle.rs # Connection management
|
|
retry.rs # Retry and resilience logic
|
|
|
|
myapp-search/ # Search / query engine crate
|
|
Cargo.toml
|
|
src/
|
|
lib.rs
|
|
search.rs # Search implementation
|
|
filter.rs # Result filtering
|
|
tests/ # Per-crate integration tests
|
|
search_integration.rs
|
|
|
|
myapp-common/ # Shared types and utilities
|
|
Cargo.toml
|
|
src/
|
|
lib.rs
|
|
types.rs # Shared domain types
|
|
error.rs # Common error types
|
|
tests/ # Per-crate integration tests
|
|
common_integration.rs
|
|
|
|
tests/ # Workspace-level integration tests
|
|
integration/
|
|
full_pipeline_test.rs # End-to-end tests across crates
|
|
|
|
config/ # Default configuration
|
|
myapp.config.default.json
|
|
```
|
|
|
|
**Key differences from Go/Node layouts:**
|
|
- `crates/` replaces `apps/` — Cargo workspace with explicit inter-crate dependencies in `Cargo.toml`
|
|
- Each crate has its own `Cargo.toml` — dependencies are scoped, compile separately, enforces boundaries
|
|
- `build.rs` — Rust-specific build script for FFI compilation (C grammars for tree-sitter)
|
|
- `Cargo.lock` committed — standard practice for binary projects (not for library crates)
|
|
- No `node_modules/`, `vendor/` — dependencies are managed by Cargo globally in `~/.cargo/`
|
|
- Feature flags in `Cargo.toml` — use `[features]` for optional functionality instead of build-time env vars
|
|
|
|
### Test Organization in Rust
|
|
|
|
Rust has a compiler-enforced two-tier test system that differs fundamentally from Go/TS:
|
|
|
|
**Unit Tests — Inline (Not Separate Files)**
|
|
- Convention: `#[cfg(test)] mod tests` block **at the bottom of each `.rs` file**
|
|
- Tests are compiled conditionally — stripped from production builds
|
|
- Can access **private** functions via `use super::*`
|
|
- This is NOT a shortcut — it is the official, idiomatic Rust convention
|
|
- Do NOT create separate `*_test.rs` files for unit tests
|
|
|
|
**Integration Tests — `tests/` Directory**
|
|
- Location: `tests/` directory **at each crate's root** (next to `src/`)
|
|
- Each `.rs` file in `tests/` is compiled as its own **separate crate**
|
|
- Can only access the crate's **public API** (`use my_crate::...`)
|
|
- No `#[cfg(test)]` needed — Cargo treats `tests/` as test-only automatically
|
|
- Shared test helpers go in `tests/common/mod.rs` (not `tests/common.rs`)
|
|
|
|
**Workspace-level tests:**
|
|
- For cross-crate integration / E2E tests, place in `tests/` at the workspace root
|
|
- Or create a dedicated test crate in the workspace (e.g. `tests-integration/` — tokio pattern)
|
|
|
|
**Example per-crate layout with tests:**
|
|
```
|
|
crates/pathfinder-search/
|
|
Cargo.toml
|
|
src/
|
|
lib.rs # Contains #[cfg(test)] mod tests { ... } at bottom
|
|
search.rs # Contains #[cfg(test)] mod tests { ... } at bottom
|
|
filter.rs # Contains #[cfg(test)] mod tests { ... } at bottom
|
|
mock.rs # Mock implementations
|
|
tests/ # Integration tests (separate crate, public API only)
|
|
search_integration.rs # Tests search through public lib.rs API
|
|
common/
|
|
mod.rs # Shared test fixtures and helpers
|
|
```
|
|
|
|
### Related Principles
|
|
- Project Structure @project-structure.md (core philosophy)
|
|
- Rust Idioms and Patterns @rust-idioms-and-patterns.md
|