Skill v1.0.0
currentTrusted Publisher100/100version: "1.0.0" name: "rust-coding-skill" description: "Use whenever editing Rust in PET to write allocation-aware, cross-platform, byte-safe code with behavior-proving tests."
PET Rust Coding Skill
Use this alongside rust-locator-patterns. Priority order:
- Readable code with explicit invariants
- Correct cross-platform and concurrent behavior
- Measured performance improvements without duplicate work
Path Identity and Caches
Use Path/PathBuf for paths. Preserve the caller-facing path in reported values, but normalize cache and comparison keys with existing PET helpers such as norm_case.
A normalized key does not imply the cached value can expose the first caller's spelling:
let key = norm_case(path);let mut cached = cache.get(&key)?.clone();cached.prefix = Some(path.to_path_buf());
When adding or reviewing a path-keyed cache, check lookup, insert, remove, retain/prune, and state-sync paths. Add Windows coverage using equivalent separators or casing; do not test only the happy-path spelling.
Byte-Safe Parsing
Never calculate byte offsets from a transformed Unicode string and apply them to the original. Unicode case conversion can change byte length.
For ASCII wire/file markers, use byte-stable ASCII-insensitive matching and checked slicing:
let marker = b"# cmd:";let start = line.as_bytes().windows(marker.len()).position(|window| window.eq_ignore_ascii_case(marker))?+ marker.len();let value = line.get(start..)?.trim();
Use to_ascii_lowercase rather than to_lowercase when the format is defined as ASCII. Add a non-ASCII path regression test whenever offsets are derived from textual markers.
Hot-Path I/O and Allocations
Discovery runs frequently and in parallel. Before adding a cache, prove the repeated work and define invalidation. Within one operation, read immutable metadata once and pass borrowed snapshots through parsers.
- Prefer
&str/&[u8]over cloning content between parsers. - Prefer
rfind/iterator operations over collecting an intermediateVecjust to select one item. - Avoid
format!and Unicode case conversion in per-line loops when ASCII matching or direct writes suffice. - Do not claim an optimization is complete until every relevant call path is traced, including base/root environments and manager lookup.
- Do not emit the same warning, telemetry event, or report from both a pre-check and the worker path.
Error Handling and Locks
Library code should preserve typed information where repository APIs permit it. Prefer ?, let-else, and if let over broad fallbacks. Do not swallow filesystem errors when doing so can make stale cache data look valid.
Use contextual expect for poisoned locks in production code, matching the surrounding crate. Keep lock scopes short and never perform filesystem I/O or callbacks while holding a shared-state lock unless the design explicitly requires it.
Cross-Platform Semantics
- Use
#[cfg(...)]for platform-only code;cfg!does not prevent compilation. - Avoid
canonicalizefor Windows junction identity; use PET path helpers. - Treat both
/and\as separators when parsing user patterns, but only classify**as recursive when it is a complete path segment.foo**baris not a recursive segment. - Preserve original user-facing paths after normalized comparisons.
- Prefer raw string literals for regexes and backslash-heavy path examples to avoid malformed escapes.
- Before documenting or logging a recommended config value, trace how the consumer uses it. For example,
environmentDirectoriescontains directories that hold environments, not environment folders themselves.
Tests Must Prove the Change
Tests should demonstrate the behavior or performance invariant, not merely execute new lines.
For optimizations, instrument the dependency boundary and assert the operation count:
let reads = AtomicUsize::new(0);parse_with_reader(path, |_| {reads.fetch_add(1, Ordering::Relaxed);Some(history.clone())});assert_eq!(reads.load(Ordering::Relaxed), 1);
For parser helpers, include malformed input, non-ASCII surrounding data, and case variations. For diagnostics, test pattern classification and expansion filtering separately. Keep temp paths unique with tempfile or process/counter-based names.
Before every Rust commit, run targeted tests and invoke the rust-precommit skill. Keep that skill as the single source of truth for required format and Clippy commands.