rust
Use when writing Rust command-line tools and libraries with cargo and clap — tariff or pricing calculators, data processing, error handling with Result, property and table tests, and release builds. A
SKILL.mdskills/languages/rust/SKILL.md
GitHubRust
Default: stable toolchain via rustup, edition from cargo new, clap (derive) for CLIs, anyhow in binaries and thiserror in libraries, cargo test, clippy and rustfmt in CI.
Setup
cargo new tool(binary) orcargo new --lib core; for anything non-trivial, a workspace withcore(logic) andcli(I/O).- Pin the toolchain with
rust-toolchain.tomlso every machine uses the same compiler and components (clippy,rustfmt). - Commit
Cargo.lockfor binaries.
CLI with clap
#[derive(clap::Parser)]
#[command(version, about)]
struct Args {
/// Monthly usage in kWh
#[arg(long)]
usage: u32,
#[arg(long, default_value = "plans.toml")]
plans: std::path::PathBuf,
}
- Doc comments become help text; keep them accurate.
- Parse, then call a pure function from
core; print results inmainonly.
Modelling money and tiers
For tiered tariffs (first N units at one price, next M at another, plus a fixed charge and an adjustment per unit):
- Represent prices as integers of the smallest unit (or a decimal crate such as
rust_decimal) — notf64. - Model tiers as a sorted
Vec<(Option<u32>, i64)>(upper bound, price per unit;None= no limit) and compute with one loop; test boundaries at exactly the tier limits. - Compare plans by evaluating each across a range of usages and reporting the crossover points, which is what a person actually wants to know.
Errors
- Libraries: an error enum with
thiserror, one variant per failure the caller may handle. - Binaries:
anyhow::Resultwith.context("reading plans file")so messages explain what was being done. - Avoid
unwrap()outside tests and truly impossible cases; preferexpect("reason")when you must.
Testing
- Unit tests next to the code (
#[cfg(test)] mod tests), integration tests intests/that run the binary withassert_cmd. - Table tests over boundary values;
proptestfor invariants (e.g. total cost is monotonic in usage).
Verification loop
cargo fmt --check,cargo clippy -- -D warnings.cargo test.cargo build --releaseand run the binary with--helpand a real input.
Pitfalls
- Borrow fights over a simple flow usually mean shared mutable state; restructure into owned data passed through functions, or clone small values. Reach for
Rc<RefCell<_>>last. - Integer overflow panics in debug and wraps in release; use
checked_*/saturating_*where inputs are external. Stringvs&str: take&str(orimpl AsRef<str>) in parameters, returnString.- Slow first build is normal; use
cargo checkwhile iterating. - Cross-compiling needs the target's linker; build in a container of the target platform when in doubt.