9.0 KiB
9.0 KiB
trigger, description
| trigger | description |
|---|---|
| model_decision | 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 againstlib.rspublic APImod.rsre-exports — each feature'smod.rsis its public boundaryerror.rsper feature — typed errors withthiserror, composed at app level with#[from]tests/directory — integration tests see only the public API, enforcing encapsulation- No
controllers/orservices/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/replacesapps/— Cargo workspace with explicit inter-crate dependencies inCargo.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.lockcommitted — 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 testsblock at the bottom of each.rsfile - 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.rsfiles for unit tests
Integration Tests — tests/ Directory
- Location:
tests/directory at each crate's root (next tosrc/) - Each
.rsfile intests/is compiled as its own separate crate - Can only access the crate's public API (
use my_crate::...) - No
#[cfg(test)]needed — Cargo treatstests/as test-only automatically - Shared test helpers go in
tests/common/mod.rs(nottests/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