Agent skill

rust-api-guidelines

Idiomatic Rust API design, naming, traits, error handling, and type safety. Use when writing or reviewing Rust code, designing library APIs, or implementing traits and error types.

Stars 1
Forks 0

Install this agent skill to your Project

npx add-skill https://github.com/PierreZ/claude-personal-skills/tree/main/skills/rust-api-guidelines

SKILL.md

Rust API Guidelines

Apply these rules when writing or reviewing Rust code. See REFERENCE.md for full details.

Top LLM Violations

# Guideline Wrong Right
1 C-COMMON-TRAITS No derives on public types #[derive(Debug, Clone, PartialEq)] minimum
2 C-QUESTION-MARK .unwrap() in lib/example code ? with Result return types
3 C-GENERIC fn f(v: &Vec<T>), fn f(s: &String) fn f(v: &[T]), fn f(s: &str)
4 C-GETTER fn get_name(&self) -> &str fn name(&self) -> &str
5 C-GOOD-ERR Result<T, ()>, Result<T, String> Domain error enum with thiserror
6 C-CONV Wrong conversion prefix See Conversion Naming below
7 C-DEREF Deref on wrapper types Only for smart pointers (Box, Arc)
8 C-STRUCT-BOUNDS struct Foo<T: Debug + Clone> struct Foo<T> — bounds on impl only
9 C-CALLER-CONTROL Hidden .clone(), wrong ownership Take owned when you need it, borrow when you don't
10 C-STRUCT-PRIVATE All pub fields on library structs Private fields + new() + getters
11 C-FAILURE No error docs # Errors, # Panics, # Safety sections
12 C-BUILDER Struct with 5+ pub config fields Builder: FooBuilder::new().bar(1).build()
13 C-NEWTYPE user_id: u64, timeout: u64 struct UserId(u64), struct Timeout(Duration)
14 C-CUSTOM-TYPE fn connect(use_tls: bool) enum TlsMode { Enabled, Disabled }
15 C-NEWTYPE-HIDE -> Enumerate<Skip<Map<...>>> -> impl Iterator<Item = T> or newtype

Conversion Naming

Prefix Cost Ownership Example
as_ Free &self -> &T fn as_str(&self) -> &str
to_ Expensive &self -> T (allocates) fn to_string(&self) -> String
into_ Variable self -> T (consumes) fn into_inner(self) -> T
from_ Variable T -> Self (constructs) fn from_bytes(v: Vec<u8>) -> Self

Trait Checklist

Type category Always derive When applicable
Public structs Debug, Clone Default, PartialEq, Eq, Hash
Error types Debug + manual Display + Error Clone, must be Send + Sync + 'static
ID / newtype Debug, Clone, Copy, PartialEq, Eq, Hash Display, Ord
Config / options Debug, Clone, Default PartialEq
API boundary types Debug, Clone, PartialEq, Serialize, Deserialize JsonSchema

Generic Parameters

Instead of Accept Why
&Vec<T> &[T] Works with arrays, slices, Vec
&String &str Works with literals, String, Cow
&Box<T> &T Box is transparent for borrows
String param impl Into<String> Accepts &str without caller .to_string()
PathBuf param impl AsRef<Path> Accepts &str, &Path, PathBuf
Vec<T> param impl IntoIterator<Item = T> Accepts arrays, slices, iterators

Type Design

  • Newtype IDs: #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(transparent)] pub struct JobId(pub Uuid);
  • Enum state machines: States as enum variants with embedded data. No struct-with-booleans/optionals.
  • Validated newtypes: Private fields + fn new(...) -> Result<Self, Error> + custom Deserialize that calls new.

Error Handling

  • Define domain error enums with #[derive(Debug, thiserror::Error)], specific variants with context fields.
  • With #[source], don't embed {err} in #[error("...")] — the error chain formatter appends it. Embedding causes double-printing.

Functions

  • Target 10-30 lines per function. Decompose longer functions into well-named helpers.
  • Value composition and testability: each function does one thing, returns a value, is independently testable.

Async / Tokio

Apply only to applications already using tokio. Libraries must not embed a runtime.

Pattern Rule
Event loop Single select! returning typed action enum, clean loop { let action = select().await; apply(action).await; }
Futurelock Never hold locks across select! branches. Use channels + spawn instead.
Cancel-safety scopeguard::guard() to restore invariants on drop. Defuse with ScopeGuard::into_inner() on success.
Channels Bounded mpsc (backpressure), oneshot (request-reply), watch (broadcast/cancel). Avoid unbounded mpsc.
Lock scope Clone data out of mutex before .await. Never hold MutexGuard across await points.

Clippy

  • Never add #[allow(clippy::...)] to suppress a Clippy warning. Fix the underlying issue instead.

Testing

  • Write tests before implementation. Use #[cfg(test)] mod tests in the same file.
  • Wrap external dependencies behind traits for testability. Ask the developer about the scope: IO boundaries only, all external deps, or full ports-and-adapters.

Full Reference

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results