Source profileQuality 82/100Review permissions

affaan-m/ECC/docs/ja-JP/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/ja-JP/skills/rust-patterns"
    Safe inspection promptEditorial

    Inspect the Agent Skill "rust-patterns" from https://github.com/affaan-m/ECC/blob/4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38/docs/ja-JP/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コードをリファクタリングする場合 クレート構造とモジュールレイアウトを設計する場合

      新しいRustコードを書く場合Rustコードをレビューする場合既存のRustコードをリファクタリングする場合
    2. 02

      動作原理

      このスキルは6つの重要な領域で慣用的なRustの規約を強制する:コンパイル時のデータ競合防止のための所有権と借用、ライブラリではthiserror、アプリケーションではanyhowを使用したResult/?エラー伝播、不正な状態を表現不可能にする列挙型と完全パターンマッチング、ゼロコスト抽象化のためのトレイトとジェネリクス、Arc、チャンネル、async/awaitによる安全な並行処理、ドメインで整理された最小化されたpubインターフェース。

      このスキルは6つの重要な領域で慣用的なRustの規約を強制する:コンパイル時のデータ競合防止のための所有権と借用、ライブラリではthiserror、アプリケーションではanyhowを使用したResult/?エラー伝播、不正な状態を表現不可能にする列挙型と完全パターンマッチング、ゼロコスト抽象化のためのトレイトとジェネリクス、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/ja-JP/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コードをリファクタリングする場合
    • クレート構造とモジュールレイアウトを設計する場合

    動作原理

    このスキルは6つの重要な領域で慣用的なRustの規約を強制する:コンパイル時のデータ競合防止のための所有権と借用、ライブラリではthiserror、アプリケーションではanyhowを使用したResult/?エラー伝播、不正な状態を表現不可能にする列挙型と完全パターンマッチング、ゼロコスト抽象化のためのトレイトとジェネリクス、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
    }
    

    トレイトとジェネリクス

    ジェネリックを受け取り、具体的な型を返す

    // 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}")
    }
    

    動的ディスパッチにトレイトオブジェクトを使用する

    // 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
    

    モジュールシステムとクレート構造

    型ではなくドメインで整理する

    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