stand-rust
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRust Standards
Rust编码规范
Standards for Rust code.
Rust代码编写规范。
Edition
版本选择
- Use the latest stable edition (2021+)
- Set explicitly in
editionCargo.toml
- 使用最新稳定版本(2021+)
- 在中显式设置
Cargo.tomledition
Toolchain
工具链
- Follow the skill for formatting and linting — lintro runs
lint,rustfmt,clippy, andcargo_auditas configuredcargo_deny - Treat clippy warnings as errors in CI ()
-D warnings - Customize formatting via where needed
rustfmt.toml
- 遵循技能进行格式化与代码检查 — lintro会按照配置运行
lint、rustfmt、clippy和cargo_auditcargo_deny - 在CI中将clippy警告视为错误()
-D warnings - 必要时通过自定义格式化规则
rustfmt.toml
Error Handling
错误处理
-
Usefor library error types — derive structured, typed errors
thiserror -
Usefor application-level error propagation
anyhow -
Noin library code — use
.unwrap()or return?Result -
only with descriptive messages explaining the invariant:
.expect()rust// Good let config = load_config().expect("config.toml must exist at startup"); // Bad let config = load_config().unwrap(); -
Implementfor all custom error types
std::fmt::Display -
Non-panicking/
.unwrap_or_default()over trivial-arm matches:.unwrap_or()rust// Don't let count = match maybe_count { Some(n) => n, None => 0, }; // Do let count = maybe_count.unwrap_or(0);
-
为库错误类型使用— 派生结构化的类型化错误
thiserror -
在应用层错误传播中使用
anyhow -
库代码中禁止使用— 使用
.unwrap()或返回?Result -
仅在带有描述不变量的说明性消息时使用:
.expect()rust// Good let config = load_config().expect("config.toml must exist at startup"); // Bad let config = load_config().unwrap(); -
为所有自定义错误类型实现
std::fmt::Display -
对于简单分支匹配,优先使用非panic的/
.unwrap_or_default():.unwrap_or()rust// Don't let count = match maybe_count { Some(n) => n, None => 0, }; // Do let count = maybe_count.unwrap_or(0);
Type Patterns
类型模式
- Prefer newtypes for domain concepts — over bare
struct UserId(u64)u64 - Use in argument position for flexibility; explicit generics in return position for clarity
impl Trait - Derive on all public types
Debug - Derive ,
Clone,PartialEq,Eqwhere semantically appropriateHash - Prefer over
&strin function arguments; returnStringwhen ownership transfersString
- 优先为领域概念使用新类型 — 用替代裸
struct UserId(u64)u64 - 参数位置使用以提升灵活性;返回位置使用显式泛型以保证清晰性
impl Trait - 为所有公共类型派生
Debug - 在语义合适的情况下派生、
Clone、PartialEq、EqHash - 函数参数中优先使用而非
&str;当需要转移所有权时返回StringString
Unsafe
Unsafe使用准则
-
blocks MUST include a
unsafecomment justifying soundness:// SAFETY:rust// SAFETY: pointer is guaranteed non-null by the allocator contract, // and the lifetime is bounded by the enclosing scope. unsafe { ptr.as_ref() } -
Minimize unsafe surface area — encapsulate in safe abstractions
-
Prefer safe alternatives (e.g.,over raw atomics) unless performance demands otherwise
std::sync::Mutex
-
代码块必须包含
unsafe注释以说明安全性依据:// SAFETY:rust// SAFETY: pointer is guaranteed non-null by the allocator contract, // and the lifetime is bounded by the enclosing scope. unsafe { ptr.as_ref() } -
最小化unsafe代码范围 — 将其封装在安全抽象中
-
优先使用安全替代方案(例如而非原始原子操作),除非性能要求必须使用unsafe
std::sync::Mutex
Documentation
文档编写
-
doc comments on all public items (functions, types, traits, modules)
/// -
Include code examples in doc comments for non-trivial APIs:rust
/// Parse a duration string like "5s", "100ms", or "2m". /// /// # Examples /// /// ``` /// use mycrate::parse_duration; /// /// let d = parse_duration("5s").unwrap(); /// assert_eq!(d, std::time::Duration::from_secs(5)); /// ``` pub fn parse_duration(s: &str) -> Result<Duration> { ... } -
Usefor library crates
#![deny(missing_docs)] -
Module-leveldoc comments for crate and module overviews
//!
-
为所有公共项(函数、类型、trait、模块)添加文档注释
/// -
为非简单API在文档注释中包含代码示例:rust
/// Parse a duration string like "5s", "100ms", or "2m". /// /// # Examples /// /// ``` /// use mycrate::parse_duration; /// /// let d = parse_duration("5s").unwrap(); /// assert_eq!(d, std::time::Duration::from_secs(5)); /// ``` pub fn parse_duration(s: &str) -> Result<Duration> { ... } -
库crate使用
#![deny(missing_docs)] -
为crate和模块概述添加模块级文档注释
//!
Testing
测试规范
- Unit tests in within the same file
#[cfg(test)] mod tests - Integration tests in directory
tests/ - Use for expected panics
#[should_panic(expected = "...")] - Consider or
proptestfor property-based testing where valuablequickcheck - Use and
assert_eq!over bareassert_ne!for better error messagesassert!
rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_duration_seconds() {
let d = parse_duration("5s").unwrap();
assert_eq!(d, Duration::from_secs(5));
}
#[test]
#[should_panic(expected = "invalid format")]
fn parse_duration_rejects_garbage() {
parse_duration("not_a_duration").unwrap();
}
}- 单元测试放在同一文件内的中
#[cfg(test)] mod tests - 集成测试放在目录下
tests/ - 对预期的panic使用
#[should_panic(expected = "...")] - 在有价值的场景下考虑使用或
proptest进行基于属性的测试quickcheck - 优先使用和
assert_eq!而非裸assert_ne!以获得更友好的错误信息assert!
rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_duration_seconds() {
let d = parse_duration("5s").unwrap();
assert_eq!(d, Duration::from_secs(5));
}
#[test]
#[should_panic(expected = "invalid format")]
fn parse_duration_rejects_garbage() {
parse_duration("not_a_duration").unwrap();
}
}Dependencies
依赖管理
- Keep the dependency tree minimal — every dependency is an audit and supply chain surface
- Run vulnerability scanning via lintro (includes
uv run lintro chkandcargo_audit)cargo_deny - Pin versions in workspace for multi-crate workspaces
Cargo.toml - Prefer well-maintained crates with active maintainers and good documentation
- 保持依赖树最小化 — 每个依赖都会增加审计和供应链风险
- 通过lintro运行漏洞扫描(包含
uv run lintro chk和cargo_audit)cargo_deny - 多crate工作区在工作区中固定版本
Cargo.toml - 优先选择维护良好、有活跃维护者且文档完善的crate
Patterns
编码模式
-
Preferblocks over free functions for associated behavior
impl -
Use the builder pattern for types with many optional fields
-
Prefer iterators and combinators over manual loops where readability permits
-
over nested
let-elsepyramids:if letrust// Don't if let Some(user) = lookup(id) { if let Some(email) = user.email { send(email); } } // Do let Some(user) = lookup(id) else { return }; let Some(email) = user.email else { return }; send(email); -
/
.find()/.position()over manual index loops:.any()rust// Don't let mut idx = None; for (i, item) in items.iter().enumerate() { if item.id == target { idx = Some(i); break; } } // Do let idx = items.iter().position(|item| item.id == target); -
for pattern booleans:
matches!()rust// Don't let is_ready = match state { State::Ready => true, _ => false, }; // Do let is_ready = matches!(state, State::Ready); -
Useon functions whose return value should not be ignored
#[must_use] -
Prefer/
Fromimplementations over ad-hoc conversion methodsInto
-
优先使用块而非自由函数来实现关联行为
impl -
为具有多个可选字段的类型使用构建器模式
-
在可读性允许的情况下,优先使用迭代器和组合子而非手动循环
-
使用替代嵌套的
let-else金字塔:if letrust// Don't if let Some(user) = lookup(id) { if let Some(email) = user.email { send(email); } } // Do let Some(user) = lookup(id) else { return }; let Some(email) = user.email else { return }; send(email); -
使用/
.find()/.position()替代手动索引循环:.any()rust// Don't let mut idx = None; for (i, item) in items.iter().enumerate() { if item.id == target { idx = Some(i); break; } } // Do let idx = items.iter().position(|item| item.id == target); -
使用进行模式布尔判断:
matches!()rust// Don't let is_ready = match state { State::Ready => true, _ => false, }; // Do let is_ready = matches!(state, State::Ready); -
对返回值不应被忽略的函数使用
#[must_use] -
优先使用/
From实现而非临时转换方法Into
Linting
代码检查
Follow the skill for linting and formatting workflow.
lint遵循技能进行代码检查与格式化工作流。
lint