agy-superpowers 5.2.2 → 5.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/rules/CLAUDE.md +80 -0
  4. package/template/agent/rules/code-styles.md +31 -32
  5. package/template/agent/rules/debug-confirmation-policy.md +2 -0
  6. package/template/agent/rules/file-length-policy.md +2 -0
  7. package/template/agent/rules/git-policy.md +7 -0
  8. package/template/agent/rules/language-matching.md +2 -0
  9. package/template/agent/rules/scratch-scripts.md +39 -0
  10. package/template/agent/rules/superpowers.md +8 -51
  11. package/template/agent/skills/executing-plans/SKILL.md +17 -0
  12. package/template/agent/skills/systematic-debugging/SKILL.md +16 -0
  13. package/template/agent/skills/test-driven-development/SKILL.md +16 -0
  14. package/template/agent/skills/verification-before-completion/SKILL.md +22 -0
  15. package/template/agent/skills/writing-plans/SKILL.md +16 -0
  16. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  17. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  18. package/template/agent/skills/api-design/SKILL.md +0 -193
  19. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  20. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  21. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  22. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  23. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  24. package/template/agent/skills/community-manager/SKILL.md +0 -115
  25. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  26. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  27. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  28. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  29. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  30. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  31. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  32. package/template/agent/skills/game-design/SKILL.md +0 -194
  33. package/template/agent/skills/game-developer/SKILL.md +0 -175
  34. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  35. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  36. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  37. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  38. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  39. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  40. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  41. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  42. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  43. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  44. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  45. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  46. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  47. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  48. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  49. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  50. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  53. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  54. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  55. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  56. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  57. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  58. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  59. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  60. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  61. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  62. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  63. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  64. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  65. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  68. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  69. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  70. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  71. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  72. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  73. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  74. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  75. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  76. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  77. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  78. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  79. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  80. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  83. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  84. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  85. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  86. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  87. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  88. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  89. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  90. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  91. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  92. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  93. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  94. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  95. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  96. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  97. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  98. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  99. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  100. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  101. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  102. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  103. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  104. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  105. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  106. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  107. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  108. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  109. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  110. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  111. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  112. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  113. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  114. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  115. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  116. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  117. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  118. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  119. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  120. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  121. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  122. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  123. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  124. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  125. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  126. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  127. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  128. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  129. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  132. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  133. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  134. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  135. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  136. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  137. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  138. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  139. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  140. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  141. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  142. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  143. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  144. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  148. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  149. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  150. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  151. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  152. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  153. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  154. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  155. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  156. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  157. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  158. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  159. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  160. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  161. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  162. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  163. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  164. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  165. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  166. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  167. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  168. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  169. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  170. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  171. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  172. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  173. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  174. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  175. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  176. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  177. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  178. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  179. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  180. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  181. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  182. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  183. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  184. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  185. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  186. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  187. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  188. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  189. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  190. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  191. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  192. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  193. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  194. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  195. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  196. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  197. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  198. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  199. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  200. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  201. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  202. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  203. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  204. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  205. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  206. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  207. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  208. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  209. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  210. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  211. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  212. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  213. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  214. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  215. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  216. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  217. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  218. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  219. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  220. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  221. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  222. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  223. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  224. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  225. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  226. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  227. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  228. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  229. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  230. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  231. package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
@@ -1,160 +0,0 @@
1
- # type-newtype-ids
2
-
3
- > Wrap IDs in newtypes: `UserId(u64)`
4
-
5
- ## Why It Matters
6
-
7
- Using raw integers for IDs is error-prone. It's easy to accidentally pass a `user_id` where a `post_id` is expected. Newtypes make these mix-ups compile-time errors instead of runtime bugs.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- fn get_user_posts(user_id: u64, post_id: u64) -> Vec<Post> {
13
- // Which is which? Easy to swap by accident
14
- }
15
-
16
- // Oops! Arguments swapped - compiles fine, wrong at runtime
17
- let posts = get_user_posts(post_id, user_id);
18
-
19
- // Even worse with multiple IDs
20
- fn transfer(from: u64, to: u64, amount: u64) {
21
- // from/to can easily be swapped
22
- }
23
- ```
24
-
25
- ## Good
26
-
27
- ```rust
28
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
29
- pub struct UserId(pub u64);
30
-
31
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
32
- pub struct PostId(pub u64);
33
-
34
- fn get_user_posts(user_id: UserId, post_id: PostId) -> Vec<Post> {
35
- // Types are distinct
36
- }
37
-
38
- // This won't compile - types don't match
39
- // let posts = get_user_posts(post_id, user_id); // ERROR!
40
-
41
- // Correct usage
42
- let posts = get_user_posts(UserId(1), PostId(42));
43
- ```
44
-
45
- ## Derive Common Traits
46
-
47
- ```rust
48
- #[derive(
49
- Debug, // For printing
50
- Clone, // For copying
51
- Copy, // For implicit copies (if small)
52
- PartialEq, // For == comparison
53
- Eq, // For HashMap keys
54
- Hash, // For HashMap keys
55
- PartialOrd, // For sorting (optional)
56
- Ord, // For BTreeMap keys (optional)
57
- )]
58
- pub struct UserId(pub u64);
59
- ```
60
-
61
- ## Add Useful Methods
62
-
63
- ```rust
64
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
65
- pub struct UserId(u64);
66
-
67
- impl UserId {
68
- pub const fn new(id: u64) -> Self {
69
- Self(id)
70
- }
71
-
72
- pub const fn get(self) -> u64 {
73
- self.0
74
- }
75
-
76
- // For database queries
77
- pub fn as_i64(self) -> i64 {
78
- self.0 as i64
79
- }
80
- }
81
-
82
- impl From<u64> for UserId {
83
- fn from(id: u64) -> Self {
84
- Self(id)
85
- }
86
- }
87
-
88
- impl std::fmt::Display for UserId {
89
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90
- write!(f, "user:{}", self.0)
91
- }
92
- }
93
- ```
94
-
95
- ## With Serde
96
-
97
- ```rust
98
- use serde::{Deserialize, Serialize};
99
-
100
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
101
- #[serde(transparent)] // Serializes as just the inner value
102
- pub struct UserId(pub u64);
103
-
104
- // JSON: {"user_id": 123} not {"user_id": {"0": 123}}
105
- ```
106
-
107
- ## String IDs (UUIDs, etc.)
108
-
109
- ```rust
110
- #[derive(Debug, Clone, PartialEq, Eq, Hash)]
111
- pub struct SessionId(String);
112
-
113
- impl SessionId {
114
- pub fn new() -> Self {
115
- Self(uuid::Uuid::new_v4().to_string())
116
- }
117
-
118
- pub fn parse(s: &str) -> Result<Self, ParseError> {
119
- // Validate format
120
- uuid::Uuid::parse_str(s)?;
121
- Ok(Self(s.to_string()))
122
- }
123
-
124
- pub fn as_str(&self) -> &str {
125
- &self.0
126
- }
127
- }
128
- ```
129
-
130
- ## Multiple Related IDs
131
-
132
- ```rust
133
- // Macro for consistent ID types
134
- macro_rules! define_id {
135
- ($name:ident) => {
136
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
137
- pub struct $name(pub u64);
138
-
139
- impl $name {
140
- pub const fn new(id: u64) -> Self { Self(id) }
141
- pub const fn get(self) -> u64 { self.0 }
142
- }
143
-
144
- impl From<u64> for $name {
145
- fn from(id: u64) -> Self { Self(id) }
146
- }
147
- };
148
- }
149
-
150
- define_id!(UserId);
151
- define_id!(PostId);
152
- define_id!(CommentId);
153
- define_id!(TeamId);
154
- ```
155
-
156
- ## See Also
157
-
158
- - [api-newtype-safety](api-newtype-safety.md) - Newtypes for type safety
159
- - [type-newtype-validated](type-newtype-validated.md) - Newtypes for validated data
160
- - [api-parse-dont-validate](api-parse-dont-validate.md) - Parse into validated types
@@ -1,159 +0,0 @@
1
- # type-newtype-validated
2
-
3
- > Use newtypes to enforce validation at construction time
4
-
5
- ## Why It Matters
6
-
7
- A validated newtype guarantees its inner value is always valid. Once you have an `Email`, you know it passed validation—no re-checking needed. This "parse, don't validate" pattern catches errors at boundaries and makes invalid states unrepresentable.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Validation scattered throughout code
13
- fn send_email(to: &str, body: &str) -> Result<(), Error> {
14
- if !is_valid_email(to) { // Must check every time
15
- return Err(Error::InvalidEmail);
16
- }
17
- // ...
18
- }
19
-
20
- fn add_recipient(list: &mut Vec<String>, email: &str) -> Result<(), Error> {
21
- if !is_valid_email(email) { // Check again
22
- return Err(Error::InvalidEmail);
23
- }
24
- list.push(email.to_string());
25
- Ok(())
26
- }
27
- ```
28
-
29
- ## Good
30
-
31
- ```rust
32
- #[derive(Debug, Clone, PartialEq, Eq, Hash)]
33
- pub struct Email(String);
34
-
35
- impl Email {
36
- pub fn new(s: &str) -> Result<Self, EmailError> {
37
- if is_valid_email(s) {
38
- Ok(Email(s.to_string()))
39
- } else {
40
- Err(EmailError::Invalid(s.to_string()))
41
- }
42
- }
43
-
44
- pub fn as_str(&self) -> &str {
45
- &self.0
46
- }
47
- }
48
-
49
- // No validation needed - Email is always valid
50
- fn send_email(to: &Email, body: &str) -> Result<(), Error> {
51
- // to is guaranteed valid
52
- send_to_address(to.as_str(), body)
53
- }
54
-
55
- fn add_recipient(list: &mut Vec<Email>, email: Email) {
56
- // email is guaranteed valid
57
- list.push(email);
58
- }
59
- ```
60
-
61
- ## Common Validated Types
62
-
63
- ```rust
64
- // URLs
65
- pub struct Url(url::Url);
66
-
67
- impl Url {
68
- pub fn parse(s: &str) -> Result<Self, UrlError> {
69
- url::Url::parse(s)
70
- .map(Url)
71
- .map_err(UrlError::from)
72
- }
73
- }
74
-
75
- // Non-empty strings
76
- pub struct NonEmptyString(String);
77
-
78
- impl NonEmptyString {
79
- pub fn new(s: String) -> Option<Self> {
80
- if s.is_empty() {
81
- None
82
- } else {
83
- Some(NonEmptyString(s))
84
- }
85
- }
86
- }
87
-
88
- // Positive numbers
89
- pub struct PositiveI32(i32);
90
-
91
- impl PositiveI32 {
92
- pub fn new(n: i32) -> Option<Self> {
93
- if n > 0 {
94
- Some(PositiveI32(n))
95
- } else {
96
- None
97
- }
98
- }
99
-
100
- pub fn get(&self) -> i32 {
101
- self.0
102
- }
103
- }
104
-
105
- // Bounded ranges
106
- pub struct Percentage(f64);
107
-
108
- impl Percentage {
109
- pub fn new(value: f64) -> Result<Self, RangeError> {
110
- if (0.0..=100.0).contains(&value) {
111
- Ok(Percentage(value))
112
- } else {
113
- Err(RangeError::OutOfBounds)
114
- }
115
- }
116
- }
117
- ```
118
-
119
- ## With Serde
120
-
121
- ```rust
122
- use serde::{Deserialize, Serialize};
123
-
124
- #[derive(Debug, Clone, Serialize)]
125
- pub struct Email(String);
126
-
127
- impl<'de> Deserialize<'de> for Email {
128
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
129
- where
130
- D: serde::Deserializer<'de>,
131
- {
132
- let s = String::deserialize(deserializer)?;
133
- Email::new(&s).map_err(serde::de::Error::custom)
134
- }
135
- }
136
-
137
- // JSON deserialization automatically validates
138
- let email: Email = serde_json::from_str(r#""user@example.com""#)?;
139
- ```
140
-
141
- ## Compile-Time Validation
142
-
143
- ```rust
144
- // For values known at compile time
145
- macro_rules! email {
146
- ($s:literal) => {{
147
- const _: () = assert!(is_valid_email_const($s));
148
- Email::new_unchecked($s)
149
- }};
150
- }
151
-
152
- let admin = email!("admin@example.com"); // Validated at compile time
153
- ```
154
-
155
- ## See Also
156
-
157
- - [api-parse-dont-validate](./api-parse-dont-validate.md) - Parse at boundaries
158
- - [api-newtype-safety](./api-newtype-safety.md) - Type-safe distinctions
159
- - [type-newtype-ids](./type-newtype-ids.md) - ID newtypes
@@ -1,144 +0,0 @@
1
- # type-no-stringly
2
-
3
- > Avoid stringly-typed APIs; use enums, newtypes, or validated types
4
-
5
- ## Why It Matters
6
-
7
- Strings accept any value—typos, wrong formats, invalid data all compile fine. Enums, newtypes, and validated types catch errors at compile time or construction time, not runtime. They also provide better IDE support, documentation, and make invalid states unrepresentable.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Status as string - easy to get wrong
13
- fn set_status(status: &str) {
14
- match status {
15
- "pending" => { ... }
16
- "active" => { ... }
17
- "completed" => { ... }
18
- _ => panic!("Unknown status"), // Runtime error
19
- }
20
- }
21
-
22
- // Easy to misuse
23
- set_status("pending"); // OK
24
- set_status("Pending"); // Runtime error - wrong case
25
- set_status("aktive"); // Runtime error - typo
26
- set_status("done"); // Runtime error - wrong word
27
-
28
- // Configuration as strings
29
- fn configure(key: &str, value: &str) {
30
- // No type safety, no validation
31
- }
32
- ```
33
-
34
- ## Good
35
-
36
- ```rust
37
- // Status as enum - compile-time safety
38
- enum Status {
39
- Pending,
40
- Active,
41
- Completed,
42
- }
43
-
44
- fn set_status(status: Status) {
45
- match status {
46
- Status::Pending => { ... }
47
- Status::Active => { ... }
48
- Status::Completed => { ... }
49
- } // Exhaustive - compiler checks all cases
50
- }
51
-
52
- // Can only pass valid values
53
- set_status(Status::Pending); // OK
54
- set_status(Status::Aktivev); // Compile error - typo caught!
55
-
56
- // Configuration with typed builder
57
- struct Config {
58
- timeout: Duration,
59
- retries: u32,
60
- mode: Mode,
61
- }
62
-
63
- enum Mode { Fast, Safe, Balanced }
64
- ```
65
-
66
- ## Parsing at Boundaries
67
-
68
- ```rust
69
- use std::str::FromStr;
70
-
71
- #[derive(Debug, Clone, Copy)]
72
- enum Priority {
73
- Low,
74
- Medium,
75
- High,
76
- }
77
-
78
- impl FromStr for Priority {
79
- type Err = ParseError;
80
-
81
- fn from_str(s: &str) -> Result<Self, Self::Err> {
82
- match s.to_lowercase().as_str() {
83
- "low" => Ok(Priority::Low),
84
- "medium" | "med" => Ok(Priority::Medium),
85
- "high" => Ok(Priority::High),
86
- _ => Err(ParseError::UnknownPriority(s.to_string())),
87
- }
88
- }
89
- }
90
-
91
- // Parse once at boundary
92
- fn handle_request(priority_str: &str) -> Result<(), Error> {
93
- let priority: Priority = priority_str.parse()?;
94
- // From here, priority is type-safe
95
- process(priority);
96
- Ok(())
97
- }
98
- ```
99
-
100
- ## Validated Newtypes
101
-
102
- ```rust
103
- // Instead of string for email
104
- struct Email(String);
105
-
106
- impl Email {
107
- fn new(s: &str) -> Result<Self, ValidationError> {
108
- if is_valid_email(s) {
109
- Ok(Email(s.to_string()))
110
- } else {
111
- Err(ValidationError::InvalidEmail)
112
- }
113
- }
114
- }
115
-
116
- // Instead of string for UUID
117
- struct UserId(uuid::Uuid);
118
-
119
- // Instead of string for paths
120
- struct ConfigPath(PathBuf);
121
- ```
122
-
123
- ## With Serde
124
-
125
- ```rust
126
- use serde::{Deserialize, Serialize};
127
-
128
- #[derive(Debug, Serialize, Deserialize)]
129
- #[serde(rename_all = "snake_case")]
130
- enum EventType {
131
- UserCreated,
132
- UserDeleted,
133
- UserUpdated,
134
- }
135
-
136
- // JSON: {"type": "user_created", ...}
137
- // Automatically validated during deserialization
138
- ```
139
-
140
- ## See Also
141
-
142
- - [anti-stringly-typed](./anti-stringly-typed.md) - Anti-pattern details
143
- - [type-newtype-validated](./type-newtype-validated.md) - Validated newtypes
144
- - [type-enum-states](./type-enum-states.md) - Enums for states
@@ -1,137 +0,0 @@
1
- # type-option-nullable
2
-
3
- > Use `Option<T>` for values that might not exist
4
-
5
- ## Why It Matters
6
-
7
- `Option<T>` explicitly represents "value or nothing" in the type system. Unlike null pointers or sentinel values, you can't accidentally use a missing value—the compiler forces you to handle the `None` case. This eliminates null pointer exceptions at compile time.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Sentinel values - easy to forget to check
13
- fn find_user(id: u64) -> User {
14
- // Returns "empty" user if not found - caller might not check
15
- users.get(&id).cloned().unwrap_or(User::empty())
16
- }
17
-
18
- // Nullable-style with raw pointers
19
- fn find_user(id: u64) -> *const User {
20
- // Null if not found - unsafe, no compiler help
21
- }
22
-
23
- // Error-prone usage
24
- let user = find_user(42);
25
- println!("{}", user.name); // Might be empty user - silent bug
26
- ```
27
-
28
- ## Good
29
-
30
- ```rust
31
- // Option makes absence explicit
32
- fn find_user(id: u64) -> Option<User> {
33
- users.get(&id).cloned()
34
- }
35
-
36
- // Must handle the None case
37
- let user = find_user(42);
38
- match user {
39
- Some(u) => println!("{}", u.name),
40
- None => println!("User not found"),
41
- }
42
-
43
- // Or use combinators
44
- let name = find_user(42)
45
- .map(|u| u.name)
46
- .unwrap_or_else(|| "Unknown".to_string());
47
- ```
48
-
49
- ## Common Option Patterns
50
-
51
- ```rust
52
- // if let for single case
53
- if let Some(user) = find_user(id) {
54
- process(user);
55
- }
56
-
57
- // Chaining with map
58
- let upper_name = find_user(id)
59
- .map(|u| u.name)
60
- .map(|n| n.to_uppercase());
61
-
62
- // Providing defaults
63
- let user = find_user(id).unwrap_or_default();
64
- let user = find_user(id).unwrap_or_else(|| User::guest());
65
-
66
- // ? operator for propagation
67
- fn get_user_email(id: u64) -> Option<String> {
68
- let user = find_user(id)?;
69
- Some(user.email)
70
- }
71
-
72
- // and_then for chained optionals
73
- fn get_user_country(id: u64) -> Option<String> {
74
- find_user(id)
75
- .and_then(|u| u.address)
76
- .and_then(|a| a.country)
77
- }
78
- ```
79
-
80
- ## Struct Fields
81
-
82
- ```rust
83
- struct User {
84
- name: String,
85
- email: String,
86
- phone: Option<String>, // Optional field
87
- avatar_url: Option<Url>, // Optional field
88
- }
89
-
90
- impl User {
91
- fn display_phone(&self) -> &str {
92
- self.phone.as_deref().unwrap_or("Not provided")
93
- }
94
- }
95
- ```
96
-
97
- ## Option vs Result
98
-
99
- ```rust
100
- // Option: value might not exist (no error context)
101
- fn find(key: &str) -> Option<Value> { ... }
102
-
103
- // Result: operation might fail (with error context)
104
- fn parse(input: &str) -> Result<Value, ParseError> { ... }
105
-
106
- // Convert Option to Result
107
- let value = find("key").ok_or(Error::NotFound)?;
108
-
109
- // Convert Result to Option
110
- let value = parse("input").ok(); // Discards error
111
- ```
112
-
113
- ## Option References
114
-
115
- ```rust
116
- // Option<&T> for optional borrows
117
- fn get(&self, key: &str) -> Option<&Value> {
118
- self.map.get(key)
119
- }
120
-
121
- // as_ref() to borrow Option contents
122
- let opt: Option<String> = Some("hello".to_string());
123
- let opt_ref: Option<&String> = opt.as_ref();
124
- let opt_str: Option<&str> = opt.as_deref();
125
-
126
- // as_mut() for mutable borrow
127
- let mut opt = Some(vec![1, 2, 3]);
128
- if let Some(v) = opt.as_mut() {
129
- v.push(4);
130
- }
131
- ```
132
-
133
- ## See Also
134
-
135
- - [type-result-fallible](./type-result-fallible.md) - Result for errors
136
- - [type-enum-states](./type-enum-states.md) - Enums for states
137
- - [err-no-unwrap-prod](./err-no-unwrap-prod.md) - Handling Option safely