用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill rust-mastery命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
| Use when this capability is needed.
> Use when this capability is needed.
Review architecture and API design for the vfs-s3 project. Use when the user mentions @architect, asks to review an issue's design, discuss module boundaries, API shape, or architectural decisions for vfs-s3. Also trigger when the user wants to create an ADR (Architecture Decision Record) or evaluate a technical approach for the project. Intended for dispatch from Codex automation or Claude routines; GitHub trigger phrase: @vfs-s3-bot please prepare design doc Use when this capability is needed.
基于 SOC 职业分类
正在显示 SKILL.md
| name | rust-mastery |
| description | | Use when this capability is needed. |
Comprehensive guide to writing idiomatic, safe, and performant Rust code. This skill synthesizes best practices from "The Rust Programming Language", "Programming Rust", "Effective Rust", and community patterns.
Read additional references based on the task:
Rust's type system is your ally. Use it to:
// Bad: String that could be anything
fn process_email(email: String) { ... }
// Good: Newtype enforces validation
struct Email(String);
impl Email {
pub fn new(s: &str) -> Result<Self, EmailError> {
// Validation happens once, at creation
if s.contains('@') && s.contains('.') {
Ok(Self(s.to_string()))
} else {
Err(EmailError::Invalid)
}
}
}
fn process_email(email: Email) { ... } // Can only receive valid emails
Every value in Rust has exactly one owner. When the owner goes out of scope, the value is dropped.
Three rules to internalize:
// Move semantics (ownership transfer)
let s1 = String::from("hello");
let s2 = s1; // s1 is moved, no longer valid
// println!("{}", s1); // Compile error!
// Borrowing (reference without taking ownership)
let s1 = String::from("hello");
let len = calculate_length(&s1); // Borrow s1
println!("{} has length {}", s1, len); // s1 still valid
fn calculate_length(s: &str) -> usize {
s.len()
}
The borrow checker enforces these rules at compile time:
let mut data = vec![1, 2, 3];
// Multiple immutable borrows OK
let r1 = &data;
let r2 = &data;
println!("{:?} {:?}", r1, r2);
// Mutable borrow after immutable borrows end
let r3 = &mut data;
r3.push(4);
Avoid explicit match when transforms work. This produces cleaner, more composable code.
// Verbose match-based approach
fn get_user_email(user_id: u32) -> Option<String> {
match find_user(user_id) {
Some(user) => match user.email {
Some(email) => Some(email.to_lowercase()),
None => None,
},
None => None,
}
}
// Idiomatic transform approach
fn get_user_email(user_id: u32) -> Option<String> {
find_user(user_id)
.and_then(|user| user.email)
.map(|email| email.to_lowercase())
}
// With the ? operator for Results
fn get_user_data(id: u32) -> Result<UserData, Error> {
let user = find_user(id)?;
let profile = fetch_profile(&user)?;
let settings = load_settings(&user)?;
Ok(UserData { user, profile, settings })
}
Rust distinguishes between recoverable errors (Result) and unrecoverable errors (panic!).
Use Result for:
Use panic for:
// Define custom error types
use thiserror::Error;
#[derive(Error, Debug)]
pub enum DataError {
#[error("Failed to parse data: {0}")]
ParseError(String),
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),
#[error("Not found: {0}")]
NotFound(String),
}
// Use anyhow for application code
use anyhow::{Context, Result};
fn process_config() -> Result<Config> {
let content = std::fs::read_to_string("config.toml")
.context("Failed to read config file")?;
let config: Config = toml::from_str(&content)
.context("Failed to parse config")?;
Ok(config)
}
Prefer iterator transforms over explicit loops. They're often more readable and equally performant.
// Imperative style
let mut results = Vec::new();
for item in items {
if item.is_valid() {
results.push(item.transform());
}
}
// Functional style (preferred)
let results: Vec<_> = items
.iter()
.filter(|item| item.is_valid())
.map(|item| item.transform())
.collect();
// Useful iterator methods
items.iter().find(|x| x.id == target_id) // First match
items.iter().any(|x| x.is_active()) // Existence check
items.iter().all(|x| x.is_valid()) // Universal check
items.iter().fold(0, |acc, x| acc + x.value) // Reduce/accumulate
items.iter().flat_map(|x| x.children()) // Flatten nested
items.iter().()
items.().(other.())
Structs for data with named fields:
struct User {
id: UserId,
name: String,
email: Email,
created_at: DateTime<Utc>,
}
Enums for variants/states:
enum ConnectionState {
Disconnected,
Connecting { attempt: u32 },
Connected { session_id: String },
Error { message: String, retryable: bool },
}
// Pattern matching extracts data
match state {
ConnectionState::Connected { session_id } => {
println!("Session: {}", session_id);
}
ConnectionState::Error { message, retryable: true } => {
println!("Retryable error: {}", message);
}
_ => {}
}
Builder Pattern for complex construction:
#[derive(Default)]
struct RequestBuilder {
url: Option<String>,
method: Method,
headers: HashMap<String, String>,
timeout: Duration,
}
impl RequestBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn url(mut self, url: impl Into<String>) -> Self {
self.url = Some(url.into());
self
}
pub fn header(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.headers.insert(key.into(), value.into());
self
}
pub fn build(self) <Request, BuildError> {
= .url.(BuildError::MissingUrl)?;
(Request { url, method: .method, headers: .headers, timeout: .timeout })
}
}
= RequestBuilder::()
.()
.(, )
.()?;
Newtype Pattern for type safety:
struct UserId(u64);
struct OrderId(u64);
// These cannot be confused, even though both are u64
fn get_user_orders(user_id: UserId) -> Vec<OrderId> { ... }
RAII with Drop:
struct TempFile {
path: PathBuf,
}
impl Drop for TempFile {
fn drop(&mut self) {
let _ = std::fs::remove_file(&self.path);
}
}
// File is automatically deleted when TempFile goes out of scope
&str instead of String where possibleCow<str> - For functions that might or might not need to allocate&[T] - Over &Vec<T> in function parametersimpl Trait - For returning iterators without boxinguse std::borrow::Cow;
// Accepts both owned and borrowed strings efficiently
fn process(input: Cow<'_, str>) -> String {
if input.contains("special") {
input.to_uppercase() // Only allocates when needed
} else {
input.into_owned()
}
}
// Flexible slice parameter
fn sum(numbers: &[i32]) -> i32 {
numbers.iter().sum()
}
// Works with Vec, array, or any contiguous sequence
sum(&vec![1, 2, 3]);
sum(&[1, 2, 3]);
E0382: Use of moved value
// Error: s moved to s2, then used
let s = String::from("hello");
let s2 = s;
println!("{}", s); // Error!
// Fix: Clone if you need both, or use references
let s = String::from("hello");
let s2 = s.clone();
println!("{} {}", s, s2);
E0502: Cannot borrow as mutable because also borrowed as immutable
// Error: Immutable and mutable borrow overlap
let mut v = vec![1, 2, 3];
let first = &v[0];
v.push(4); // Error: v borrowed mutably while first exists
println!("{}", first);
// Fix: End immutable borrow before mutable borrow
let mut v = vec![1, 2, 3];
let first = v[0]; // Copy the value, no borrow
v.push(4);
println!("{}", first);
E0106: Missing lifetime specifier
// Error: Rust can't infer lifetime
fn longest(x: &str, y: &str) -> &str { // Error!
if x.len() > y.len() { x } else { y }
}
// Fix: Add lifetime annotation
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
| Trait | Purpose | When to Implement |
|---|---|---|
Debug | Debug formatting ({:?}) | Always (use #[derive(Debug)]) |
Clone | Explicit duplication | When copying makes sense |
Copy | Implicit copy (bitwise) | Small, stack-only types |
Default | Default value | When there's a sensible default |
PartialEq/Eq | Equality comparison | Comparable types |
PartialOrd/Ord | Ordering | Sortable types |
Hash | Hashing | HashMap/HashSet keys |
Display | User-facing format | Public types |
From/Into | Type conversion | When conversion is natural |
AsRef/AsMut | Cheap reference conversion | Flexible APIs |
Deref | Smart pointer behavior | Wrapper types |
Iterator | Iteration | Custom collections |
Drop | Cleanup on scope exit | RAII resources |
| Category | Crate | Purpose |
|---|---|---|
| Error Handling | thiserror | Derive Error for library types |
| Error Handling | anyhow | Flexible errors for applications |
| Serialization | serde | Serialize/deserialize anything |
| Async Runtime | tokio | Async runtime with full features |
| HTTP Client | reqwest | Ergonomic HTTP client |
| CLI | clap | Command-line argument parsing |
| Logging | tracing | Structured logging/tracing |
| Testing | proptest | Property-based testing |
| Testing | criterion | Benchmarking |
See references/ for deep dives:
Result for expected failures and reserve panics for bugs/invariants.Source: adxptived/Rust-Skills — distributed by TomeVault.