Rust Project Structure

Understanding standard Rust project organization and file architecture.

Intermediateā±ļø 40 minšŸ“š Prerequisites: 2

Rust Project Structure

Proper project structure is essential for maintainable, scalable Rust applications.

Standard Rust Project Layout

my-project/
ā”œā”€ā”€ Cargo.toml          # Project manifest
ā”œā”€ā”€ Cargo.lock          # Dependency lock file
ā”œā”€ā”€ README.md           # Project documentation
ā”œā”€ā”€ .gitignore          # Git ignore rules
ā”œā”€ā”€ src/                # Source code
│   ā”œā”€ā”€ main.rs         # Binary entry point
│   ā”œā”€ā”€ lib.rs          # Library entry point
│   ā”œā”€ā”€ bin/            # Additional binaries
│   │   └── cli.rs
│   ā”œā”€ā”€ modules/        # Application modules
│   │   ā”œā”€ā”€ mod.rs
│   │   ā”œā”€ā”€ api.rs
│   │   └── db.rs
│   └── utils/          # Utility functions
│       └── helpers.rs
ā”œā”€ā”€ tests/              # Integration tests
│   └── integration_test.rs
ā”œā”€ā”€ examples/           # Example code
│   └── basic_example.rs
ā”œā”€ā”€ benches/            # Benchmark tests
│   └── performance.rs
└── docs/               # Additional documentation

Cargo.toml Structure

TOML
[package]
name = "my-project"
version = "0.1.0"
edition = "2021"
authors = ["Your Name"]
description = "Project description"
license = "MIT"

[dependencies]
# External crates
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }

[dev-dependencies]
# Test dependencies
mockito = "1.0"

[build-dependencies]
# Build-time dependencies

[[bin]]
name = "my-binary"
path = "src/bin/my_binary.rs"

[lib]
name = "my_lib"
path = "src/lib.rs"

Module Organization

Flat Structure (Small Projects)

src/
ā”œā”€ā”€ main.rs
ā”œā”€ā”€ api.rs
ā”œā”€ā”€ database.rs
ā”œā”€ā”€ models.rs
└── utils.rs

Hierarchical Structure (Medium Projects)

src/
ā”œā”€ā”€ main.rs
ā”œā”€ā”€ lib.rs
ā”œā”€ā”€ api/
│   ā”œā”€ā”€ mod.rs
│   ā”œā”€ā”€ routes.rs
│   └── handlers.rs
ā”œā”€ā”€ database/
│   ā”œā”€ā”€ mod.rs
│   ā”œā”€ā”€ connection.rs
│   └── migrations.rs
└── models/
    ā”œā”€ā”€ mod.rs
    ā”œā”€ā”€ user.rs
    └── transaction.rs

Domain-Driven Structure (Large Projects)

src/
ā”œā”€ā”€ main.rs
ā”œā”€ā”€ lib.rs
ā”œā”€ā”€ domain/
│   ā”œā”€ā”€ mod.rs
│   ā”œā”€ā”€ user/
│   │   ā”œā”€ā”€ mod.rs
│   │   ā”œā”€ā”€ model.rs
│   │   └── service.rs
│   └── transaction/
│       ā”œā”€ā”€ mod.rs
│       ā”œā”€ā”€ model.rs
│       └── service.rs
ā”œā”€ā”€ infrastructure/
│   ā”œā”€ā”€ mod.rs
│   ā”œā”€ā”€ database.rs
│   └── cache.rs
└── api/
    ā”œā”€ā”€ mod.rs
    └── routes.rs

Workspace Structure (Multiple Crates)

workspace/
ā”œā”€ā”€ Cargo.toml          # Workspace manifest
ā”œā”€ā”€ api/                # API crate
│   ā”œā”€ā”€ Cargo.toml
│   └── src/
ā”œā”€ā”€ core/               # Core business logic
│   ā”œā”€ā”€ Cargo.toml
│   └── src/
ā”œā”€ā”€ database/           # Database layer
│   ā”œā”€ā”€ Cargo.toml
│   └── src/
└── shared/             # Shared utilities
    ā”œā”€ā”€ Cargo.toml
    └── src/

Workspace Cargo.toml:

TOML
[workspace]
members = ["api", "core", "database", "shared"]
resolver = "2"

[workspace.dependencies]
# Shared dependencies
serde = "1.0"
tokio = "1.0"

Best Practices

  • Separation of concerns: Keep business logic separate from infrastructure
  • Module visibility: Use pub carefully, prefer private by default
  • Feature flags: Use Cargo features for optional functionality
  • Tests alongside code: Unit tests in same file, integration tests in tests/
  • Documentation: Use /// for public API docs
  • Error types: Centralize error definitions
  • Configuration: Separate config from code

Code Examples

Module Structure Example

Organizing code into modules

RUST
pub mod api;
pub mod database;
pub mod models;
pub mod routes;
pub mod handlers;
pub fn setup_routes() {
    println!("Setting up API routes");
}
pub fn handle_request() {
    println!("Handling request");
}
pub mod connection;
pub mod migrations;
pub mod user;
pub mod transaction;
fn main() {
    println!("Project structure:");
    println!("- lib.rs: Library entry point");
    println!("- mod.rs: Module declarations");
    println!("- Separate files: Different concerns");
}

Explanation:

Modules organize code into logical units. Each module can be in its own file or directory with a mod.rs file.

Workspace Structure

Multi-crate workspace organization

RUST
fn main() {
    println!("Workspace benefits:");
    println!("- Multiple related crates");
    println!("- Shared dependencies");
    println!("- Independent versioning");
    println!("- Faster compilation");
}

Explanation:

Workspaces allow managing multiple related crates together. They share a dependency resolver and can reference each other.

Exercises

Create Module Structure

Create a module structure with api, database, and models modules!

Easy

Starter Code:

RUST
fn main() {
    println!("Modules created!");
}