skills/ carries the SKILL.md files; scripts/import_skills.py runs inside the VM via turnstone's own storage layer (SKILL.md parser + risk scanner) so rows match what the console admin API would write. Server must be restarted after import (stale WAL snapshot).
2.3 KiB
2.3 KiB
name, description
| name | description |
|---|---|
| rust-best-practices | Best-practices for Rust software. Load into a workstream whenever you need to read or write a Rust (.rs) file. |
Best practices for programming Rust
- Run
cargo check,cargo clippy, andcargo clippybefore comitting to git. - Don't ignore warnings from cargo.
- Don't supress warnings using e.g.
#[allow(warning)] - Never use
unsafewithout asking the user for explicit permission.
When setting up a new rust project, enable these lints:
[lints.clippy]
allow_attributes = "warn"
as_ptr_cast_mut = "warn"
as_underscore = "warn"
borrow_as_ptr = "warn"
implicit_clone = "warn"
undocumented_unsafe_blocks = "warn"
unicode_not_nfc = "warn"
unused_async = "deny"
wildcard_dependencies = "deny"
[lints.rust]
absolute_paths_not_starting_with_crate = "deny"
explicit_outlives_requirements = "warn"
macro_use_extern_crate = "deny"
missing_abi = "deny"
non_ascii_idents = "forbid"
rust_2018_idioms = { level = "deny", priority = -1 }
single_use_lifetimes = "warn"
unused_lifetimes = "warn"
unused_macro_rules = "warn"
Newtypes and "Parse, Don't Validate"
Use newtypes to make invalid states unrepresentable. Instead of passing raw strings and validating at every use site, parse once into a validated type.
Pattern
pub struct Email(String); // private field prevents construction without validation
impl Email {
pub fn parse(s: &str) -> Result<Self, ParseError> {
if !s.contains('@') {
return Err(ParseError::InvalidEmail);
}
Ok(Self(s.to_owned()))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
Guidelines
- Private fields: Force construction through
parse()only - Parse at boundaries: Validate at system edges (API handlers, CLI args, config loading)
- Use the type in signatures:
fn create_user(email: Email)notfn create_user(email: &str) - No re-validation: Once parsed, the type guarantees validity
When to Apply
- Email addresses, passwords, phone numbers
- File paths, URLs, identifiers
- Any domain value with invariants
- Configuration values requiring validation
Anti-pattern to Avoid
// BAD: validation scattered, easy to forget
fn handler(email: &str) {
if !validate_email(email) { return Err(...); }
create_user(email) // still just &str, could be invalid
}