5.0 KiB
5.0 KiB
Rust Application Development Guidelines
Document Version: v1
Note on Versioning:
- This document version is independent — reused across projects
- Project version source of truth:
Cargo.tomlunder[package]CHANGELOG.mduses project version fromCargo.toml
Related Documents
- README.md — Project overview, build instructions, usage
- AGENTS.md — Rules for AI assistants
- PROJECT.md — Project goals and current state
- CHANGELOG.md — Version history
1. Code Style
- Rust edition: 2021
- Format with rustfmt — run
cargo fmtbefore every commit - Lint with clippy — run
cargo clippy -- -D warningsbefore every commit - snake_case functions/variables/modules, PascalCase types/traits, SCREAMING_SNAKE_CASE constants
- Keep functions short and focused — one responsibility per function
2. Cargo
cargo add <crate> # Add runtime dependency
cargo add --dev <crate> # Add dev dependency
cargo remove <crate> # Remove dependency
cargo build # Debug build
cargo build --release # Release build
cargo run # Run debug build
cargo run --release # Run release build
cargo test # Run all tests
cargo fmt # Format code
cargo clippy -- -D warnings # Lint (treat warnings as errors)
Never edit Cargo.toml dependency versions by hand — use cargo add.
3. Project Structure
project/
├── src/
│ ├── main.rs # Entry point
│ ├── lib.rs # Optional: shared library code
│ └── <module>/
│ └── mod.rs
├── tests/ # Integration tests
├── Cargo.toml
└── Cargo.lock # Commit for applications, not for libraries
A project may have multiple binaries under src/bin/.
4. Error Handling
- Use thiserror for defining typed errors in library/domain code
- Use anyhow for application-level error propagation (
main, CLI handlers) - Never use
.unwrap()in production code — use?or explicit handling .expect("reason")is acceptable only when the invariant is guaranteed and documented
5. Logging
Use tracing for structured logging.
[dependencies]
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
use tracing::{debug, info, warn, error};
fn main() {
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.init();
}
Control log level via RUST_LOG environment variable:
RUST_LOG=debug cargo run
RUST_LOG=my_app=info,warn cargo run
Log levels
| Level | When to use |
|---|---|
debug |
Per-item detail: internal state, cache hits, per-item operations |
info |
User-visible milestones: process started/finished, file saved |
warn |
Recoverable issues: fallback used, unexpected but non-fatal state |
error |
Failures the user must know about — operation cannot continue |
Never use println! for debugging or internal logging.
6. Environment and Secrets
- Store secrets in
.envfile - Load via dotenvy crate and
std::env::var() - Never commit
.env
dotenvy::dotenv().ok();
let api_key = std::env::var("API_KEY").expect("API_KEY must be set");
7. Testing
- Use Rust's built-in test framework —
#[test]and#[cfg(test)] - Unit tests live in the same file as the code, in a
mod testsblock - Integration tests live in
tests/ - Use
assert_eq!,assert!,assert_ne!— no external test frameworks needed - Test naming:
test_<action>_<context>
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_valid_input() {
assert_eq!(parse("42"), Ok(42));
}
}
8. Tooling
| Tool | Purpose |
|---|---|
| rustfmt | Code formatting |
| clippy | Linting |
| cargo test | Testing |
| cargo build --release | Production build |
Run before every commit:
cargo fmt
cargo clippy -- -D warnings
cargo test
9. Distribution
For standalone executables:
cargo build --release
# Binary is at: target/release/<project-name>
For cross-compilation (e.g. Windows from Linux):
cargo install cross
cross build --release --target x86_64-pc-windows-gnu
Cargo.lock is committed for applications — it ensures reproducible builds.
10. Versioning
- Follow semantic versioning:
MAJOR.MINOR.PATCH - Version is defined in
Cargo.tomlunder[package] - Always ask before bumping the version — never increment automatically
- Update
CHANGELOG.mdbefore bumping the version
11. Documentation and Task Management
- Keep
PROJECT.mdandCHANGELOG.mdup to date when making changes
Task notation
// TODO: one-liner description of a task to be done
// FIXME: one-liner description of a known bug to be fixed