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.
- package/README.md +47 -150
- package/package.json +1 -1
- package/template/agent/rules/CLAUDE.md +80 -0
- package/template/agent/rules/code-styles.md +31 -32
- package/template/agent/rules/debug-confirmation-policy.md +2 -0
- package/template/agent/rules/file-length-policy.md +2 -0
- package/template/agent/rules/git-policy.md +7 -0
- package/template/agent/rules/language-matching.md +2 -0
- package/template/agent/rules/scratch-scripts.md +39 -0
- package/template/agent/rules/superpowers.md +8 -51
- package/template/agent/skills/executing-plans/SKILL.md +17 -0
- package/template/agent/skills/systematic-debugging/SKILL.md +16 -0
- package/template/agent/skills/test-driven-development/SKILL.md +16 -0
- package/template/agent/skills/verification-before-completion/SKILL.md +22 -0
- package/template/agent/skills/writing-plans/SKILL.md +16 -0
- package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
- package/template/agent/skills/analytics-setup/SKILL.md +0 -51
- package/template/agent/skills/api-design/SKILL.md +0 -193
- package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
- package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
- package/template/agent/skills/backend-developer/SKILL.md +0 -148
- package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
- package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
- package/template/agent/skills/community-manager/SKILL.md +0 -115
- package/template/agent/skills/content-marketer/SKILL.md +0 -111
- package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
- package/template/agent/skills/cto-architect/SKILL.md +0 -133
- package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
- package/template/agent/skills/data-analyst/SKILL.md +0 -147
- package/template/agent/skills/devops-engineer/SKILL.md +0 -117
- package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
- package/template/agent/skills/game-design/SKILL.md +0 -194
- package/template/agent/skills/game-developer/SKILL.md +0 -175
- package/template/agent/skills/growth-hacker/SKILL.md +0 -122
- package/template/agent/skills/idea-validator/SKILL.md +0 -55
- package/template/agent/skills/indie-legal/SKILL.md +0 -53
- package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
- package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
- package/template/agent/skills/launch-strategist/SKILL.md +0 -62
- package/template/agent/skills/market-researcher/SKILL.md +0 -53
- package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
- package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
- package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
- package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
- package/template/agent/skills/real-time-features/SKILL.md +0 -194
- package/template/agent/skills/retention-specialist/SKILL.md +0 -123
- package/template/agent/skills/rust-developer/SKILL.md +0 -281
- package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
- package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
- package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
- package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
- package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
- package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
- package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
- package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
- package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
- package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
- package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
- package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
- package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
- package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
- package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
- package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
- package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
- package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
- package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
- package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
- package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
- package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
- package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
- package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
- package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
- package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
- package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
- package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
- package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
- package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
- package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
- package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
- package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
- package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
- package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
- package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
- package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
- package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
- package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
- package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
- package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
- package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
- package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
- package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
- package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
- package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
- package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
- package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
- package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
- package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
- package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
- package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
- package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
- package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
- package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
- package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
- package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
- package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
- package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
- package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
- package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
- package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
- package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
- package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
- package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
- package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
- package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
- package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
- package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
- package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
- package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
- package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
- package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
- package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
- package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
- package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
- package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
- package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
- package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
- package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
- package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
- package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
- package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
- package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
- package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
- package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
- package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
- package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
- package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
- package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
- package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
- package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
- package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
- package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
- package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
- package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
- package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
- package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
- package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
- package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
- package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
- package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
- package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
- package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
- package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
- package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
- package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
- package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
- package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
- package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
- package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
- package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
- package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
- package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
- package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
- package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
- package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
- package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
- package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
- package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
- package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
- package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
- package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
- package/template/agent/skills/saas-architect/SKILL.md +0 -139
- package/template/agent/skills/security-engineer/SKILL.md +0 -133
- package/template/agent/skills/seo-specialist/SKILL.md +0 -130
- 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
|
package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md
DELETED
|
@@ -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
|