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,158 +0,0 @@
|
|
|
1
|
-
# mem-box-large-variant
|
|
2
|
-
|
|
3
|
-
> Box large enum variants to reduce overall enum size
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
An enum's size is determined by its largest variant. If one variant contains a large struct while others are small, every instance of the enum pays for the largest variant's size. Boxing the large variant puts that data on the heap, keeping the enum itself small. This can significantly reduce memory usage and improve cache performance.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
enum Message {
|
|
13
|
-
Quit, // 0 bytes of data
|
|
14
|
-
Move { x: i32, y: i32 }, // 8 bytes
|
|
15
|
-
Text(String), // 24 bytes
|
|
16
|
-
Image {
|
|
17
|
-
data: [u8; 1024], // 1024 bytes - forces entire enum to ~1032 bytes!
|
|
18
|
-
width: u32,
|
|
19
|
-
height: u32
|
|
20
|
-
},
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Every Message is ~1032 bytes, even Quit and Move
|
|
24
|
-
let messages: Vec<Message> = vec![
|
|
25
|
-
Message::Quit, // Wastes ~1032 bytes
|
|
26
|
-
Message::Quit, // Wastes ~1032 bytes
|
|
27
|
-
Message::Move { x: 0, y: 0 }, // Wastes ~1024 bytes
|
|
28
|
-
];
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Good
|
|
32
|
-
|
|
33
|
-
```rust
|
|
34
|
-
struct ImageData {
|
|
35
|
-
data: [u8; 1024],
|
|
36
|
-
width: u32,
|
|
37
|
-
height: u32,
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
enum Message {
|
|
41
|
-
Quit,
|
|
42
|
-
Move { x: i32, y: i32 },
|
|
43
|
-
Text(String),
|
|
44
|
-
Image(Box<ImageData>), // Now just 8 bytes (pointer)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Message is now ~32 bytes (String variant is largest)
|
|
48
|
-
let messages: Vec<Message> = vec![
|
|
49
|
-
Message::Quit, // Uses ~32 bytes
|
|
50
|
-
Message::Quit, // Uses ~32 bytes
|
|
51
|
-
Message::Move { x: 0, y: 0 }, // Uses ~32 bytes
|
|
52
|
-
];
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Check Enum Sizes
|
|
56
|
-
|
|
57
|
-
```rust
|
|
58
|
-
use std::mem::size_of;
|
|
59
|
-
|
|
60
|
-
// Before boxing
|
|
61
|
-
enum BadEvent {
|
|
62
|
-
Click { x: u32, y: u32 }, // 8 bytes
|
|
63
|
-
KeyPress(char), // 4 bytes
|
|
64
|
-
LargeData([u8; 256]), // 256 bytes
|
|
65
|
-
}
|
|
66
|
-
println!("BadEvent: {} bytes", size_of::<BadEvent>()); // ~264 bytes
|
|
67
|
-
|
|
68
|
-
// After boxing
|
|
69
|
-
enum GoodEvent {
|
|
70
|
-
Click { x: u32, y: u32 },
|
|
71
|
-
KeyPress(char),
|
|
72
|
-
LargeData(Box<[u8; 256]>), // 8 bytes (pointer)
|
|
73
|
-
}
|
|
74
|
-
println!("GoodEvent: {} bytes", size_of::<GoodEvent>()); // ~16 bytes
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Clippy Lint
|
|
78
|
-
|
|
79
|
-
```toml
|
|
80
|
-
[lints.clippy]
|
|
81
|
-
large_enum_variant = "warn" # Warns when variants differ significantly
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
```rust
|
|
85
|
-
// Clippy will suggest:
|
|
86
|
-
// warning: large size difference between variants
|
|
87
|
-
// help: consider boxing the large fields to reduce the total size
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
## When to Box
|
|
91
|
-
|
|
92
|
-
| Largest Variant | Other Variants | Action |
|
|
93
|
-
|-----------------|----------------|--------|
|
|
94
|
-
| < 64 bytes | Similar size | Don't box |
|
|
95
|
-
| > 128 bytes | Much smaller | Box the large variant |
|
|
96
|
-
| > 256 bytes | Any | Definitely box |
|
|
97
|
-
|
|
98
|
-
## Recursive Types Require Boxing
|
|
99
|
-
|
|
100
|
-
```rust
|
|
101
|
-
// Won't compile - infinite size
|
|
102
|
-
enum List {
|
|
103
|
-
Cons(i32, List),
|
|
104
|
-
Nil,
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Must box recursive variant
|
|
108
|
-
enum List {
|
|
109
|
-
Cons(i32, Box<List>), // Now finite size
|
|
110
|
-
Nil,
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Same for ASTs
|
|
114
|
-
enum Expr {
|
|
115
|
-
Number(i64),
|
|
116
|
-
BinOp {
|
|
117
|
-
op: Op,
|
|
118
|
-
left: Box<Expr>, // Recursive - must box
|
|
119
|
-
right: Box<Expr>,
|
|
120
|
-
},
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## Pattern Matching with Boxed Variants
|
|
125
|
-
|
|
126
|
-
```rust
|
|
127
|
-
enum Event {
|
|
128
|
-
Small(u32),
|
|
129
|
-
Large(Box<LargeData>),
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
fn handle(event: Event) {
|
|
133
|
-
match event {
|
|
134
|
-
Event::Small(n) => println!("Small: {}", n),
|
|
135
|
-
Event::Large(data) => {
|
|
136
|
-
// data is Box<LargeData>, dereference to access
|
|
137
|
-
println!("Large: {} bytes", data.size);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Or match on reference
|
|
143
|
-
fn handle_ref(event: &Event) {
|
|
144
|
-
match event {
|
|
145
|
-
Event::Small(n) => println!("Small: {}", n),
|
|
146
|
-
Event::Large(data) => {
|
|
147
|
-
// data is &Box<LargeData>, auto-derefs
|
|
148
|
-
println!("Large: {} bytes", data.size);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## See Also
|
|
155
|
-
|
|
156
|
-
- [own-move-large](./own-move-large.md) - Boxing large types for cheap moves
|
|
157
|
-
- [mem-smallvec](./mem-smallvec.md) - Alternative for inline small collections
|
|
158
|
-
- [lint-deny-correctness](./lint-deny-correctness.md) - Enabling clippy lints
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
# mem-boxed-slice
|
|
2
|
-
|
|
3
|
-
> Use `Box<[T]>` instead of `Vec<T>` for fixed-size heap data
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
`Vec<T>` stores three words: pointer, length, and capacity. When you know a collection won't grow, `Box<[T]>` stores only pointer and length (2 words), saving 8 bytes per instance. More importantly, it communicates intent: "this data is fixed-size." For large numbers of fixed collections, this adds up.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
struct Document {
|
|
13
|
-
// Vec signals "might grow" but we never push after creation
|
|
14
|
-
paragraphs: Vec<Paragraph>, // 24 bytes: ptr + len + capacity
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
fn load_document(data: &[u8]) -> Document {
|
|
18
|
-
let paragraphs: Vec<Paragraph> = parse_paragraphs(data);
|
|
19
|
-
// paragraphs has capacity >= len, wasting the capacity field
|
|
20
|
-
Document { paragraphs }
|
|
21
|
-
}
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Good
|
|
25
|
-
|
|
26
|
-
```rust
|
|
27
|
-
struct Document {
|
|
28
|
-
// Box<[T]> signals "fixed size" - clear intent
|
|
29
|
-
paragraphs: Box<[Paragraph]>, // 16 bytes: ptr + len (as fat pointer)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
fn load_document(data: &[u8]) -> Document {
|
|
33
|
-
let paragraphs: Vec<Paragraph> = parse_paragraphs(data);
|
|
34
|
-
Document {
|
|
35
|
-
paragraphs: paragraphs.into_boxed_slice() // Shrinks + converts
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Memory Layout
|
|
41
|
-
|
|
42
|
-
```rust
|
|
43
|
-
use std::mem::size_of;
|
|
44
|
-
|
|
45
|
-
// Vec: 24 bytes on 64-bit
|
|
46
|
-
assert_eq!(size_of::<Vec<u8>>(), 24); // ptr(8) + len(8) + cap(8)
|
|
47
|
-
|
|
48
|
-
// Box<[T]>: 16 bytes (fat pointer)
|
|
49
|
-
assert_eq!(size_of::<Box<[u8]>>(), 16); // ptr(8) + len(8)
|
|
50
|
-
|
|
51
|
-
// Savings per instance: 8 bytes
|
|
52
|
-
// For 1 million instances: 8 MB saved
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Conversion Patterns
|
|
56
|
-
|
|
57
|
-
```rust
|
|
58
|
-
// Vec to Box<[T]>
|
|
59
|
-
let vec: Vec<i32> = vec![1, 2, 3, 4, 5];
|
|
60
|
-
let boxed: Box<[i32]> = vec.into_boxed_slice();
|
|
61
|
-
|
|
62
|
-
// Box<[T]> back to Vec (if you need to grow)
|
|
63
|
-
let vec_again: Vec<i32> = boxed.into_vec();
|
|
64
|
-
|
|
65
|
-
// From iterator
|
|
66
|
-
let boxed: Box<[i32]> = (0..100).collect::<Vec<_>>().into_boxed_slice();
|
|
67
|
-
|
|
68
|
-
// Shrink Vec first if it has excess capacity
|
|
69
|
-
let mut vec = Vec::with_capacity(1000);
|
|
70
|
-
vec.extend(0..10);
|
|
71
|
-
vec.shrink_to_fit(); // Reduce capacity to length
|
|
72
|
-
let boxed = vec.into_boxed_slice(); // Now no wasted allocation
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## When to Use What
|
|
76
|
-
|
|
77
|
-
| Type | Use When |
|
|
78
|
-
|------|----------|
|
|
79
|
-
| `Vec<T>` | Collection may grow/shrink |
|
|
80
|
-
| `Box<[T]>` | Fixed-size, heap-allocated, many instances |
|
|
81
|
-
| `[T; N]` | Fixed-size, stack-allocated, size known at compile time |
|
|
82
|
-
| `&[T]` | Borrowed view, don't need ownership |
|
|
83
|
-
|
|
84
|
-
## Box<str> for Immutable Strings
|
|
85
|
-
|
|
86
|
-
Same principle applies to strings:
|
|
87
|
-
|
|
88
|
-
```rust
|
|
89
|
-
use std::mem::size_of;
|
|
90
|
-
|
|
91
|
-
// String: 24 bytes (like Vec<u8>)
|
|
92
|
-
assert_eq!(size_of::<String>(), 24);
|
|
93
|
-
|
|
94
|
-
// Box<str>: 16 bytes
|
|
95
|
-
assert_eq!(size_of::<Box<str>>(), 16);
|
|
96
|
-
|
|
97
|
-
// For immutable strings
|
|
98
|
-
struct Name {
|
|
99
|
-
value: Box<str>, // Saves 8 bytes vs String
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
impl Name {
|
|
103
|
-
fn new(s: &str) -> Self {
|
|
104
|
-
Name { value: s.into() } // &str -> Box<str>
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Or from String
|
|
109
|
-
let s = String::from("hello");
|
|
110
|
-
let boxed: Box<str> = s.into_boxed_str();
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
## Real-World Example
|
|
114
|
-
|
|
115
|
-
```rust
|
|
116
|
-
// Cache with millions of entries
|
|
117
|
-
struct Cache {
|
|
118
|
-
// 8 bytes saved per entry adds up
|
|
119
|
-
entries: HashMap<Key, Box<[u8]>>,
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
impl Cache {
|
|
123
|
-
fn insert(&mut self, key: Key, data: Vec<u8>) {
|
|
124
|
-
// Convert to boxed slice for storage
|
|
125
|
-
self.entries.insert(key, data.into_boxed_slice());
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
fn get(&self, key: &Key) -> Option<&[u8]> {
|
|
129
|
-
// Returns regular slice reference
|
|
130
|
-
self.entries.get(key).map(|b| b.as_ref())
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## See Also
|
|
136
|
-
|
|
137
|
-
- [mem-with-capacity](./mem-with-capacity.md) - Pre-allocating when size is known
|
|
138
|
-
- [own-slice-over-vec](./own-slice-over-vec.md) - Using slices in function parameters
|
|
139
|
-
- [mem-compact-string](./mem-compact-string.md) - Compact string alternatives
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# mem-clone-from
|
|
2
|
-
|
|
3
|
-
> Use `clone_from()` to reuse allocations when repeatedly cloning
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
`x = y.clone()` drops x's allocation and creates a new one from y. `x.clone_from(&y)` reuses x's existing allocation if possible, avoiding the allocation overhead. For repeatedly cloning into the same variable (loops, buffers), this can significantly reduce allocator pressure.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
let mut buffer = String::with_capacity(1024);
|
|
13
|
-
|
|
14
|
-
for source in sources {
|
|
15
|
-
buffer = source.clone(); // Drops old allocation, allocates new
|
|
16
|
-
process(&buffer);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Each iteration:
|
|
20
|
-
// 1. Drops buffer's 1024-byte allocation
|
|
21
|
-
// 2. Allocates new memory for source.clone()
|
|
22
|
-
// Allocator thrashing!
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Good
|
|
26
|
-
|
|
27
|
-
```rust
|
|
28
|
-
let mut buffer = String::with_capacity(1024);
|
|
29
|
-
|
|
30
|
-
for source in sources {
|
|
31
|
-
buffer.clone_from(source); // Reuses allocation if capacity sufficient
|
|
32
|
-
process(&buffer);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// If source.len() <= 1024, no allocation happens
|
|
36
|
-
// Just copies bytes into existing buffer
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## How clone_from Works
|
|
40
|
-
|
|
41
|
-
```rust
|
|
42
|
-
impl Clone for String {
|
|
43
|
-
fn clone(&self) -> Self {
|
|
44
|
-
// Always allocates new memory
|
|
45
|
-
String::from(self.as_str())
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
fn clone_from(&mut self, source: &Self) {
|
|
49
|
-
// Reuse existing capacity if possible
|
|
50
|
-
self.clear();
|
|
51
|
-
self.push_str(source); // Only reallocates if capacity insufficient
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Types That Benefit
|
|
57
|
-
|
|
58
|
-
```rust
|
|
59
|
-
// String - reuses capacity
|
|
60
|
-
let mut s = String::with_capacity(100);
|
|
61
|
-
s.clone_from(&other_string);
|
|
62
|
-
|
|
63
|
-
// Vec<T> - reuses capacity
|
|
64
|
-
let mut v: Vec<u8> = Vec::with_capacity(1000);
|
|
65
|
-
v.clone_from(&other_vec);
|
|
66
|
-
|
|
67
|
-
// HashMap - reuses buckets
|
|
68
|
-
let mut map = HashMap::with_capacity(100);
|
|
69
|
-
map.clone_from(&other_map);
|
|
70
|
-
|
|
71
|
-
// PathBuf - reuses capacity
|
|
72
|
-
let mut path = PathBuf::with_capacity(256);
|
|
73
|
-
path.clone_from(&other_path);
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Benchmarking the Difference
|
|
77
|
-
|
|
78
|
-
```rust
|
|
79
|
-
use criterion::{black_box, criterion_group, Criterion};
|
|
80
|
-
|
|
81
|
-
fn bench_clone_patterns(c: &mut Criterion) {
|
|
82
|
-
let source = "x".repeat(1000);
|
|
83
|
-
|
|
84
|
-
c.bench_function("clone assignment", |b| {
|
|
85
|
-
let mut buffer = String::new();
|
|
86
|
-
b.iter(|| {
|
|
87
|
-
buffer = black_box(&source).clone();
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
c.bench_function("clone_from", |b| {
|
|
92
|
-
let mut buffer = String::with_capacity(1000);
|
|
93
|
-
b.iter(|| {
|
|
94
|
-
buffer.clone_from(black_box(&source));
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
// clone_from is typically 2-3x faster for this pattern
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Custom Implementations
|
|
102
|
-
|
|
103
|
-
When implementing Clone for your types:
|
|
104
|
-
|
|
105
|
-
```rust
|
|
106
|
-
#[derive(Debug)]
|
|
107
|
-
struct Buffer {
|
|
108
|
-
data: Vec<u8>,
|
|
109
|
-
metadata: Metadata,
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
impl Clone for Buffer {
|
|
113
|
-
fn clone(&self) -> Self {
|
|
114
|
-
Buffer {
|
|
115
|
-
data: self.data.clone(),
|
|
116
|
-
metadata: self.metadata.clone(),
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Optimize clone_from to reuse vec capacity
|
|
121
|
-
fn clone_from(&mut self, source: &Self) {
|
|
122
|
-
self.data.clone_from(&source.data); // Reuses allocation
|
|
123
|
-
self.metadata = source.metadata.clone();
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## When NOT Needed
|
|
129
|
-
|
|
130
|
-
```rust
|
|
131
|
-
// Single clone - no benefit
|
|
132
|
-
let copy = original.clone(); // Can't reuse, no prior allocation
|
|
133
|
-
|
|
134
|
-
// Small Copy types - no allocation anyway
|
|
135
|
-
let x: i32 = y; // Not even Clone, just Copy
|
|
136
|
-
|
|
137
|
-
// Immutable context
|
|
138
|
-
fn process(data: &String) {
|
|
139
|
-
// Can't use clone_from - would need &mut self
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
## See Also
|
|
144
|
-
|
|
145
|
-
- [mem-with-capacity](./mem-with-capacity.md) - Pre-allocating capacity
|
|
146
|
-
- [mem-reuse-collections](./mem-reuse-collections.md) - Reusing collection allocations
|
|
147
|
-
- [own-clone-explicit](./own-clone-explicit.md) - When Clone is appropriate
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
# mem-compact-string
|
|
2
|
-
|
|
3
|
-
> Use compact string types for memory-constrained string storage
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Standard `String` is 24 bytes (pointer + length + capacity). For applications storing millions of short strings, this overhead dominates. Compact string libraries like `compact_str`, `smartstring`, or `ecow` store small strings inline (no heap allocation) and use optimized layouts for larger strings.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
struct User {
|
|
13
|
-
id: u64,
|
|
14
|
-
// Most usernames are < 24 chars, but String is always 24 bytes + heap
|
|
15
|
-
username: String,
|
|
16
|
-
email: String,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// 1 million users = 24 bytes * 2 * 1M = 48MB just for String metadata
|
|
20
|
-
// Plus all the heap allocations for actual content
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Good
|
|
24
|
-
|
|
25
|
-
```rust
|
|
26
|
-
use compact_str::CompactString;
|
|
27
|
-
|
|
28
|
-
struct User {
|
|
29
|
-
id: u64,
|
|
30
|
-
// CompactString: 24 bytes, but strings ≤ 24 chars are inline (no heap)
|
|
31
|
-
username: CompactString,
|
|
32
|
-
email: CompactString,
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Most usernames fit inline = zero heap allocations
|
|
36
|
-
// Same memory footprint as String but way fewer allocations
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Compact String Libraries
|
|
40
|
-
|
|
41
|
-
### compact_str
|
|
42
|
-
|
|
43
|
-
```rust
|
|
44
|
-
use compact_str::CompactString;
|
|
45
|
-
|
|
46
|
-
// Inline storage for strings ≤ 24 bytes
|
|
47
|
-
let small: CompactString = "hello".into(); // No heap allocation
|
|
48
|
-
|
|
49
|
-
// Automatic heap fallback for larger strings
|
|
50
|
-
let large: CompactString = "x".repeat(100).into();
|
|
51
|
-
|
|
52
|
-
// String-like API
|
|
53
|
-
let mut s = CompactString::new("hello");
|
|
54
|
-
s.push_str(" world");
|
|
55
|
-
assert_eq!(s.as_str(), "hello world");
|
|
56
|
-
|
|
57
|
-
// Format macro
|
|
58
|
-
use compact_str::format_compact;
|
|
59
|
-
let s = format_compact!("value: {}", 42);
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### smartstring
|
|
63
|
-
|
|
64
|
-
```rust
|
|
65
|
-
use smartstring::{SmartString, LazyCompact};
|
|
66
|
-
|
|
67
|
-
// Default is LazyCompact: 24 bytes inline capacity
|
|
68
|
-
let s: SmartString<LazyCompact> = "short string".into();
|
|
69
|
-
|
|
70
|
-
// Compact mode: 23 bytes inline on 64-bit
|
|
71
|
-
use smartstring::Compact;
|
|
72
|
-
let s: SmartString<Compact> = "hello".into();
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### ecow (copy-on-write)
|
|
76
|
-
|
|
77
|
-
```rust
|
|
78
|
-
use ecow::EcoString;
|
|
79
|
-
|
|
80
|
-
// Clone is O(1) - shares underlying data
|
|
81
|
-
let s1: EcoString = "shared data".into();
|
|
82
|
-
let s2 = s1.clone(); // Cheap, shares allocation
|
|
83
|
-
|
|
84
|
-
// Copy-on-write: only allocates on mutation
|
|
85
|
-
let mut s3 = s1.clone();
|
|
86
|
-
s3.push_str(" modified"); // Now allocates
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Memory Comparison
|
|
90
|
-
|
|
91
|
-
```rust
|
|
92
|
-
use std::mem::size_of;
|
|
93
|
-
|
|
94
|
-
// All 24 bytes, but different inline capacities
|
|
95
|
-
assert_eq!(size_of::<String>(), 24);
|
|
96
|
-
assert_eq!(size_of::<compact_str::CompactString>(), 24);
|
|
97
|
-
assert_eq!(size_of::<smartstring::SmartString>(), 24);
|
|
98
|
-
assert_eq!(size_of::<ecow::EcoString>(), 16); // Even smaller!
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Inline Capacity
|
|
102
|
-
|
|
103
|
-
| Type | Size | Inline Capacity |
|
|
104
|
-
|------|------|-----------------|
|
|
105
|
-
| `String` | 24 | 0 (always heap) |
|
|
106
|
-
| `CompactString` | 24 | 24 bytes |
|
|
107
|
-
| `SmartString<LazyCompact>` | 24 | 23 bytes |
|
|
108
|
-
| `EcoString` | 16 | 15 bytes |
|
|
109
|
-
|
|
110
|
-
## When to Use
|
|
111
|
-
|
|
112
|
-
```rust
|
|
113
|
-
// ✅ Good: Many short strings in memory
|
|
114
|
-
struct Dictionary {
|
|
115
|
-
words: Vec<CompactString>, // Millions of short words
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// ✅ Good: Frequently cloned strings
|
|
119
|
-
struct Template {
|
|
120
|
-
parts: Vec<EcoString>, // O(1) clone
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ❌ Don't: Hot path string manipulation
|
|
124
|
-
fn transform(s: &str) -> String {
|
|
125
|
-
// Standard String is optimized for manipulation
|
|
126
|
-
s.to_uppercase()
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// ❌ Don't: API boundaries (prefer &str or String for interop)
|
|
130
|
-
pub fn public_api(input: CompactString) { } // Forces dependency
|
|
131
|
-
pub fn public_api(input: impl Into<String>) { } // Better
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## Cargo.toml
|
|
135
|
-
|
|
136
|
-
```toml
|
|
137
|
-
[dependencies]
|
|
138
|
-
compact_str = "0.7"
|
|
139
|
-
# or
|
|
140
|
-
smartstring = "1.0"
|
|
141
|
-
# or
|
|
142
|
-
ecow = "0.2"
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## See Also
|
|
146
|
-
|
|
147
|
-
- [mem-boxed-slice](./mem-boxed-slice.md) - Box<str> for immutable strings
|
|
148
|
-
- [own-cow-conditional](./own-cow-conditional.md) - Cow<str> for borrow-or-own
|
|
149
|
-
- [mem-smallvec](./mem-smallvec.md) - Similar concept for Vec
|