mcpField
R
rust-stdlib

rust-stdlib

github.com/full-stack-skills開発1298 回インストール5 週間前に更新
リポジトリ

rust-stdlib について

Rust 開発者向けに、標準ライブラリ API の選択と組み合わせを案内するスキルです。コレクション、ポインター、文字列、I/O、イテレーター、並行処理の選択を扱います。

主な機能

  1. 01コレクションとスマートポインターの選択
  2. 02文字列型とパス型の選択
  3. 03Option と Result の連鎖処理
  4. 04I/O トレイトとイテレーターパターンの選択
  5. 05標準ライブラリの並行処理プリミティブ

活用シーン

  1. 01検索や順序付けに使うコレクションの選択
  2. 02所有権と内部可変性の型の選択
  3. 03ファイル I/O とイテレーターパイプラインの構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/full-stack-skills/rust-skills --skill rust-stdlib

インストール後、Claude Code で/rust-stdlibを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
examples/golden-stdlib/
Cargo.lock
Cargo.toml
examples/golden-stdlib/src/
lib.rs
references/
collections.md
interior-mutability.md
io-streams.md
iterators.md
option-result-combinators.md
process-and-fs.md
smart-pointers.md
std-concurrency.md
std-module-index.md
string-types.md

詳細

Rust 標準ライブラリ — API の選択と組み合わせ

権威ある参照先:Rust 標準ライブラリ — 標準的なリファレンスです。モジュールの全体像については、references/std-module-index.md を参照してください。

このスキルが扱うのは std API の選択と組み合わせです。どのコレクション、スマートポインター、文字列型、I/O トレイト、イテレーターパターンを使うかを扱います。言語のセマンティクス(rust-stable)、非同期ランタイム(rust-concurrency)、アプリケーション層の関心事(ドメインスキル)は扱いません。

対応範囲

✅ 得意分野
  1. 適切なコレクションの選択(HashMap と BTreeMap、Vec、VecDeque、LinkedList、BinaryHeap の比較)
  2. 適切なスマートポインターの選択(Box、Rc、Arc、RefCell、Mutex、OnceLock の比較)
  3. 適切な文字列型の選択(String、&str、OsString、PathBuf、Cow の比較)
  4. 内部可変性プリミティブの選択(Cell、RefCell、OnceCell、OnceLock、LazyLock の比較)
  5. Option/Result のコンビネーターをつなげた処理の設計(map、and_then、unwrap_or_else、ok_or、transpose)
  6. I/O トレイトの選択(Read、Write、BufRead、Seek、AsyncRead の比較)
  7. イテレーターパターンの選択(iter、into_iter、所有権を持つイテレーター、遅延評価と collect の比較)
  8. std の並行処理プリミティブの使用(thread、mpsc、barrier、Once、スコープ付きスレッド)
  9. 時刻 API の選択(Duration、Instant、SystemTime、TryFromFloat の比較)
  10. クロスプラットフォームのパス処理(Path と PathBuf、fs、env、process::Command)
⚠️ 前提条件
  1. Rust の所有権とライフタイム — rust-stable を参照
  2. Cargo とプロジェクト構成 — rust-cargo-build、rust-workspace を参照
❌ 対象外
  1. 非同期ランタイム(Tokio、async-std)→ rust-concurrency
  2. 言語のセマンティクス(所有権、トレイト、ライフタイム)→ rust-stable
  3. アプリケーション層の関心事(CLI、ウェブ、データベース)→ ドメインスキル
  4. Unsafe と FFI → rust-unsafe-ffi

データのプライバシー

このスキルは、ユーザーデータを収集、保存、送信しません。


パート 1:コレクション

判断ツリー

Need a collection?
│
├─ Key-value lookup?
│   ├─ Order doesn't matter, fast lookup → HashMap<K, V>
│   ├─ Need sorted iteration / range queries → BTreeMap<K, V>
│   └─ Tiny (<20 entries), linear scan OK → Vec<(K, V)> with .iter().find()
│
├─ Sequence?
│   ├─ Append/pop from end → Vec<T>
│   ├─ Push/pop from both ends → VecDeque<T>
│   ├─ Insert/remove from middle frequently → LinkedList<T> (rare; usually Vec is better)
│   └─ Priority queue / always-min-first → BinaryHeap<T>
│
├─ Set?
│   ├─ Fast membership, no order → HashSet<T>
│   └─ Sorted iteration → BTreeSet<T>
│
└─ No collection needed — use Vec<T>

クイックリファレンス

型順序検索挿入用途
Vec<T>挿入順値で O(n)、インデックスで O(1)push の償却 O(1)標準的なシーケンス
VecDeque<T>挿入順先頭/末尾で O(1)先頭/末尾で O(1)キュー、スライディングウィンドウ
LinkedList<T>挿入順O(n)カーソルを使えば任意の位置で O(1)ほとんど使いません。Vec を優先してください
BinaryHeap<T>優先度順先頭要素の参照で O(1)push/pop で O(log n)優先度付きキュー
HashMap<K,V>なし平均 O(1)平均 O(1)高速な検索、順序なし
BTreeMap<K,V>ソート済みO(log n)O(log n)順序付きキー、範囲検索
HashSet<T>なし平均 O(1)平均 O(1)要素の所属確認
BTreeSet<T>ソート済みO(log n)O(log n)ソート済み要素の所属確認

メモリー確保の挙動、ハッシャーの選択(BuildHasherDefault/FxHashMap)、Entry API のパターンについては、references/collections.md を参照してください。

Entry API — 二重検索を回避

use std::collections::HashMap;

let mut counts: HashMap<&str, u32> = HashMap::new();
for word in text.split_whitespace() {
    *counts.entry(word).or_insert(0) += 1;   // single hash, no double lookup
}

パート 2:スマートポインター

判断ツリー

Need shared/indirected ownership?
│
├─ Single owner, heap-allocated → Box<T>
│
├─ Multiple readers, single thread → Rc<T>
│   └─ Need to mutate through shared ref → Rc<RefCell<T>>
│
├─ Multiple readers, multiple threads → Arc<T>
│   └─ Need to mutate through shared ref → Arc<Mutex<T>> or Arc<RwLock<T>>
│
├─ Need lazy one-time init → OnceLock<T> (sync) or once_cell::Lazy
│
└─ Need interior mutability (no shared ownership)?
    ├─ Copy type, simple → Cell<T>
    ├─ Non-Copy, complex → RefCell<T> (single thread)
    └─ Multi-thread → Mutex<T> or RwLock<T>

クイックリファレンス

型所有権スレッドセーフ可変性用途
Box<T>単独はい直接(所有)ヒープ確保、再帰型
Rc<T>共有いいえ不変のみ参照カウント、シングルスレッド
Arc<T>共有はい不変のみアトミックな RC、マルチスレッド
Cell<T>単独いいえ内部(Copy のみ)単純な可変状態
RefCell<T>単独いいえ内部(実行時に借用を検査)共有参照を介した変更
Mutex<T>単独はい内部(ロック)共有可変状態、同期
RwLock<T>単独はい内部(読み書きロック)多数の読み取り、少数の書き込み
OnceLock<T>単独はい一度だけ初期化遅延初期化グローバル、std::sync::OnceLock
LazyLock<T>単独はい一度だけ初期化、透過的なデリファレンス定数に近いグローバル(Rust 1.80 以降)

トレードオフ、drop の順序、循環参照に使う Weak<T> については、references/smart-pointers.md を参照してください。


パート 3:文字列型

判断ツリー

Working with text?
│
├─ Function parameter → &str (always)
├─ Owned, mutable, UTF-8 → String
├─ Borrowed, UTF-8, with mixed owned/borrowed → Cow<'a, str>
├─ OS path (Windows/Unix native) → OsString (owned) / OsStr (borrowed)
├─ Filesystem path → PathBuf (owned) / Path (borrowed)
└─ Bytes that might not be UTF-8 → Vec<u8> / &[u8]

クイックリファレンス

種類エンコーディング所有するか用途
&strUTF-8いいえ関数のパラメーター、文字列リテラル
StringUTF-8はい所有する可変の UTF-8 テキスト
OsString/OsStrプラットフォームネイティブはい/いいえ環境変数、プロセス引数
PathBuf/Pathプラットフォームネイティブはい/いいえファイルシステムのパス
Cow<'a, str>UTF-8場合による可能な場合はゼロコピー、必要な場合は所有
Vec<u8>/&[u8]バイト列はい/いいえバイナリデータ、非 UTF-8

変換(.to_string() と .to_owned() と .into())、Cow の使い方、&str のスライスの安全性(is_char_boundary)については、references/string-types.md を参照してください。


パート 4:内部可変性

Cell、RefCell、OnceCell の比較

use std::cell::{Cell, RefCell, OnceCell};

// Cell: only for Copy types, no borrow checking
let counter = Cell::new(0);
counter.set(counter.get() + 1);

// RefCell: for non-Copy types, runtime borrow check (panics on double borrow)
let cache = RefCell::new(HashMap::new());
cache.borrow_mut().insert("k", 42);

// OnceCell: one-time initialization
static CONFIG: OnceCell<Config> = OnceCell::new();
let cfg = CONFIG.get_or_init(|| Config::load());
型Sync か用途
Cell<T>いいえCopy 型のみ、簡単な変更
RefCell<T>いいえCopy 以外の型、単一スレッド
OnceCell<T>いいえ1 回限りの遅延初期化
OnceLock<T>はい1 回限りの遅延初期化、マルチスレッド(std 1.70+)
LazyLock<T>はい透過的な遅延初期化(std 1.80+)

パニック安全性(RefCell の二重借用)、Cell と RefCell の選択、マルチスレッド向けの Atomic* については、references/interior-mutability.md を参照してください。


パート 5:Option と Result のコンビネーター

Option のコンビネーター

// map: transform inner value
name.map(|n| n.to_uppercase())                    // Option<String>

// and_then: chain fallible operations
id.and_then(|i| db.lookup(i))                     // Option<User>

// unwrap_or / unwrap_or_else: provide default
port.unwrap_or(8080)
port.unwrap_or_else(|| env::var("PORT").unwrap_or("8080").parse().unwrap())

// ok_or / ok_or_else: convert Option to Result
user.ok_or(Error::NotFound)?
user.ok_or_else(|| Error::UserMissing(id))?

// filter, is_some, is_some_and
age.filter(|&a| a >= 18)
opt.is_some_and(|x| x > 0)

// transpose: swap Option<Result> → Result<Option>
let x: Result<Option<i32>, _> = Some("5").parse::<i32>().map(Some);

Result のコンビネーター

// ? for propagation (prefer over explicit match)
fn load() -> Result<Config, Error> { Ok(parse(file_read()?)?) }

// map_err: convert error type
file_read().map_err(|e| Error::Io(e))?

// map: transform success value
parse(s).map(|n| n * 2)

// and_then: chain fallible
validate(input).and_then(process)

// or_else / or: fallback on error
primary.or_else(|_| fallback())

よく使われるパターン

パターンコード
パースを試み、デフォルト値にフォールバックするs.parse().unwrap_or(default)
エラー時に早期リターンするlet x = result?;
Option を Result に変換するopt.ok_or(Error::Missing)?
すべての Result を収集するresults.collect::<Result<Vec<_>, _>>()
すべて試し、最初に成功したものを返す`opts.into_iter().find_map(

コンビネーターの全一覧とリファクタリングのパターンについては、references/option-result-combinators.md を参照してください。


パート 6:I/O ストリーム

トレイト階層

Read ────┐
         ├─ BufRead (adds buffering, lines())
Write ───┘
Seek (random access)

選び方

必要なこと使用するもの
ソースからバイトを読み取るimpl Read(File、Cursor、stdin)
バッファー付きで読み取る(行、指定位置まで)impl BufRead(BufReader でラップ)
出力先にバイトを書き込むimpl Write(File、stdout、Vec)
ランダムアクセスimpl Seek(File)
非同期 I/Otokio::io::AsyncRead/AsyncWrite(rust-concurrency)
use std::io::{BufRead, BufReader, Read, Write};
use std::fs::File;

let f = File::open("log.txt")?;          // impl Read
let reader = BufReader::new(f);          // wrap for BufRead
for line in reader.lines() {             // BufRead::lines
    println!("{}", line?);
}

Cursor<Vec<u8>>、エラー処理(io::Result)、同期処理と非同期処理の変換については、references/io-streams.md を参照してください。


パート 7:イテレーター

選び方

必要なこと使用するもの
要素を借用する.iter() → Iterator<Item = &T>
可変借用する.iter_mut() → Iterator<Item = &mut T>
消費する.into_iter() → Iterator<Item = T>
インデックス付きのペア.iter().enumerate()
フィルターする.filter(|x| *x > 0)
変換する.map(|x| x * 2)
平坦化する.flat_map(|x| x.iter())
Vec に収集する.collect::<Vec<_>>()
HashMap に収集する.collect::<HashMap<_, _>>()((K, V) タプルから)
最初に一致するもの.find(|x| *x == 5)
いずれか/すべて.any(|x| *x > 0)、.all(|x| *x > 0)
グループ化/合計.sum::<i32>()、.product()、.fold(0, |a, b| a + b)
// Borrowed iteration is the default
let v = vec![1, 2, 3];
for x in &v { /* x: &i32 */ }      // .iter()
for x in &mut v { /* x: &mut i32 */ }
for x in v { /* x: i32, v consumed */ }

カスタムイテレーター(Iterator の実装)、遅延評価、ゼロコスト抽象化については、references/iterators.md を参照してください。


パート 8:標準ライブラリの並行処理

標準ライブラリはスレッド、チャネル、同期プリミティブを提供します。非同期処理については、rust-concurrency を参照してください。

スレッド

use std::thread;
use std::time::Duration;

let handle = thread::spawn(|| {
    thread::sleep(Duration::from_millis(500));
    "result"
});
let r = handle.join().unwrap();   // wait, get result

スコープ付きスレッド(Rust 1.63+)— 'static なしで借用

let mut data = vec![1, 2, 3];
thread::scope(|s| {
    s.spawn(|| { data[0] += 1; });
    s.spawn(|| { data[1] += 1; });
});   // all threads joined here; data borrow ends

mpsc チャネル

use std::sync::mpsc;
use std::thread;

let (tx, rx) = mpsc::channel();
thread::spawn(move || {
    tx.send(42).unwrap();
});
println!("{}", rx.recv().unwrap());

同期プリミティブ

プリミティブ用途
Mutex<T>排他ロック、同期的な内部可変性
RwLock<T>多数の読み取り、少数の書き込み
Arc<T>アトミックな参照カウント
Barrier複数スレッドを特定の地点で同期する
Once1 回限りの初期化
Condvar待機/通知
Atomic*(AtomicUsize、AtomicBool など)ロックフリーのカウンター、フラグ

Arc<Mutex<T>> のパターン、poison の回復、Tokio への移行タイミングについては、references/std-concurrency.md を参照してください。


パート 9:時間、パス、プロセス

時間

use std::time::{Duration, Instant, SystemTime};

let start = Instant::now();
expensive_op();
println!("took {:?}", start.elapsed());   // Duration

let five_secs = Duration::from_secs(5);
let mixed = Duration::new(5, 500_000_000);  // 5.5s

let now = SystemTime::now();
let since_epoch = now.duration_since(SystemTime::UNIX_EPOCH)?;
  • Duration — 時間の長さ(特定の時点ではありません)
  • Instant — 経過時間の測定に使う単調な時点
  • SystemTime — タイムスタンプ用の実時間(逆行することがあります!)

パス

use std::path::{Path, PathBuf};

let p = Path::new("/usr/bin/foo");
let stem = p.file_stem();      // "foo"
let ext = p.extension();       // "foo" → None; "foo.txt" → "txt"

let joined = PathBuf::from("/usr").join("bin").join("foo");
let parent = p.parent();       // "/usr/bin"

ファイルシステムのパスには、必ず Path/PathBuf を使用してください。String は使用しないでください。クロスプラットフォームで安全です。

プロセス

use std::process::Command;

let output = Command::new("ls")
    .arg("-l")
    .arg("/")
    .output()?;          // waits, returns Output
println!("{}", String::from_utf8_lossy(&output.stdout));

// Stream stdin/stdout
use std::process::Stdio;
let mut child = Command::new("cat")
    .stdin(Stdio::piped())
    .stdout(Stdio::piped())
    .spawn()?;

Command の終了コード、シグナル処理、fs モジュール(read、write、create_dir、メタデータ)については、references/process-and-fs.md を参照してください。


ワークフロー

  1. 必要なものを特定する — コレクション、ポインター、文字列、I/O、イテレーター、システムインターフェースのどれですか?
  2. 判断ツリーを適用する — 上記の該当するパートから選択します
  3. MSRV を確認する — 一部の API(OnceLock 1.70、LazyLock 1.80、スコープ付きスレッド 1.63)には、最近の stable が必要です
  4. コンビネーターで組み合わせる — 明示的な match よりも、Option/Result のチェーンを優先します
  5. 検証する — cargo check、cargo test、cargo clippy
  6. 引き継ぐ — 非同期ランタイム → rust-concurrency、unsafe → rust-unsafe-ffi、アプリケーション関連の課題 → ドメインスキル

判断の早見表

質問回答
デフォルトのコレクションは?Vec<T>
キーと値の検索が必要ですか?HashMap(順序なし)または BTreeMap(ソート済み)
所有権を共有しますか?Rc(単一スレッド)または Arc(マルチスレッド)
可変の共有状態が必要ですか?RefCell(単一スレッド)または Mutex/RwLock(マルチスレッド)
文字列パラメーターは?常に &str
ファイルパスは?Path/PathBuf
遅延初期化するグローバル変数は?OnceLock(1.70 以降)または LazyLock(1.80 以降)
借用して反復しますか?.iter()
両端キューは?VecDeque
優先度付きキューは?BinaryHeap

リソース

上流のソース

コメント