agy-superpowers 5.1.4 → 5.1.5

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 (182) hide show
  1. package/package.json +1 -1
  2. package/template/agent/skills/rust-developer/SKILL.md +281 -0
  3. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +231 -0
  4. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +124 -0
  5. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +131 -0
  6. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +132 -0
  7. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +95 -0
  8. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +141 -0
  9. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +125 -0
  10. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +127 -0
  11. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +120 -0
  12. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +131 -0
  13. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +156 -0
  14. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +122 -0
  15. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +167 -0
  16. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +134 -0
  17. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +143 -0
  18. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +121 -0
  19. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +143 -0
  20. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +187 -0
  21. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +165 -0
  22. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +177 -0
  23. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +163 -0
  24. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +146 -0
  25. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +142 -0
  26. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +160 -0
  27. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +125 -0
  28. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +162 -0
  29. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +177 -0
  30. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +184 -0
  31. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +168 -0
  32. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +182 -0
  33. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +199 -0
  34. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +175 -0
  35. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +185 -0
  36. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +203 -0
  37. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +171 -0
  38. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +158 -0
  39. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +195 -0
  40. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +171 -0
  41. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +156 -0
  42. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +191 -0
  43. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +198 -0
  44. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +154 -0
  45. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +167 -0
  46. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +169 -0
  47. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +172 -0
  48. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +189 -0
  49. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +113 -0
  50. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +147 -0
  51. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +122 -0
  52. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +161 -0
  53. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +149 -0
  54. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +138 -0
  55. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +169 -0
  56. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +116 -0
  57. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +128 -0
  58. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +136 -0
  59. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +131 -0
  60. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +179 -0
  61. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +144 -0
  62. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +152 -0
  63. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +145 -0
  64. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +133 -0
  65. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +152 -0
  66. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +124 -0
  67. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +115 -0
  68. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +151 -0
  69. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +130 -0
  70. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +155 -0
  71. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +171 -0
  72. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +138 -0
  73. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +107 -0
  74. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +154 -0
  75. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +118 -0
  76. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +157 -0
  77. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +133 -0
  78. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +131 -0
  79. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +136 -0
  80. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +135 -0
  81. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +122 -0
  82. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +172 -0
  83. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +168 -0
  84. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +142 -0
  85. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +168 -0
  86. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +147 -0
  87. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +158 -0
  88. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +139 -0
  89. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +147 -0
  90. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +149 -0
  91. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +174 -0
  92. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +159 -0
  93. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +138 -0
  94. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +142 -0
  95. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +156 -0
  96. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +172 -0
  97. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +164 -0
  98. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +99 -0
  99. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +104 -0
  100. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +94 -0
  101. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +78 -0
  102. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +76 -0
  103. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +123 -0
  104. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +127 -0
  105. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +129 -0
  106. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +131 -0
  107. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +142 -0
  108. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +86 -0
  109. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +154 -0
  110. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +118 -0
  111. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +92 -0
  112. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +65 -0
  113. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +101 -0
  114. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +161 -0
  115. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +187 -0
  116. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +142 -0
  117. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +152 -0
  118. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +141 -0
  119. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +181 -0
  120. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +160 -0
  121. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +171 -0
  122. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +130 -0
  123. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +167 -0
  124. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +144 -0
  125. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +154 -0
  126. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +141 -0
  127. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +95 -0
  128. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +135 -0
  129. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +124 -0
  130. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +135 -0
  131. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +134 -0
  132. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +134 -0
  133. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +105 -0
  134. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +65 -0
  135. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +97 -0
  136. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +122 -0
  137. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +119 -0
  138. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +153 -0
  139. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +136 -0
  140. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +133 -0
  141. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +120 -0
  142. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +137 -0
  143. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +134 -0
  144. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +150 -0
  145. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +123 -0
  146. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +113 -0
  147. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +175 -0
  148. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +149 -0
  149. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +142 -0
  150. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +133 -0
  151. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +148 -0
  152. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +130 -0
  153. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +120 -0
  154. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +155 -0
  155. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +139 -0
  156. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +135 -0
  157. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +162 -0
  158. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +186 -0
  159. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +162 -0
  160. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +160 -0
  161. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +151 -0
  162. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +171 -0
  163. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +142 -0
  164. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +168 -0
  165. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +151 -0
  166. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +144 -0
  167. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +189 -0
  168. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +226 -0
  169. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +161 -0
  170. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +130 -0
  171. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +154 -0
  172. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +127 -0
  173. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +154 -0
  174. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +142 -0
  175. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +146 -0
  176. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +160 -0
  177. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +159 -0
  178. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +144 -0
  179. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +137 -0
  180. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +188 -0
  181. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +143 -0
  182. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +131 -0
@@ -0,0 +1,174 @@
1
+ # mem-reuse-collections
2
+
3
+ > Clear and reuse collections instead of creating new ones in loops
4
+
5
+ ## Why It Matters
6
+
7
+ Creating new `Vec`, `String`, or `HashMap` instances in hot loops generates significant allocator pressure. Clearing a collection and reusing it keeps the existing capacity, avoiding repeated allocation/deallocation cycles. This is especially impactful for frequently-executed code paths.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ fn process_batches(batches: &[Batch]) -> Vec<Result> {
13
+ let mut results = Vec::new();
14
+
15
+ for batch in batches {
16
+ let mut temp = Vec::new(); // Allocates every iteration
17
+
18
+ for item in &batch.items {
19
+ temp.push(transform(item));
20
+ }
21
+
22
+ results.push(aggregate(&temp));
23
+ // temp dropped here, deallocation
24
+ }
25
+
26
+ results
27
+ }
28
+
29
+ fn format_lines(items: &[Item]) -> String {
30
+ let mut output = String::new();
31
+
32
+ for item in items {
33
+ let line = format!("{}: {}", item.name, item.value); // Allocates
34
+ output.push_str(&line);
35
+ output.push('\n');
36
+ }
37
+
38
+ output
39
+ }
40
+ ```
41
+
42
+ ## Good
43
+
44
+ ```rust
45
+ fn process_batches(batches: &[Batch]) -> Vec<Result> {
46
+ let mut results = Vec::with_capacity(batches.len());
47
+ let mut temp = Vec::new(); // Allocate once outside loop
48
+
49
+ for batch in batches {
50
+ temp.clear(); // Reuse allocation, just reset length
51
+
52
+ for item in &batch.items {
53
+ temp.push(transform(item));
54
+ }
55
+
56
+ results.push(aggregate(&temp));
57
+ // temp keeps its capacity for next iteration
58
+ }
59
+
60
+ results
61
+ }
62
+
63
+ fn format_lines(items: &[Item]) -> String {
64
+ use std::fmt::Write;
65
+
66
+ let mut output = String::new();
67
+ let mut line = String::new(); // Reusable buffer
68
+
69
+ for item in items {
70
+ line.clear();
71
+ write!(&mut line, "{}: {}", item.name, item.value).unwrap();
72
+ output.push_str(&line);
73
+ output.push('\n');
74
+ }
75
+
76
+ output
77
+ }
78
+ ```
79
+
80
+ ## Clear vs Drain vs New
81
+
82
+ ```rust
83
+ let mut vec = vec![1, 2, 3, 4, 5];
84
+
85
+ // clear(): keeps capacity, O(n) for Drop types
86
+ vec.clear();
87
+ assert_eq!(vec.len(), 0);
88
+ assert!(vec.capacity() >= 5);
89
+
90
+ // drain(): returns iterator, clears after iteration
91
+ let drained: Vec<_> = vec.drain(..).collect();
92
+
93
+ // truncate(): keeps first n elements
94
+ vec.truncate(2);
95
+
96
+ // Creating new: loses all capacity
97
+ vec = Vec::new(); // Capacity gone
98
+ ```
99
+
100
+ ## HashMap Reuse
101
+
102
+ ```rust
103
+ use std::collections::HashMap;
104
+
105
+ fn count_words_per_line(lines: &[&str]) -> Vec<HashMap<String, usize>> {
106
+ let mut results = Vec::with_capacity(lines.len());
107
+ let mut counts = HashMap::new(); // Reuse across iterations
108
+
109
+ for line in lines {
110
+ counts.clear(); // Keeps bucket allocation
111
+
112
+ for word in line.split_whitespace() {
113
+ *counts.entry(word.to_string()).or_insert(0) += 1;
114
+ }
115
+
116
+ results.push(counts.clone());
117
+ }
118
+
119
+ results
120
+ }
121
+ ```
122
+
123
+ ## BufWriter Pattern
124
+
125
+ ```rust
126
+ use std::io::{BufWriter, Write};
127
+
128
+ fn write_many_records(records: &[Record], mut output: impl Write) -> std::io::Result<()> {
129
+ // BufWriter reuses its internal buffer
130
+ let mut writer = BufWriter::with_capacity(8192, &mut output);
131
+ let mut line = String::with_capacity(256); // Reusable formatting buffer
132
+
133
+ for record in records {
134
+ line.clear();
135
+ format_record(record, &mut line);
136
+ writer.write_all(line.as_bytes())?;
137
+ writer.write_all(b"\n")?;
138
+ }
139
+
140
+ writer.flush()
141
+ }
142
+ ```
143
+
144
+ ## When to Create Fresh
145
+
146
+ ```rust
147
+ // When ownership transfer is needed
148
+ fn produce_results() -> Vec<Vec<Item>> {
149
+ let mut results = Vec::new();
150
+
151
+ for batch in batches {
152
+ let processed: Vec<Item> = batch.process(); // Ownership transferred
153
+ results.push(processed); // Moved into results
154
+ }
155
+
156
+ results // Each inner Vec is independent
157
+ }
158
+
159
+ // When thread safety requires it
160
+ std::thread::scope(|s| {
161
+ for _ in 0..4 {
162
+ s.spawn(|| {
163
+ let local_buffer = Vec::new(); // Thread-local, can't share
164
+ // ...
165
+ });
166
+ }
167
+ });
168
+ ```
169
+
170
+ ## See Also
171
+
172
+ - [mem-with-capacity](./mem-with-capacity.md) - Pre-allocating capacity
173
+ - [mem-clone-from](./mem-clone-from.md) - Reusing allocations when cloning
174
+ - [mem-write-over-format](./mem-write-over-format.md) - Avoiding format! allocations
@@ -0,0 +1,159 @@
1
+ # mem-smaller-integers
2
+
3
+ > Use appropriately-sized integers to reduce memory footprint
4
+
5
+ ## Why It Matters
6
+
7
+ Using `i64` when `i16` suffices wastes 6 bytes per value. In arrays, vectors, and structs with millions of instances, this waste compounds dramatically. Choosing the smallest integer type that fits your domain reduces memory usage and improves cache utilization.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ struct Pixel {
13
+ r: u64, // Color channels 0-255 = 8 bits needed
14
+ g: u64, // Using 64 bits = 8x waste
15
+ b: u64,
16
+ a: u64,
17
+ }
18
+ // Size: 32 bytes per pixel
19
+
20
+ struct HttpStatus {
21
+ code: i32, // HTTP codes 100-599 = 10 bits needed
22
+ version: i32, // HTTP 1.0, 1.1, 2, 3 = 2 bits needed
23
+ }
24
+ // Size: 8 bytes per status
25
+
26
+ struct GeoPoint {
27
+ lat: f64, // -90 to 90
28
+ lon: f64, // -180 to 180
29
+ }
30
+ // Often f32 precision is sufficient for display
31
+ ```
32
+
33
+ ## Good
34
+
35
+ ```rust
36
+ struct Pixel {
37
+ r: u8,
38
+ g: u8,
39
+ b: u8,
40
+ a: u8,
41
+ }
42
+ // Size: 4 bytes per pixel (8x smaller!)
43
+
44
+ struct HttpStatus {
45
+ code: u16, // 100-599 fits in u16
46
+ version: u8, // 1, 2, 3 fits in u8
47
+ }
48
+ // Size: 3 bytes (+ 1 padding = 4 bytes)
49
+
50
+ struct GeoPoint {
51
+ lat: f32, // ~7 decimal digits precision
52
+ lon: f32, // Sufficient for most geo applications
53
+ }
54
+ // Size: 8 bytes vs 16 bytes
55
+ ```
56
+
57
+ ## Integer Size Reference
58
+
59
+ | Type | Range | Use For |
60
+ |------|-------|---------|
61
+ | `u8` | 0 to 255 | Bytes, small counts, flags |
62
+ | `i8` | -128 to 127 | Small signed values |
63
+ | `u16` | 0 to 65,535 | Port numbers, small indices |
64
+ | `i16` | -32,768 to 32,767 | Audio samples |
65
+ | `u32` | 0 to 4 billion | Array indices, timestamps (seconds) |
66
+ | `i32` | ±2 billion | General integers, file offsets |
67
+ | `u64` | 0 to 18 quintillion | Large counts, nanosecond timestamps |
68
+ | `usize` | Platform-dependent | Array indexing (required by Rust) |
69
+
70
+ ## Struct Packing
71
+
72
+ ```rust
73
+ use std::mem::size_of;
74
+
75
+ // Poor ordering - 24 bytes due to padding
76
+ struct Wasteful {
77
+ a: u8, // 1 byte + 7 padding
78
+ b: u64, // 8 bytes
79
+ c: u8, // 1 byte + 7 padding
80
+ }
81
+ assert_eq!(size_of::<Wasteful>(), 24);
82
+
83
+ // Better ordering - 16 bytes
84
+ struct Efficient {
85
+ b: u64, // 8 bytes (aligned)
86
+ a: u8, // 1 byte
87
+ c: u8, // 1 byte + 6 padding
88
+ }
89
+ assert_eq!(size_of::<Efficient>(), 16);
90
+
91
+ // Even better with smaller types - 10 bytes
92
+ struct Compact {
93
+ b: u32, // 4 bytes (if u32 suffices)
94
+ a: u8, // 1 byte
95
+ c: u8, // 1 byte
96
+ }
97
+ assert_eq!(size_of::<Compact>(), 8); // With padding
98
+ ```
99
+
100
+ ## Conversion Safety
101
+
102
+ ```rust
103
+ // Safe: always succeeds (widening)
104
+ let small: u8 = 42;
105
+ let big: u32 = small.into();
106
+
107
+ // Fallible: may overflow (narrowing)
108
+ let big: u32 = 1000;
109
+ let small: u8 = big.try_into().expect("value out of range");
110
+
111
+ // Or use checked conversion
112
+ if let Ok(small) = u8::try_from(big) {
113
+ use_small(small);
114
+ } else {
115
+ handle_overflow();
116
+ }
117
+ ```
118
+
119
+ ## Bitflags for Boolean Sets
120
+
121
+ ```rust
122
+ use bitflags::bitflags;
123
+
124
+ // Instead of 8 separate bool fields (8 bytes minimum)
125
+ bitflags! {
126
+ struct Permissions: u8 {
127
+ const READ = 0b0000_0001;
128
+ const WRITE = 0b0000_0010;
129
+ const EXECUTE = 0b0000_0100;
130
+ const DELETE = 0b0000_1000;
131
+ }
132
+ }
133
+ // All 8 flags in 1 byte!
134
+
135
+ let perms = Permissions::READ | Permissions::WRITE;
136
+ if perms.contains(Permissions::READ) {
137
+ // ...
138
+ }
139
+ ```
140
+
141
+ ## NonZero Types for Option Optimization
142
+
143
+ ```rust
144
+ use std::num::NonZeroU64;
145
+
146
+ // Option<u64> = 16 bytes (no null pointer optimization)
147
+ assert_eq!(size_of::<Option<u64>>(), 16);
148
+
149
+ // Option<NonZeroU64> = 8 bytes (0 represents None)
150
+ assert_eq!(size_of::<Option<NonZeroU64>>(), 8);
151
+
152
+ let id: Option<NonZeroU64> = NonZeroU64::new(42);
153
+ ```
154
+
155
+ ## See Also
156
+
157
+ - [mem-box-large-variant](./mem-box-large-variant.md) - Optimizing enum sizes
158
+ - [mem-assert-type-size](./mem-assert-type-size.md) - Compile-time size checks
159
+ - [type-newtype-ids](./type-newtype-ids.md) - Type safety for integer IDs
@@ -0,0 +1,138 @@
1
+ # mem-smallvec
2
+
3
+ > Use `SmallVec` for usually-small collections
4
+
5
+ ## Why It Matters
6
+
7
+ `SmallVec<[T; N]>` stores up to N elements inline (on the stack), only allocating on the heap when the size exceeds N. This eliminates heap allocations for the common case while still allowing growth when needed.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ // Always heap-allocates, even for 1-2 elements
13
+ fn get_path_components(path: &str) -> Vec<&str> {
14
+ path.split('/').collect() // Usually 2-4 components
15
+ }
16
+
17
+ // Always heap-allocates for error list
18
+ fn validate(input: &Input) -> Vec<ValidationError> {
19
+ let mut errors = Vec::new(); // Usually 0-3 errors
20
+ // validation logic...
21
+ errors
22
+ }
23
+ ```
24
+
25
+ ## Good
26
+
27
+ ```rust
28
+ use smallvec::{smallvec, SmallVec};
29
+
30
+ // Stack-allocated for typical paths (1-8 components)
31
+ fn get_path_components(path: &str) -> SmallVec<[&str; 8]> {
32
+ path.split('/').collect()
33
+ }
34
+
35
+ // Stack-allocated for typical error counts
36
+ fn validate(input: &Input) -> SmallVec<[ValidationError; 4]> {
37
+ let mut errors = SmallVec::new();
38
+ // validation logic...
39
+ errors
40
+ }
41
+
42
+ // Using smallvec! macro
43
+ let v: SmallVec<[i32; 4]> = smallvec![1, 2, 3];
44
+ ```
45
+
46
+ ## Choosing Capacity N
47
+
48
+ ```rust
49
+ // Measure your actual data distribution!
50
+ // Guidelines:
51
+
52
+ // Path components: 4-8 (most paths are shallow)
53
+ type PathParts<'a> = SmallVec<[&'a str; 8]>;
54
+
55
+ // Function arguments: 4-8 (most functions have few args)
56
+ type Args = SmallVec<[Arg; 8]>;
57
+
58
+ // AST children: 2-4 (binary ops, if/else, etc.)
59
+ type Children = SmallVec<[Node; 4]>;
60
+
61
+ // Error accumulation: 2-4 (most inputs have few errors)
62
+ type Errors = SmallVec<[Error; 4]>;
63
+
64
+ // Attribute lists: 4-8 (most items have few attributes)
65
+ type Attrs = SmallVec<[Attribute; 8]>;
66
+ ```
67
+
68
+ ## Evidence from rust-analyzer
69
+
70
+ ```rust
71
+ // https://github.com/rust-lang/rust/blob/main/compiler/rustc_expand/src/base.rs
72
+ macro_rules! make_stmts_default {
73
+ ($me:expr) => {
74
+ $me.make_expr().map(|e| {
75
+ smallvec![ast::Stmt {
76
+ id: ast::DUMMY_NODE_ID,
77
+ span: e.span,
78
+ kind: ast::StmtKind::Expr(e),
79
+ }]
80
+ })
81
+ }
82
+ }
83
+ ```
84
+
85
+ ## Trade-offs
86
+
87
+ ```rust
88
+ // SmallVec is slightly larger than Vec
89
+ use std::mem::size_of;
90
+ // Vec<i32>: 24 bytes (ptr + len + cap)
91
+ // SmallVec<[i32; 4]>: 32 bytes (inline storage + len + discriminant)
92
+
93
+ // SmallVec has branching overhead on every operation
94
+ // (must check if inline or heap)
95
+
96
+ // Profile to verify benefit!
97
+ ```
98
+
99
+ ## When to Use SmallVec vs Alternatives
100
+
101
+ | Situation | Use |
102
+ |-----------|-----|
103
+ | Usually small, sometimes large | `SmallVec<[T; N]>` |
104
+ | Always small, fixed max | `ArrayVec<T, N>` |
105
+ | Rarely grows past initial | `Vec::with_capacity` |
106
+ | No `unsafe` allowed | `TinyVec` |
107
+ | Often empty | `ThinVec` |
108
+
109
+ ## ArrayVec Alternative
110
+
111
+ ```rust
112
+ use arrayvec::ArrayVec;
113
+
114
+ // Fixed maximum capacity, never heap allocates
115
+ // Panics if you exceed capacity
116
+ fn parse_rgb(s: &str) -> ArrayVec<u8, 3> {
117
+ let mut components = ArrayVec::new();
118
+ for part in s.split(',').take(3) {
119
+ components.push(part.parse().unwrap());
120
+ }
121
+ components
122
+ }
123
+ ```
124
+
125
+ ## TinyVec (No Unsafe)
126
+
127
+ ```rust
128
+ use tinyvec::{tiny_vec, TinyVec};
129
+
130
+ // Same concept as SmallVec but 100% safe code
131
+ let v: TinyVec<[i32; 4]> = tiny_vec![1, 2, 3];
132
+ ```
133
+
134
+ ## See Also
135
+
136
+ - [mem-arrayvec](mem-arrayvec.md) - Use ArrayVec for fixed-max collections
137
+ - [mem-with-capacity](mem-with-capacity.md) - Pre-allocate when size is known
138
+ - [mem-thinvec](mem-thinvec.md) - Use ThinVec for often-empty vectors
@@ -0,0 +1,142 @@
1
+ # mem-thinvec
2
+
3
+ > Use `ThinVec<T>` for nullable collections with minimal overhead
4
+
5
+ ## Why It Matters
6
+
7
+ Standard `Vec<T>` is 24 bytes even when empty. `ThinVec` from Mozilla's `thin_vec` crate uses a single pointer (8 bytes), storing length and capacity inline with the heap allocation. For Option<Vec<T>> patterns or structs with many optional vecs, this significantly reduces memory overhead.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ struct TreeNode {
13
+ value: i32,
14
+ // Each node pays 24 bytes for children, even leaves
15
+ children: Vec<TreeNode>, // Most nodes are leaves with empty Vec
16
+ }
17
+
18
+ // Or using Option<Vec<T>>
19
+ struct SparseData {
20
+ // Option<Vec> = 24 bytes (Vec is never null-pointer optimized)
21
+ tags: Option<Vec<String>>,
22
+ metadata: Option<Vec<Metadata>>,
23
+ // 48 bytes for usually-None fields
24
+ }
25
+ ```
26
+
27
+ ## Good
28
+
29
+ ```rust
30
+ use thin_vec::ThinVec;
31
+
32
+ struct TreeNode {
33
+ value: i32,
34
+ // Empty ThinVec is just a null pointer - 8 bytes
35
+ children: ThinVec<TreeNode>,
36
+ }
37
+
38
+ struct SparseData {
39
+ // ThinVec empty = 8 bytes each
40
+ tags: ThinVec<String>,
41
+ metadata: ThinVec<Metadata>,
42
+ // 16 bytes vs 48 bytes
43
+ }
44
+ ```
45
+
46
+ ## Memory Layout
47
+
48
+ ```rust
49
+ use std::mem::size_of;
50
+
51
+ // Standard Vec: always 24 bytes
52
+ assert_eq!(size_of::<Vec<u8>>(), 24);
53
+ assert_eq!(size_of::<Option<Vec<u8>>>(), 24); // No NPO benefit
54
+
55
+ // ThinVec: 8 bytes (one pointer)
56
+ use thin_vec::ThinVec;
57
+ assert_eq!(size_of::<ThinVec<u8>>(), 8);
58
+ assert_eq!(size_of::<Option<ThinVec<u8>>>(), 8); // Option is free!
59
+ ```
60
+
61
+ ## ThinVec vs Vec
62
+
63
+ | Feature | `Vec<T>` | `ThinVec<T>` |
64
+ |---------|----------|--------------|
65
+ | Size (empty) | 24 bytes | 8 bytes |
66
+ | Size (non-empty) | 24 bytes | 8 bytes (header on heap) |
67
+ | Option<T> optimization | No | Yes |
68
+ | Cache locality | Better (len/cap on stack) | Worse (len/cap on heap) |
69
+ | Iteration speed | Faster | Slightly slower |
70
+ | API compatibility | Full | Vec-like |
71
+
72
+ ## When to Use ThinVec
73
+
74
+ ```rust
75
+ // ✅ Good: Many instances, often empty
76
+ struct SparseGraph {
77
+ nodes: Vec<Node>,
78
+ // Most edges lists are empty or small
79
+ edges: Vec<ThinVec<EdgeId>>, // Saves 16 bytes per node
80
+ }
81
+
82
+ // ✅ Good: Nullable collection field
83
+ struct Document {
84
+ content: String,
85
+ attachments: ThinVec<Attachment>, // Often empty
86
+ }
87
+
88
+ // ❌ Avoid: Hot loops, performance-critical iteration
89
+ fn process_hot_path(data: &ThinVec<Item>) {
90
+ // Every length check goes through pointer indirection
91
+ for item in data { // Vec would be faster here
92
+ process(item);
93
+ }
94
+ }
95
+
96
+ // ❌ Avoid: Few instances
97
+ fn main() {
98
+ let single_vec: ThinVec<i32> = ThinVec::new();
99
+ // Saving 16 bytes once is meaningless
100
+ }
101
+ ```
102
+
103
+ ## API Compatibility
104
+
105
+ ```rust
106
+ use thin_vec::{ThinVec, thin_vec};
107
+
108
+ // Constructor macro
109
+ let v: ThinVec<i32> = thin_vec![1, 2, 3];
110
+
111
+ // Familiar Vec-like API
112
+ let mut v = ThinVec::new();
113
+ v.push(1);
114
+ v.push(2);
115
+ v.extend([3, 4, 5]);
116
+ v.pop();
117
+
118
+ // Iteration
119
+ for item in &v {
120
+ println!("{}", item);
121
+ }
122
+
123
+ // Slicing
124
+ let slice: &[i32] = &v[..];
125
+
126
+ // Conversion
127
+ let vec: Vec<i32> = v.into();
128
+ let thin: ThinVec<i32> = vec.into();
129
+ ```
130
+
131
+ ## Cargo.toml
132
+
133
+ ```toml
134
+ [dependencies]
135
+ thin-vec = "0.2"
136
+ ```
137
+
138
+ ## See Also
139
+
140
+ - [mem-smallvec](./mem-smallvec.md) - Stack-allocated small vecs
141
+ - [mem-boxed-slice](./mem-boxed-slice.md) - Fixed-size heap slices
142
+ - [mem-with-capacity](./mem-with-capacity.md) - Pre-allocation strategies