rust について
rustは、ファイルデータ、サブプロセス、言語間インターフェースを扱うRustシステム向けの開発ガイドです。入力検証や決定的な動作、安全なRustを重視し、分野別の参照資料を用意しています。
主な機能
- 01ファイルデータ処理の指針
- 02サブプロセス連携パターン
- 03言語間データモデリング
- 04厳格な入力検証
- 05エラー処理と段階的な機能縮退
- 06テストと品質チェックリスト
活用シーン
- 01バージョン管理可能なファイル形式の設計
- 02サブプロセス出力の安全な処理
- 03UTF-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 システムを構築するためのパターンです。
基本理念
デフォルトでは慎重に:ファイル、サブプロセス、外部システムからの入力は信頼できないものとして扱います。
- 誤検出よりも見逃しを優先します
- 同じ入力 → 同じ出力(決定的)
- 不正な入力が原因でユーザーのマシン上でパニックを起こさないようにします
正規モデルの所有権:Rust を信頼できる情報源とする場合は、表現を分けて維持します。
| レイヤー | 目的 | 特徴 |
|---|---|---|
| 内部ドメイン | ビジネスロジック | 表現力の高い列挙型、豊富な型 |
| FFI DTO | 言語間の境界 | フラットで安定し、String が多い |
| ファイル形式 | 永続化 | バージョン管理され、往復変換が可能 |
| 外部入力 | 検証境界 | 厳密に検証し、決して信頼しない |
安全な Rust のみ:これらのパターンに unsafe は必要ありません。安全な抽象化を提供するエコシステムのクレートを使用します。
リファレンスガイド
該当する領域で作業する際は、関連するリファレンスを読み込みます。
| 領域 | リファレンス | 読み込むタイミング |
|---|---|---|
| データモデリング | 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]で文字列をスライスします(文字境界でパニックを起こします)- ディレクトリの列挙順が安定していると仮定します
- 検証せずにサブプロセスの出力を信頼します
unsafeを使用します(これらのパターンでは必要ありません)
このガイドで防げるバグ
| バグ | パターン | リファレンス |
|---|---|---|
| PID の再利用による「ゴーストセッション」 | プロセスの開始時刻を保存して検証する | process-integration.md |
| タイムスタンプの単位の不一致(秒とミリ秒) | 読み取り時に正規化する | process-integration.md |
| 切り詰め時の UTF-8 パニック | .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 |
変更チェックリスト
これらのシステムを変更する際は、以下を確認してください。
スキーマ/Serde
- 新しいフィールドでは
Optionと#[serde(default)]を使用している -
alias(読み込み時)またはrename(書き込み時)で古いフィールド名に対応している - 外部入力では
#[serde(deny_unknown_fields)]を使用している
並行処理
- 読み取り・変更・書き込みのサイクル全体を通して Mutex を保持している
- 共有状態では
thread_local!ではなくMutex<T>を使用している - ファイルロックを使用する場合は、プラットフォームごとの注意事項を記載している
堅牢性
- ファイル I/O エラーや解析エラーでパニックが発生しない
- 無視する前にエラーをログに記録している
- サブプロセスにタイムアウトを設定している
品質
-
cargo clippy -- -D warningsが成功する -
cargo fmt --checkが成功する - (正当な理由があり、監査済みの場合を除き)
unsafeブロックがない
コメント
Markdown 対応