Source profileQuality 82/100Review permissions

affaan-m/ECC/docs/zh-CN/skills/rust-patterns/SKILL.md

rust-patterns

Review rust-patterns's use cases, installation, workflow, and original source instructions.

Source repository stars
234,327
Declared platforms
0
Static risk flags
1
Last source update
2026-07-27
Source checked
2026-07-28

Decision brief

What it does—and where it fits

构建安全、高性能且可维护应用程序的惯用 Rust 模式和最佳实践。

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/affaan-m/ECC --skill "docs/zh-CN/skills/rust-patterns"
    Safe inspection promptEditorial

    Inspect the Agent Skill "rust-patterns" from https://github.com/affaan-m/ECC/blob/4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38/docs/zh-CN/skills/rust-patterns/SKILL.md at commit 4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      何时使用

      编写新的 Rust 代码时 评审 Rust 代码时 重构现有 Rust 代码时 设计 crate 结构和模块布局时

      编写新的 Rust 代码时评审 Rust 代码时重构现有 Rust 代码时
    2. 02

      工作原理

      此技能在六个关键领域强制执行惯用的 Rust 约定:所有权和借用,用于在编译时防止数据竞争;Result/? 错误传播,库使用 thiserror 而应用程序使用 anyhow;枚举和穷尽模式匹配,使非法状态无法表示;用于零成本抽象的 trait 和泛型;通过 Arc、通道和 async/await 实现的安全并发;以及按领域组织的最小化 pub 接口。

      此技能在六个关键领域强制执行惯用的 Rust 约定:所有权和借用,用于在编译时防止数据竞争;Result/? 错误传播,库使用 thiserror 而应用程序使用 anyhow;枚举和穷尽模式匹配,使非法状态无法表示;用于零成本抽象的 trait 和泛型;通过 Arc、通道和 async/await 实现的安全并发;以及按领域组织的最小化 pub 接口。
    3. 03

      核心原则

      Rust 的所有权系统在编译时防止数据竞争和内存错误。

      Rust 的所有权系统在编译时防止数据竞争和内存错误。
    4. 04

      1. 所有权和借用

      Rust 的所有权系统在编译时防止数据竞争和内存错误。

      Rust 的所有权系统在编译时防止数据竞争和内存错误。
    5. 05

      使用 Cow 实现灵活的所有权

      Review the “使用 Cow 实现灵活的所有权” section in the pinned source before continuing.

      Review and apply the “使用 Cow 实现灵活的所有权” source section.

    Permission review

    Static risk signals and limitations

    Runs scripts

    medium · line 432

    The documentation asks the agent to run terminal commands or scripts.

    cargo build

    Runs scripts

    medium · line 433

    The documentation asks the agent to run terminal commands or scripts.

    cargo check # Fast type checking without codegen

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score82/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars234,327SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    affaan-m/ECC
    Skill path
    docs/zh-CN/skills/rust-patterns/SKILL.md
    Commit
    4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38
    License
    MIT
    Collected
    2026-07-28
    Default branch
    main
    View the original SKILL.md

    Rust 开发模式

    构建安全、高性能且可维护应用程序的惯用 Rust 模式和最佳实践。

    何时使用

    • 编写新的 Rust 代码时
    • 评审 Rust 代码时
    • 重构现有 Rust 代码时
    • 设计 crate 结构和模块布局时

    工作原理

    此技能在六个关键领域强制执行惯用的 Rust 约定:所有权和借用,用于在编译时防止数据竞争;Result/? 错误传播,库使用 thiserror 而应用程序使用 anyhow;枚举和穷尽模式匹配,使非法状态无法表示;用于零成本抽象的 trait 和泛型;通过 Arc<Mutex<T>>、通道和 async/await 实现的安全并发;以及按领域组织的最小化 pub 接口。

    核心原则

    1. 所有权和借用

    Rust 的所有权系统在编译时防止数据竞争和内存错误。

    // Good: Pass references when you don't need ownership
    fn process(data: &[u8]) -> usize {
        data.len()
    }
    
    // Good: Take ownership only when you need to store or consume
    fn store(data: Vec<u8>) -> Record {
        Record { payload: data }
    }
    
    // Bad: Cloning unnecessarily to avoid borrow checker
    fn process_bad(data: &Vec<u8>) -> usize {
        let cloned = data.clone(); // Wasteful — just borrow
        cloned.len()
    }
    

    使用 Cow 实现灵活的所有权

    use std::borrow::Cow;
    
    fn normalize(input: &str) -> Cow<'_, str> {
        if input.contains(' ') {
            Cow::Owned(input.replace(' ', "_"))
        } else {
            Cow::Borrowed(input) // Zero-cost when no mutation needed
        }
    }
    

    错误处理

    使用 Result? —— 切勿在生产环境中使用 unwrap()

    // Good: Propagate errors with context
    use anyhow::{Context, Result};
    
    fn load_config(path: &str) -> Result<Config> {
        let content = std::fs::read_to_string(path)
            .with_context(|| format!("failed to read config from {path}"))?;
        let config: Config = toml::from_str(&content)
            .with_context(|| format!("failed to parse config from {path}"))?;
        Ok(config)
    }
    
    // Bad: Panics on error
    fn load_config_bad(path: &str) -> Config {
        let content = std::fs::read_to_string(path).unwrap(); // Panics!
        toml::from_str(&content).unwrap()
    }
    

    库错误使用 thiserror,应用程序错误使用 anyhow

    // Library code: structured, typed errors
    use thiserror::Error;
    
    #[derive(Debug, Error)]
    pub enum StorageError {
        #[error("record not found: {id}")]
        NotFound { id: String },
        #[error("connection failed")]
        Connection(#[from] std::io::Error),
        #[error("invalid data: {0}")]
        InvalidData(String),
    }
    
    // Application code: flexible error handling
    use anyhow::{bail, Result};
    
    fn run() -> Result<()> {
        let config = load_config("app.toml")?;
        if config.workers == 0 {
            bail!("worker count must be > 0");
        }
        Ok(())
    }
    

    优先使用 Option 组合子而非嵌套匹配

    // Good: Combinator chain
    fn find_user_email(users: &[User], id: u64) -> Option<String> {
        users.iter()
            .find(|u| u.id == id)
            .map(|u| u.email.clone())
    }
    
    // Bad: Deeply nested matching
    fn find_user_email_bad(users: &[User], id: u64) -> Option<String> {
        match users.iter().find(|u| u.id == id) {
            Some(user) => match &user.email {
                email => Some(email.clone()),
            },
            None => None,
        }
    }
    

    枚举和模式匹配

    将状态建模为枚举

    // Good: Impossible states are unrepresentable
    enum ConnectionState {
        Disconnected,
        Connecting { attempt: u32 },
        Connected { session_id: String },
        Failed { reason: String, retries: u32 },
    }
    
    fn handle(state: &ConnectionState) {
        match state {
            ConnectionState::Disconnected => connect(),
            ConnectionState::Connecting { attempt } if *attempt > 3 => abort(),
            ConnectionState::Connecting { .. } => wait(),
            ConnectionState::Connected { session_id } => use_session(session_id),
            ConnectionState::Failed { retries, .. } if *retries < 5 => retry(),
            ConnectionState::Failed { reason, .. } => log_failure(reason),
        }
    }
    

    穷尽匹配 —— 业务逻辑中不使用通配符

    // Good: Handle every variant explicitly
    match command {
        Command::Start => start_service(),
        Command::Stop => stop_service(),
        Command::Restart => restart_service(),
        // Adding a new variant forces handling here
    }
    
    // Bad: Wildcard hides new variants
    match command {
        Command::Start => start_service(),
        _ => {} // Silently ignores Stop, Restart, and future variants
    }
    

    Trait 和泛型

    接受泛型,返回具体类型

    // Good: Generic input, concrete output
    fn read_all(reader: &mut impl Read) -> std::io::Result<Vec<u8>> {
        let mut buf = Vec::new();
        reader.read_to_end(&mut buf)?;
        Ok(buf)
    }
    
    // Good: Trait bounds for multiple constraints
    fn process<T: Display + Send + 'static>(item: T) -> String {
        format!("processed: {item}")
    }
    

    使用 Trait 对象进行动态分发

    // Use when you need heterogeneous collections or plugin systems
    trait Handler: Send + Sync {
        fn handle(&self, request: &Request) -> Response;
    }
    
    struct Router {
        handlers: Vec<Box<dyn Handler>>,
    }
    
    // Use generics when you need performance (monomorphization)
    fn fast_process<H: Handler>(handler: &H, request: &Request) -> Response {
        handler.handle(request)
    }
    

    使用 Newtype 模式确保类型安全

    // Good: Distinct types prevent mixing up arguments
    struct UserId(u64);
    struct OrderId(u64);
    
    fn get_order(user: UserId, order: OrderId) -> Result<Order> {
        // Can't accidentally swap user and order IDs
        todo!()
    }
    
    // Bad: Easy to swap arguments
    fn get_order_bad(user_id: u64, order_id: u64) -> Result<Order> {
        todo!()
    }
    

    结构体和数据建模

    使用构建器模式进行复杂构造

    struct ServerConfig {
        host: String,
        port: u16,
        max_connections: usize,
    }
    
    impl ServerConfig {
        fn builder(host: impl Into<String>, port: u16) -> ServerConfigBuilder {
            ServerConfigBuilder { host: host.into(), port, max_connections: 100 }
        }
    }
    
    struct ServerConfigBuilder { host: String, port: u16, max_connections: usize }
    
    impl ServerConfigBuilder {
        fn max_connections(mut self, n: usize) -> Self { self.max_connections = n; self }
        fn build(self) -> ServerConfig {
            ServerConfig { host: self.host, port: self.port, max_connections: self.max_connections }
        }
    }
    
    // Usage: ServerConfig::builder("localhost", 8080).max_connections(200).build()
    

    迭代器和闭包

    优先使用迭代器链而非手动循环

    // Good: Declarative, lazy, composable
    let active_emails: Vec<String> = users.iter()
        .filter(|u| u.is_active)
        .map(|u| u.email.clone())
        .collect();
    
    // Bad: Imperative accumulation
    let mut active_emails = Vec::new();
    for user in &users {
        if user.is_active {
            active_emails.push(user.email.clone());
        }
    }
    

    使用带有类型注解的 collect()

    // Collect into different types
    let names: Vec<_> = items.iter().map(|i| &i.name).collect();
    let lookup: HashMap<_, _> = items.iter().map(|i| (i.id, i)).collect();
    let combined: String = parts.iter().copied().collect();
    
    // Collect Results — short-circuits on first error
    let parsed: Result<Vec<i32>, _> = strings.iter().map(|s| s.parse()).collect();
    

    并发

    使用 Arc<Mutex<T>> 处理共享可变状态

    use std::sync::{Arc, Mutex};
    
    let counter = Arc::new(Mutex::new(0));
    let handles: Vec<_> = (0..10).map(|_| {
        let counter = Arc::clone(&counter);
        std::thread::spawn(move || {
            let mut num = counter.lock().expect("mutex poisoned");
            *num += 1;
        })
    }).collect();
    
    for handle in handles {
        handle.join().expect("worker thread panicked");
    }
    

    使用通道进行消息传递

    use std::sync::mpsc;
    
    let (tx, rx) = mpsc::sync_channel(16); // Bounded channel with backpressure
    
    for i in 0..5 {
        let tx = tx.clone();
        std::thread::spawn(move || {
            tx.send(format!("message {i}")).expect("receiver disconnected");
        });
    }
    drop(tx); // Close sender so rx iterator terminates
    
    for msg in rx {
        println!("{msg}");
    }
    

    使用 Tokio 进行异步编程

    use tokio::time::Duration;
    
    async fn fetch_with_timeout(url: &str) -> Result<String> {
        let response = tokio::time::timeout(
            Duration::from_secs(5),
            reqwest::get(url),
        )
        .await
        .context("request timed out")?
        .context("request failed")?;
    
        response.text().await.context("failed to read body")
    }
    
    // Spawn concurrent tasks
    async fn fetch_all(urls: Vec<String>) -> Vec<Result<String>> {
        let handles: Vec<_> = urls.into_iter()
            .map(|url| tokio::spawn(async move {
                fetch_with_timeout(&url).await
            }))
            .collect();
    
        let mut results = Vec::with_capacity(handles.len());
        for handle in handles {
            results.push(handle.await.unwrap_or_else(|e| panic!("spawned task panicked: {e}")));
        }
        results
    }
    

    不安全代码

    何时可以使用 Unsafe

    // Acceptable: FFI boundary with documented invariants (Rust 2024+)
    /// # Safety
    /// `ptr` must be a valid, aligned pointer to an initialized `Widget`.
    unsafe fn widget_from_raw<'a>(ptr: *const Widget) -> &'a Widget {
        // SAFETY: caller guarantees ptr is valid and aligned
        unsafe { &*ptr }
    }
    
    // Acceptable: Performance-critical path with proof of correctness
    // SAFETY: index is always < len due to the loop bound
    unsafe { slice.get_unchecked(index) }
    

    何时不可以使用 Unsafe

    // Bad: Using unsafe to bypass borrow checker
    // Bad: Using unsafe for convenience
    // Bad: Using unsafe without a Safety comment
    // Bad: Transmuting between unrelated types
    

    模块系统和 Crate 结构

    按领域组织,而非按类型

    my_app/
    ├── src/
    │   ├── main.rs
    │   ├── lib.rs
    │   ├── auth/          # 领域模块
    │   │   ├── mod.rs
    │   │   ├── token.rs
    │   │   └── middleware.rs
    │   ├── orders/        # 领域模块
    │   │   ├── mod.rs
    │   │   ├── model.rs
    │   │   └── service.rs
    │   └── db/            # 基础设施
    │       ├── mod.rs
    │       └── pool.rs
    ├── tests/             # 集成测试
    ├── benches/           # 基准测试
    └── Cargo.toml
    

    可见性 —— 最小化暴露

    // Good: pub(crate) for internal sharing
    pub(crate) fn validate_input(input: &str) -> bool {
        !input.is_empty()
    }
    
    // Good: Re-export public API from lib.rs
    pub mod auth;
    pub use auth::AuthMiddleware;
    
    // Bad: Making everything pub
    pub fn internal_helper() {} // Should be pub(crate) or private
    

    工具集成

    基本命令

    # Build and check
    cargo build
    cargo check              # Fast type checking without codegen
    cargo clippy             # Lints and suggestions
    cargo fmt                # Format code
    
    # Testing
    cargo test
    cargo test -- --nocapture    # Show println output
    cargo test --lib             # Unit tests only
    cargo test --test integration # Integration tests only
    
    # Dependencies
    cargo audit              # Security audit
    cargo tree               # Dependency tree
    cargo update             # Update dependencies
    
    # Performance
    cargo bench              # Run benchmarks
    

    快速参考:Rust 惯用法

    惯用法描述
    借用,而非克隆传递 &T,除非需要所有权,否则不要克隆
    使非法状态无法表示使用枚举仅对有效状态进行建模
    ? 优于 unwrap()传播错误,切勿在库/生产代码中恐慌
    解析,而非验证在边界处将非结构化数据转换为类型化结构体
    Newtype 用于类型安全将基本类型包装在 newtype 中以防止参数错位
    优先使用迭代器而非循环声明式链更清晰且通常更快
    对 Result 使用 #[must_use]确保调用者处理返回值
    使用 Cow 实现灵活的所有权当借用足够时避免分配
    穷尽匹配业务关键枚举不使用通配符 _
    最小化 pub 接口内部 API 使用 pub(crate)

    应避免的反模式

    // Bad: .unwrap() in production code
    let value = map.get("key").unwrap();
    
    // Bad: .clone() to satisfy borrow checker without understanding why
    let data = expensive_data.clone();
    process(&original, &data);
    
    // Bad: Using String when &str suffices
    fn greet(name: String) { /* should be &str */ }
    
    // Bad: Box<dyn Error> in libraries (use thiserror instead)
    fn parse(input: &str) -> Result<Data, Box<dyn std::error::Error>> { todo!() }
    
    // Bad: Ignoring must_use warnings
    let _ = validate(input); // Silently discarding a Result
    
    // Bad: Blocking in async context
    async fn bad_async() {
        std::thread::sleep(Duration::from_secs(1)); // Blocks the executor!
        // Use: tokio::time::sleep(Duration::from_secs(1)).await;
    }
    

    请记住:如果它能编译,那它很可能是正确的 —— 但前提是你要避免 unwrap(),最小化 unsafe,并让类型系统为你工作。

    Alternatives

    Compare before choosing