{"id":"d75c5650-7fa3-4fcc-b3a8-4cd7fbe5ca6d","shortId":"3wbQnK","kind":"skill","title":"rust-best-practices","tagline":"Rust coding best practices based on Microsoft Pragmatic Rust Guidelines. ALWAYS invoke before writing or modifying Rust code. Covers error handling, API design, performance, and idiomatic patterns.","description":"# Rust Best Practices\n\nBased on Microsoft Pragmatic Rust Guidelines and Rust community standards.\n\n## Core Principles\n\n1. **Leverage the type system** — Use types to make invalid states unrepresentable\n2. **Embrace ownership** — Work with the borrow checker, not against it\n3. **Explicit over implicit** — Be clear about fallibility, mutability, and lifetimes\n4. **Zero-cost abstractions** — Use iterators, generics, and traits without runtime cost\n5. **Fail fast, recover gracefully** — Validate early, handle errors explicitly\n\n---\n\n## Error Handling\n\n### Use `thiserror` for Libraries\n```rust\nuse thiserror::Error;\n\n#[derive(Error, Debug)]\npub enum MyError {\n    #[error(\"IO error: {0}\")]\n    Io(#[from] std::io::Error),\n    #[error(\"Parse error at line {line}: {message}\")]\n    Parse { line: usize, message: String },\n    #[error(\"Not found: {0}\")]\n    NotFound(String),\n}\n```\n\n### Use `anyhow` for Applications\n```rust\nuse anyhow::{Context, Result};\n\nfn main() -> Result<()> {\n    let config = load_config()\n        .context(\"Failed to load configuration\")?;\n    run_app(config)?;\n    Ok(())\n}\n```\n\n### Never Panic in Libraries\n```rust\n// ❌ BAD\npub fn get_item(index: usize) -> &Item {\n    &self.items[index]  // Panics on out-of-bounds\n}\n\n// ✅ GOOD\npub fn get_item(&self, index: usize) -> Option<&Item> {\n    self.items.get(index)\n}\n\n// ✅ GOOD - when you need Result\npub fn get_item(&self, index: usize) -> Result<&Item, Error> {\n    self.items.get(index).ok_or(Error::NotFound(index))\n}\n```\n\n---\n\n## API Design\n\n### Use Builder Pattern for Complex Configs\n```rust\npub struct Client {\n    url: String,\n    timeout: Duration,\n    retries: u32,\n}\n\nimpl Client {\n    pub fn builder(url: impl Into<String>) -> ClientBuilder {\n        ClientBuilder {\n            url: url.into(),\n            timeout: Duration::from_secs(30),\n            retries: 3,\n        }\n    }\n}\n\npub struct ClientBuilder {\n    url: String,\n    timeout: Duration,\n    retries: u32,\n}\n\nimpl ClientBuilder {\n    pub fn timeout(mut self, timeout: Duration) -> Self {\n        self.timeout = timeout;\n        self\n    }\n\n    pub fn retries(mut self, retries: u32) -> Self {\n        self.retries = retries;\n        self\n    }\n\n    pub fn build(self) -> Client {\n        Client {\n            url: self.url,\n            timeout: self.timeout,\n            retries: self.retries,\n        }\n    }\n}\n```\n\n### Use Newtype Pattern\n```rust\n// ❌ BAD - primitive obsession\nfn create_user(name: String, email: String, age: u32) -> User { ... }\n\n// ✅ GOOD - newtype wrappers\npub struct Username(String);\npub struct Email(String);\npub struct Age(u32);\n\nimpl Email {\n    pub fn new(email: impl Into<String>) -> Result<Self, ValidationError> {\n        let email = email.into();\n        if email.contains('@') {\n            Ok(Self(email))\n        } else {\n            Err(ValidationError::InvalidEmail)\n        }\n    }\n}\n\nfn create_user(name: Username, email: Email, age: Age) -> User { ... }\n```\n\n### Accept `impl Trait` for Flexibility\n```rust\n// ❌ BAD - overly specific\npub fn process(items: Vec<String>) { ... }\n\n// ✅ GOOD - accept any iterable\npub fn process(items: impl IntoIterator<Item = impl AsRef<str>>) {\n    for item in items {\n        println!(\"{}\", item.as_ref());\n    }\n}\n```\n\n---\n\n## Performance\n\n### Avoid Unnecessary Clones\n```rust\n// ❌ BAD\nfn process(data: &String) {\n    let owned = data.clone();  // Unnecessary allocation\n    do_something(owned);\n}\n\n// ✅ GOOD\nfn process(data: &str) {\n    do_something(data);\n}\n```\n\n### Use `Cow` for Conditional Ownership\n```rust\nuse std::borrow::Cow;\n\nfn normalize(input: &str) -> Cow<'_, str> {\n    if input.contains(' ') {\n        Cow::Owned(input.replace(' ', \"_\"))\n    } else {\n        Cow::Borrowed(input)\n    }\n}\n```\n\n### Prefer Iterators Over Loops\n```rust\n// ❌ BAD\nlet mut result = Vec::new();\nfor item in items {\n    if item.is_valid() {\n        result.push(item.transform());\n    }\n}\n\n// ✅ GOOD\nlet result: Vec<_> = items\n    .into_iter()\n    .filter(|item| item.is_valid())\n    .map(|item| item.transform())\n    .collect();\n```\n\n---\n\n## Async Patterns\n\n### Use `tokio` Runtime\n```rust\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    tracing_subscriber::init();\n    run().await\n}\n```\n\n### Structured Concurrency with `JoinSet`\n```rust\nuse tokio::task::JoinSet;\n\nasync fn process_all(urls: Vec<String>) -> Vec<Result<Response, Error>> {\n    let mut set = JoinSet::new();\n\n    for url in urls {\n        set.spawn(async move {\n            fetch(&url).await\n        });\n    }\n\n    let mut results = Vec::new();\n    while let Some(res) = set.join_next().await {\n        results.push(res.unwrap());\n    }\n    results\n}\n```\n\n### Use `#[instrument]` for Tracing\n```rust\nuse tracing::instrument;\n\n#[instrument(skip(password))]\nasync fn login(username: &str, password: &str) -> Result<Token> {\n    tracing::info!(\"Attempting login\");\n    // ...\n}\n```\n\n---\n\n## Testing\n\n### Use `#[test]` and `proptest`\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use proptest::prelude::*;\n\n    #[test]\n    fn test_basic() {\n        assert_eq!(add(2, 2), 4);\n    }\n\n    proptest! {\n        #[test]\n        fn test_add_commutative(a: i32, b: i32) {\n            prop_assert_eq!(add(a, b), add(b, a));\n        }\n    }\n}\n```\n\n### Use `mockall` for Mocking\n```rust\n#[cfg_attr(test, mockall::automock)]\ntrait Database {\n    async fn get(&self, id: u64) -> Result<Record>;\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[tokio::test]\n    async fn test_with_mock() {\n        let mut mock = MockDatabase::new();\n        mock.expect_get()\n            .returning(|_| Ok(Record::default()));\n\n        let service = Service::new(mock);\n        assert!(service.process(1).await.is_ok());\n    }\n}\n```\n\n---\n\n## Common Anti-Patterns to Avoid\n\n| Anti-Pattern | Better Alternative |\n|-------------|-------------------|\n| `unwrap()` everywhere | `?` operator with proper error types |\n| `clone()` to satisfy borrow checker | Restructure code, use references |\n| `Box<dyn Error>` | Concrete error types with `thiserror` |\n| `String` for all text | `&str`, `Cow<str>`, or domain types |\n| Manual `Drop` for cleanup | RAII with struct destructors |\n| `unsafe` without justification | Safe abstractions first |\n| `Arc<Mutex<_>>` overuse | Message passing, channels |\n| Blocking in async context | `spawn_blocking` for CPU work |\n\n---\n\n## References\n\n- [Microsoft Pragmatic Rust Guidelines](https://microsoft.github.io/rust-guidelines/)\n- [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/)\n- [The Rust Book](https://doc.rust-lang.org/book/)","tags":["rust","best","practices","claude","arsenal","majiayu000","agent-skills","ai-agents","ai-coding-assistant","automation","claude-code","code-review"],"capabilities":["skill","source-majiayu000","skill-rust-best-practices","topic-agent-skills","topic-ai-agents","topic-ai-coding-assistant","topic-automation","topic-claude","topic-claude-code","topic-code-review","topic-developer-tools","topic-devops","topic-productivity","topic-prompt-engineering","topic-python"],"categories":["claude-arsenal"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/majiayu000/claude-arsenal/rust-best-practices","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add majiayu000/claude-arsenal","source_repo":"https://github.com/majiayu000/claude-arsenal","install_from":"skills.sh"}},"qualityScore":"0.464","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 29 github stars · SKILL.md body (6,548 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-01T07:01:15.943Z","embedding":null,"createdAt":"2026-04-18T22:24:24.658Z","updatedAt":"2026-05-01T07:01:15.943Z","lastSeenAt":"2026-05-01T07:01:15.943Z","tsv":"'/api-guidelines/)':765 '/book/)':771 '/rust-guidelines/)':759 '0':123,144 '1':47,678 '2':59,606,607 '3':70,263 '30':261 '4':81,608 '5':94 'abstract':85,735 'accept':374,389 'add':605,613,622,625 'age':323,339,371,372 'alloc':422 'altern':691 'alway':15 'anti':683,688 'anti-pattern':682,687 'anyhow':148,153,505 'api':26,227,761 'app':169 'applic':150 'arc':737 'asref':400 'assert':603,620,676 'async':494,502,521,541,572,640,655,745 'attempt':582 'attr':634 'automock':637 'avoid':409,686 'await':511,545,557 'await.is':679 'b':617,624,626 'bad':177,313,380,413,464 'base':9,35 'basic':602 'best':3,7,33 'better':690 'block':743,748 'book':768 'borrow':65,442,457,702 'bound':192 'box':708 'build':299 'builder':230,249 'cfg':590,633,647 'channel':742 'checker':66,703 'cleanup':726 'clear':75 'client':238,246,301,302 'clientbuild':253,254,266,274 'clone':411,699 'code':6,22,705 'collect':493 'common':681 'communiti':43 'commut':614 'complex':233 'concret':709 'concurr':513 'condit':437 'config':160,162,170,234 'configur':167 'context':154,163,746 'core':45 'cost':84,93 'cover':23 'cow':435,443,448,452,456,719 'cpu':750 'creat':317,365 'data':416,429,433 'data.clone':420 'databas':639 'debug':116 'default':670 'deriv':114 'design':27,228 'destructor':730 'doc.rust-lang.org':770 'doc.rust-lang.org/book/)':769 'domain':721 'drop':724 'durat':242,258,270,281 'earli':100 'els':360,455 'email':321,335,342,346,353,359,369,370 'email.contains':356 'email.into':354 'embrac':60 'enum':118 'eq':604,621 'err':361 'error':24,102,104,113,115,120,122,128,129,131,141,219,224,530,697,710 'everywher':693 'explicit':71,103 'fail':95,164 'fallibl':77 'fast':96 'fetch':543 'filter':486 'first':736 'flexibl':378 'fn':156,179,195,211,248,276,287,298,316,344,364,384,393,414,427,444,503,522,573,600,611,641,656 'found':143 'generic':88 'get':180,196,212,642,666 'good':193,205,326,388,426,479 'grace':98 'guidelin':14,40,756,762 'handl':25,101,105 'i32':616,618 'id':644 'idiomat':30 'impl':245,251,273,341,347,375,396,399 'implicit':73 'index':182,186,199,204,215,221,226 'info':581 'init':509 'input':446,458 'input.contains':451 'input.replace':454 'instrument':562,568,569 'intoiter':397 'invalid':56 'invalidemail':363 'invok':16 'io':121,124,127 'item':181,184,197,202,213,218,386,395,398,402,404,471,473,483,487,491 'item.as':406 'item.is':475,488 'item.transform':478,492 'iter':87,391,460,485 'joinset':515,520,534 'justif':733 'let':159,352,418,465,480,531,546,552,660,671 'leverag':48 'librari':109,175 'lifetim':80 'line':133,134,137 'load':161,166 'login':574,583 'loop':462 'main':157,501,504 'make':55 'manual':723 'map':490 'messag':135,139,740 'microsoft':11,37,753 'microsoft.github.io':758 'microsoft.github.io/rust-guidelines/)':757 'mock':631,659,662,675 'mock.expect':665 'mockal':629,636 'mockdatabas':663 'mod':592,649 'modifi':20 'move':542 'mut':278,289,466,532,547,661 'mutabl':78 'mutex':738 'myerror':119 'name':319,367 'need':208 'never':172 'new':345,469,535,550,664,674 'newtyp':310,327 'next':556 'normal':445 'notfound':145,225 'obsess':315 'ok':171,222,357,668,680 'oper':694 'option':201 'out-of-bound':189 'over':381 'overus':739 'own':419,425,453 'ownership':61,438 'panic':173,187 'pars':130,136 'pass':741 'password':571,577 'pattern':31,231,311,495,684,689 'perform':28,408 'practic':4,8,34 'pragmat':12,38,754 'prefer':459 'prelud':598 'primit':314 'principl':46 'println':405 'process':385,394,415,428,523 'prop':619 'proper':696 'proptest':588,597,609 'pub':117,178,194,210,236,247,264,275,286,297,329,333,337,343,383,392 'raii':727 'record':669 'recov':97 'ref':407 'refer':707,752 'res':554 'res.unwrap':559 'respons':529 'restructur':704 'result':155,158,209,217,349,467,481,506,528,548,560,579,646 'result.push':477 'results.push':558 'retri':243,262,271,288,291,295,307 'return':667 'run':168,510 'runtim':92,498 'rust':2,5,13,21,32,39,42,110,151,176,235,312,379,412,439,463,499,516,565,589,632,755,760,767 'rust-best-practic':1 'rust-lang.github.io':764 'rust-lang.github.io/api-guidelines/)':763 'safe':734 'satisfi':701 'sec':260 'self':198,214,279,282,285,290,293,296,300,350,358,643 'self.items':185 'self.items.get':203,220 'self.retries':294,308 'self.timeout':283,306 'self.url':304 'servic':672,673 'service.process':677 'set':533 'set.join':555 'set.spawn':540 'skill' 'skill-rust-best-practices' 'skip':570 'someth':424,432 'source-majiayu000' 'spawn':747 'specif':382 'standard':44 'state':57 'std':126,441 'str':430,447,449,576,578,718 'string':140,146,240,268,320,322,332,336,417,714 'struct':237,265,330,334,338,729 'structur':512 'subscrib':508 'super':595,652 'system':51 'task':519 'test':584,586,591,593,599,601,610,612,635,648,650,654,657 'text':717 'thiserror':107,112,713 'timeout':241,257,269,277,280,284,305 'tokio':497,500,518,653 'topic-agent-skills' 'topic-ai-agents' 'topic-ai-coding-assistant' 'topic-automation' 'topic-claude' 'topic-claude-code' 'topic-code-review' 'topic-developer-tools' 'topic-devops' 'topic-productivity' 'topic-prompt-engineering' 'topic-python' 'trace':507,564,567,580 'trait':90,376,638 'type':50,53,698,711,722 'u32':244,272,292,324,340 'u64':645 'unnecessari':410,421 'unrepresent':58 'unsaf':731 'unwrap':692 'url':239,250,255,267,303,525,537,539,544 'url.into':256 'use':52,86,106,111,147,152,229,309,434,440,496,517,561,566,585,594,596,628,651,706 'user':318,325,366,373 'usernam':331,368,575 'usiz':138,183,200,216 'valid':99,476,489 'validationerror':351,362 'vec':387,468,482,526,527,549 'without':91,732 'work':62,751 'wrapper':328 'write':18 'zero':83 'zero-cost':82","prices":[{"id":"52528ff8-bfd7-46c2-9a67-19254f37fafd","listingId":"d75c5650-7fa3-4fcc-b3a8-4cd7fbe5ca6d","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"majiayu000","category":"claude-arsenal","install_from":"skills.sh"},"createdAt":"2026-04-18T22:24:24.658Z"}],"sources":[{"listingId":"d75c5650-7fa3-4fcc-b3a8-4cd7fbe5ca6d","source":"github","sourceId":"majiayu000/claude-arsenal/rust-best-practices","sourceUrl":"https://github.com/majiayu000/claude-arsenal/tree/main/skills/rust-best-practices","isPrimary":false,"firstSeenAt":"2026-04-18T22:24:24.658Z","lastSeenAt":"2026-05-01T07:01:15.943Z"}],"details":{"listingId":"d75c5650-7fa3-4fcc-b3a8-4cd7fbe5ca6d","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"majiayu000","slug":"rust-best-practices","github":{"repo":"majiayu000/claude-arsenal","stars":29,"topics":["agent-skills","ai-agents","ai-coding-assistant","automation","claude","claude-code","code-review","developer-tools","devops","productivity","prompt-engineering","python","software-development","typescript","workflows"],"license":"mit","html_url":"https://github.com/majiayu000/claude-arsenal","pushed_at":"2026-04-29T04:12:22Z","description":"52 production-ready Claude Code skills and 7 specialized agents for software development, DevOps, product workflows, and automation.","skill_md_sha":"5f1da0706fb8dc944048fc04f5d8b8237c953c0a","skill_md_path":"skills/rust-best-practices/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/majiayu000/claude-arsenal/tree/main/skills/rust-best-practices"},"layout":"multi","source":"github","category":"claude-arsenal","frontmatter":{"name":"rust-best-practices","description":"Rust coding best practices based on Microsoft Pragmatic Rust Guidelines. ALWAYS invoke before writing or modifying Rust code. Covers error handling, API design, performance, and idiomatic patterns."},"skills_sh_url":"https://skills.sh/majiayu000/claude-arsenal/rust-best-practices"},"updatedAt":"2026-05-01T07:01:15.943Z"}}