1.6 KiB
1.6 KiB
Rust Best Practices
Code Style
- Use
rustfmtfor formatting (runcargo fmtbefore committing) - Use
clippyfor linting (runcargo clippy -- -D warnings) - Prefer
?operator over.unwrap()for error handling - Use
anyhow::Resultfor application errors,thiserrorfor library errors - Avoid
.clone()unless necessary - prefer references - Use
&strfor function parameters,Stringfor owned data
Error Handling
// GOOD: Propagate errors with context
fn read_config(path: &Path) -> Result<Config> {
let content = fs::read_to_string(path)
.context("Failed to read config file")?;
serde_json::from_str(&content)
.context("Failed to parse config")
}
// BAD: Panic on error
fn read_config(path: &Path) -> Config {
let content = fs::read_to_string(path).unwrap(); // Don't do this
serde_json::from_str(&content).unwrap()
}
Memory Safety
- Never use
unsafewithout explicit justification and review - Prefer
Vecover raw pointers - Use
Arc<Mutex<T>>for shared mutable state across threads - Avoid
static mut- uselazy_staticoronce_cellinstead
Testing
- Write unit tests with
#[cfg(test)]modules - Use
tempfilefor tests involving filesystem - Run
cargo testbefore committing - Use
cargo tarpaulinfor coverage reports
SQL Injection Prevention
Always use parameterized queries with rusqlite::params![]:
// GOOD
conn.execute("INSERT INTO users (name) VALUES (?1)", params![name])?;
// BAD - SQL injection vulnerability
conn.execute(&format!("INSERT INTO users (name) VALUES ('{}')", name), [])?;