关于 rust
rust 是面向 Rust 开发者的工程指南,涵盖文件数据、子进程和跨语言接口处理。它强调输入验证、确定性行为与安全 Rust,并提供常见工程领域的参考指南。
主要功能
- 01文件数据处理指南
- 02子进程集成模式
- 03跨语言数据建模
- 04严格的输入验证
- 05错误处理与优雅降级
- 06测试与质量检查清单
适用场景
- 01设计可版本化的文件格式
- 02安全处理子进程输出
- 03避免 UTF-8 截断错误
- 04检查并发与原子文件写入
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ petekp/ agent-skills --skill rust安装后在 Claude Code 中输入/rust确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/data-modeling.mdfile-io.mdprocess-integration.mdtesting.mdtext-and-parsing.md详细介绍
Rust 工程指南
用于构建可靠 Rust 系统的模式,这些系统处理基于文件的数据、外部进程集成和跨语言边界。
核心理念
默认采取保守策略:来自文件、子进程和外部系统的输入都不可信。
- 宁可出现假阴性,也不要出现假阳性
- 相同输入 → 相同输出(确定性)
- 绝不因输入错误而在用户的计算机上发生 panic
规范模型的所有权:当 Rust 是事实来源时,应维护相互独立的表示形式:
| 层 | 用途 | 特点 |
|---|---|---|
| 内部领域模型 | 业务逻辑 | 表达力强的枚举、丰富的类型 |
| FFI DTO | 跨语言边界 | 扁平、稳定、以 String 为主 |
| 文件格式 | 持久化 | 有版本控制、可往返转换 |
| 外部输入 | 验证边界 | 严格验证,绝不信任 |
仅使用安全 Rust:这些模式都不需要 unsafe。使用生态系统中的 crate 实现安全抽象。
参考指南
在处理相应领域时,加载相关参考资料:
| 领域 | 参考资料 | 加载时机 |
|---|---|---|
| 数据建模 | references/data-modeling.md | Serde 模式、UniFFI、强类型、有版本控制的架构 |
| 文件 I/O | references/file-io.md | 原子写入、并发控制、文件监视 |
| 进程集成 | references/process-integration.md | PID 验证、子进程处理、时间戳 |
| 文本与解析 | references/text-and-parsing.md | UTF-8 安全、路径规范化、状态机 |
| 测试 | references/testing.md | 往返测试、模糊测试、Clippy lint |
错误处理
库错误与应用错误
库(公共 API):使用 thiserror,为每项操作定义细粒度的错误类型:
// File operations have their own error type
#[derive(thiserror::Error, Debug)]
pub enum ReadError {
#[error("failed to read {path}")]
Io { path: PathBuf, #[source] source: std::io::Error },
#[error("parse error at line {line}: {message}")]
Parse { line: usize, message: String },
}
// Subprocess operations have their own error type
#[derive(thiserror::Error, Debug)]
pub enum SubprocessError {
#[error("failed to spawn process")]
Spawn(#[source] std::io::Error),
#[error("process exited with {code:?}: {stderr}")]
NonZeroExit { code: Option<i32>, stderr: String },
#[error("output not valid UTF-8")]
InvalidUtf8(#[source] std::str::Utf8Error),
#[error("timed out after {0:?}")]
Timeout(std::time::Duration),
}
应用(内部/二进制程序):使用 anyhow,提供丰富的错误上下文:
use anyhow::{Context, Result};
fn load_config(path: &Path) -> Result<Config> {
let content = std::fs::read_to_string(path)
.with_context(|| format!("failed to read config from {}", path.display()))?;
// ...
}
优雅降级
错误应降低功能,而不是导致崩溃。但在宽松处理时要记录日志:
match parse_metadata(&line) {
Ok(meta) => entries.push(meta),
Err(e) => {
tracing::warn!("skipping malformed entry at line {}: {}", line_num, e);
// Continue processing other entries
}
}
快速参考
应该做
- 使用
std::sync::LazyLock定义静态正则表达式(Rust 1.80+) - 在整个读取-修改-写入周期内持有锁
- 对严格的外部输入添加
#[serde(deny_unknown_fields)] - 使用
.chars()或字素截断字符串,不要按字节切片 - 写入文件时先调用
sync_all(),再重命名,以确保原子性 - 通过进程启动时间验证 PID 身份
- 对时间运算使用
saturating_sub - 提交前运行
cargo clippy -- -D warnings和cargo fmt
不应该做
- 不添加上下文就使用
#[from](会丢失哪个文件出错的信息) - 创建涵盖无关操作的臃肿错误枚举
- 不记录日志就默默忽略错误
- 使用
&s[..N]切片字符串(在字符边界处会发生 panic) - 假定目录迭代顺序稳定
- 未经验证就信任子进程输出
- 使用
unsafe(这些模式不需要它)
本指南可防止的错误
| 错误 | 模式 | 参考资料 |
|---|---|---|
| PID 重用导致的“幽灵会话” | 存储并验证进程启动时间 | process-integration.md |
| 时间戳单位不匹配(秒与毫秒) | 读取时进行规范化 | process-integration.md |
| 截断时发生 UTF-8 panic | 使用 .chars().take(n) | text-and-parsing.md |
| 并发时更新丢失 | 锁覆盖完整的读取-修改-写入周期 | file-io.md |
| 断电导致文件损坏 | 重命名前调用 sync_all() | file-io.md |
| 元数据悄然损坏 | 将更新锚定到标题行 | text-and-parsing.md |
| 旧数据导致新代码出错 | #[serde(default)] + alias | data-modeling.md |
修改检查清单
修改这些系统时,请验证:
Schema / Serde
- 新字段使用
Option+#[serde(default)] - 通过
alias(读取)或rename(写入)支持旧字段名 - 外部输入使用
#[serde(deny_unknown_fields)]
并发
- 在整个读取-修改-写入周期内持有 Mutex
- 共享状态使用
Mutex<T>,而不是thread_local! - 如果使用文件锁,需记录平台注意事项
健壮性
- 文件 I/O 或解析错误不会导致 panic
- 忽略错误前先记录日志
- 子进程设有超时
质量
-
cargo clippy -- -D warnings检查通过 -
cargo fmt --check检查通过 - 不使用
unsafe代码块(除非有充分理由并经过审计)
评论
支持 Markdown