litclaude-ai 0.2.2

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 (156) hide show
  1. package/CHANGELOG.md +155 -0
  2. package/LICENSE +21 -0
  3. package/README.md +369 -0
  4. package/README_ko-KR.md +374 -0
  5. package/RELEASE_CHECKLIST.md +165 -0
  6. package/bin/litclaude-ai.js +643 -0
  7. package/cover.png +0 -0
  8. package/docs/agents.md +67 -0
  9. package/docs/hooks.md +134 -0
  10. package/docs/lsp.md +40 -0
  11. package/docs/migration.md +209 -0
  12. package/docs/workflow-compatibility-audit.md +119 -0
  13. package/generate_cover.py +123 -0
  14. package/package.json +48 -0
  15. package/plugins/litclaude/.claude-plugin/plugin.json +25 -0
  16. package/plugins/litclaude/.lsp.json +13 -0
  17. package/plugins/litclaude/.mcp.json +9 -0
  18. package/plugins/litclaude/agents/boulder-executor.md +12 -0
  19. package/plugins/litclaude/agents/librarian-researcher.md +15 -0
  20. package/plugins/litclaude/agents/oracle-verifier.md +16 -0
  21. package/plugins/litclaude/agents/prometheus-planner.md +13 -0
  22. package/plugins/litclaude/agents/qa-runner.md +16 -0
  23. package/plugins/litclaude/agents/quality-reviewer.md +17 -0
  24. package/plugins/litclaude/bin/litclaude-hook.js +110 -0
  25. package/plugins/litclaude/bin/litclaude-hud.js +271 -0
  26. package/plugins/litclaude/bin/litclaude-lsp-doctor.js +15 -0
  27. package/plugins/litclaude/bin/litclaude-mcp.js +70 -0
  28. package/plugins/litclaude/commands/deep-interview.md +21 -0
  29. package/plugins/litclaude/commands/dynamic-workflow.md +36 -0
  30. package/plugins/litclaude/commands/lit-loop.md +40 -0
  31. package/plugins/litclaude/commands/lit-plan.md +35 -0
  32. package/plugins/litclaude/commands/litgoal.md +30 -0
  33. package/plugins/litclaude/commands/review-work.md +35 -0
  34. package/plugins/litclaude/commands/start-work.md +36 -0
  35. package/plugins/litclaude/hooks/hooks.json +54 -0
  36. package/plugins/litclaude/lib/context-pressure.mjs +25 -0
  37. package/plugins/litclaude/lib/hud-accent-palette.mjs +58 -0
  38. package/plugins/litclaude/lib/litgoal/cli.mjs +266 -0
  39. package/plugins/litclaude/lib/litgoal/ledger.mjs +16 -0
  40. package/plugins/litclaude/lib/litgoal/paths.mjs +7 -0
  41. package/plugins/litclaude/lib/litgoal/state.mjs +67 -0
  42. package/plugins/litclaude/lib/mutated-file-paths.mjs +63 -0
  43. package/plugins/litclaude/lib/start-work-continuation.mjs +99 -0
  44. package/plugins/litclaude/lib/workflow-check.mjs +83 -0
  45. package/plugins/litclaude/skills/ai-slop-remover/SKILL.md +142 -0
  46. package/plugins/litclaude/skills/comment-checker/SKILL.md +55 -0
  47. package/plugins/litclaude/skills/debugging/SKILL.md +70 -0
  48. package/plugins/litclaude/skills/debugging/references/methodology/00-setup.md +108 -0
  49. package/plugins/litclaude/skills/debugging/references/methodology/02-investigate.md +126 -0
  50. package/plugins/litclaude/skills/debugging/references/methodology/04-oracle-triple.md +106 -0
  51. package/plugins/litclaude/skills/debugging/references/methodology/05-escalate.md +69 -0
  52. package/plugins/litclaude/skills/debugging/references/methodology/06-fix.md +116 -0
  53. package/plugins/litclaude/skills/debugging/references/methodology/08-qa.md +94 -0
  54. package/plugins/litclaude/skills/debugging/references/methodology/09-cleanup.md +164 -0
  55. package/plugins/litclaude/skills/debugging/references/methodology/partial-runtime-evidence.md +228 -0
  56. package/plugins/litclaude/skills/debugging/references/runtimes/bundled-js-binary.md +415 -0
  57. package/plugins/litclaude/skills/debugging/references/runtimes/go.md +252 -0
  58. package/plugins/litclaude/skills/debugging/references/runtimes/native-binary.md +484 -0
  59. package/plugins/litclaude/skills/debugging/references/runtimes/node.md +260 -0
  60. package/plugins/litclaude/skills/debugging/references/runtimes/python.md +248 -0
  61. package/plugins/litclaude/skills/debugging/references/runtimes/rust.md +234 -0
  62. package/plugins/litclaude/skills/debugging/references/tools/ghidra.md +212 -0
  63. package/plugins/litclaude/skills/debugging/references/tools/playwright-cli.md +194 -0
  64. package/plugins/litclaude/skills/debugging/references/tools/pwndbg.md +263 -0
  65. package/plugins/litclaude/skills/debugging/references/tools/pwntools.md +265 -0
  66. package/plugins/litclaude/skills/deep-interview/SKILL.md +323 -0
  67. package/plugins/litclaude/skills/deep-interview/scripts/render_progress.py +193 -0
  68. package/plugins/litclaude/skills/frontend-ui-ux/SKILL.md +62 -0
  69. package/plugins/litclaude/skills/lit-loop/SKILL.md +144 -0
  70. package/plugins/litclaude/skills/lit-plan/SKILL.md +125 -0
  71. package/plugins/litclaude/skills/litgoal/SKILL.md +219 -0
  72. package/plugins/litclaude/skills/lsp/SKILL.md +63 -0
  73. package/plugins/litclaude/skills/programming/SKILL.md +106 -0
  74. package/plugins/litclaude/skills/programming/references/go/README.md +90 -0
  75. package/plugins/litclaude/skills/programming/references/go/backend-stack.md +641 -0
  76. package/plugins/litclaude/skills/programming/references/go/bootstrap.md +328 -0
  77. package/plugins/litclaude/skills/programming/references/go/bubbletea-v2.md +360 -0
  78. package/plugins/litclaude/skills/programming/references/go/cobra-stack.md +468 -0
  79. package/plugins/litclaude/skills/programming/references/go/concurrency.md +362 -0
  80. package/plugins/litclaude/skills/programming/references/go/data-modeling.md +329 -0
  81. package/plugins/litclaude/skills/programming/references/go/error-handling.md +359 -0
  82. package/plugins/litclaude/skills/programming/references/go/golangci-strict.md +236 -0
  83. package/plugins/litclaude/skills/programming/references/go/grpc-connect.md +375 -0
  84. package/plugins/litclaude/skills/programming/references/go/libraries.md +337 -0
  85. package/plugins/litclaude/skills/programming/references/go/one-liners.md +202 -0
  86. package/plugins/litclaude/skills/programming/references/go/sqlc-pgx.md +471 -0
  87. package/plugins/litclaude/skills/programming/references/go/testing.md +467 -0
  88. package/plugins/litclaude/skills/programming/references/go/type-patterns.md +298 -0
  89. package/plugins/litclaude/skills/programming/references/python/README.md +314 -0
  90. package/plugins/litclaude/skills/programming/references/python/async-anyio.md +442 -0
  91. package/plugins/litclaude/skills/programming/references/python/data-modeling.md +233 -0
  92. package/plugins/litclaude/skills/programming/references/python/data-processing.md +133 -0
  93. package/plugins/litclaude/skills/programming/references/python/error-handling.md +218 -0
  94. package/plugins/litclaude/skills/programming/references/python/fastapi-stack.md +316 -0
  95. package/plugins/litclaude/skills/programming/references/python/httpx2-optimization.md +360 -0
  96. package/plugins/litclaude/skills/programming/references/python/libraries.md +307 -0
  97. package/plugins/litclaude/skills/programming/references/python/one-liners.md +268 -0
  98. package/plugins/litclaude/skills/programming/references/python/orjson-stack.md +378 -0
  99. package/plugins/litclaude/skills/programming/references/python/pydantic-ai.md +285 -0
  100. package/plugins/litclaude/skills/programming/references/python/pyproject-strict.md +232 -0
  101. package/plugins/litclaude/skills/programming/references/python/textual-tui.md +201 -0
  102. package/plugins/litclaude/skills/programming/references/python/type-patterns.md +176 -0
  103. package/plugins/litclaude/skills/programming/references/rust/README.md +317 -0
  104. package/plugins/litclaude/skills/programming/references/rust/async-tokio.md +299 -0
  105. package/plugins/litclaude/skills/programming/references/rust/axum-stack.md +467 -0
  106. package/plugins/litclaude/skills/programming/references/rust/cargo-strict.md +317 -0
  107. package/plugins/litclaude/skills/programming/references/rust/clap-stack.md +409 -0
  108. package/plugins/litclaude/skills/programming/references/rust/concurrency.md +375 -0
  109. package/plugins/litclaude/skills/programming/references/rust/libraries.md +439 -0
  110. package/plugins/litclaude/skills/programming/references/rust/one-liners.md +291 -0
  111. package/plugins/litclaude/skills/programming/references/rust/proptest-insta.md +429 -0
  112. package/plugins/litclaude/skills/programming/references/rust/type-state.md +354 -0
  113. package/plugins/litclaude/skills/programming/references/rust/unsafe-discipline.md +250 -0
  114. package/plugins/litclaude/skills/programming/references/rust/zero-cost-safety.md +527 -0
  115. package/plugins/litclaude/skills/programming/references/rust-ub/README.md +289 -0
  116. package/plugins/litclaude/skills/programming/references/rust-ub/miri-sanitizers-loom.md +411 -0
  117. package/plugins/litclaude/skills/programming/references/rust-ub/ub-taxonomy.md +269 -0
  118. package/plugins/litclaude/skills/programming/references/typescript/README.md +195 -0
  119. package/plugins/litclaude/skills/programming/references/typescript/backend-hono.md +672 -0
  120. package/plugins/litclaude/skills/programming/references/typescript/bootstrap.md +199 -0
  121. package/plugins/litclaude/skills/programming/references/typescript/data-modeling.md +202 -0
  122. package/plugins/litclaude/skills/programming/references/typescript/error-handling.md +169 -0
  123. package/plugins/litclaude/skills/programming/references/typescript/tsconfig-strict.md +152 -0
  124. package/plugins/litclaude/skills/programming/references/typescript/type-patterns.md +196 -0
  125. package/plugins/litclaude/skills/programming/scripts/go/check-no-excuse-rules.sh +173 -0
  126. package/plugins/litclaude/skills/programming/scripts/go/new-project.py +138 -0
  127. package/plugins/litclaude/skills/programming/scripts/go/templates/.editorconfig +13 -0
  128. package/plugins/litclaude/skills/programming/scripts/go/templates/.golangci.yml +95 -0
  129. package/plugins/litclaude/skills/programming/scripts/go/templates/AGENTS.md.tmpl +24 -0
  130. package/plugins/litclaude/skills/programming/scripts/go/templates/README.md.tmpl +12 -0
  131. package/plugins/litclaude/skills/programming/scripts/go/templates/Taskfile.yml +40 -0
  132. package/plugins/litclaude/skills/programming/scripts/go/templates/ci.yml +37 -0
  133. package/plugins/litclaude/skills/programming/scripts/go/templates/config.go +24 -0
  134. package/plugins/litclaude/skills/programming/scripts/go/templates/gitignore +15 -0
  135. package/plugins/litclaude/skills/programming/scripts/go/templates/main.go.tmpl +22 -0
  136. package/plugins/litclaude/skills/programming/scripts/go/templates/run.go +15 -0
  137. package/plugins/litclaude/skills/programming/scripts/python/check-no-excuse-rules.py +687 -0
  138. package/plugins/litclaude/skills/programming/scripts/python/new-project.py +172 -0
  139. package/plugins/litclaude/skills/programming/scripts/python/new-script.py +116 -0
  140. package/plugins/litclaude/skills/programming/scripts/rust/check-no-excuse-rules.py +296 -0
  141. package/plugins/litclaude/skills/programming/scripts/rust/check-no-excuse-rules.sh +158 -0
  142. package/plugins/litclaude/skills/programming/scripts/rust/new-project.py +175 -0
  143. package/plugins/litclaude/skills/programming/scripts/typescript/check-no-excuse-rules.ts +282 -0
  144. package/plugins/litclaude/skills/programming/scripts/typescript/new-project.ts +177 -0
  145. package/plugins/litclaude/skills/refactor/SKILL.md +73 -0
  146. package/plugins/litclaude/skills/remove-ai-slops/SKILL.md +52 -0
  147. package/plugins/litclaude/skills/review-work/SKILL.md +331 -0
  148. package/plugins/litclaude/skills/rules/SKILL.md +66 -0
  149. package/plugins/litclaude/skills/start-work/SKILL.md +132 -0
  150. package/scripts/audit-plan-checkboxes.mjs +37 -0
  151. package/scripts/doctor.mjs +41 -0
  152. package/scripts/inspect-agent-tools.mjs +27 -0
  153. package/scripts/postinstall.mjs +50 -0
  154. package/scripts/qa-claude-plugin-smoke.sh +60 -0
  155. package/scripts/qa-portable-install.sh +136 -0
  156. package/scripts/validate-plugin.mjs +72 -0
@@ -0,0 +1,527 @@
1
+ # Zero-Cost Safety — Zig Ergonomics in Rust
2
+
3
+ Rust already owns memory safety. This reference adds the patterns that give you Zig's *ergonomic* safety — explicit allocation control, compile-time computation, zero-hidden-cost APIs, bit-level layout, and deterministic cleanup — without leaving the Rust toolchain.
4
+
5
+ **When to load this file:** arena, allocator, bumpalo, const fn, const generics, comptime, zero-alloc, no-alloc, slice-based API, `#[repr]`, packed struct, bitfield, scopeguard, errdefer, RAII cleanup, Zig-like patterns.
6
+
7
+ ---
8
+
9
+ ## 1. Explicit Allocators — Arena Pattern
10
+
11
+ Zig passes `allocator: Allocator` to every function. Rust's stable equivalent: arena crates that make allocation scope visible and bulk-freeable.
12
+
13
+ ### bumpalo — The Default Arena
14
+
15
+ ```rust
16
+ use bumpalo::Bump;
17
+
18
+ fn parse_tokens<'a>(arena: &'a Bump, input: &[u8]) -> Vec<&'a str> {
19
+ // All allocations go into `arena`. Caller controls lifetime.
20
+ // When `arena` drops, everything frees in one shot.
21
+ let token = arena.alloc_str("hello");
22
+ let slice = arena.alloc_slice_copy(&[1u8, 2, 3]);
23
+ vec![token] // Vec itself is on heap; contents point into arena
24
+ }
25
+
26
+ // Usage: caller owns the arena, decides when memory dies.
27
+ let arena = Bump::new();
28
+ let tokens = parse_tokens(&arena, b"...");
29
+ drop(arena); // all arena memory freed, zero individual deallocations
30
+ ```
31
+
32
+ **When to use:** parsers, compilers, game frame allocators, request-scoped web handlers, any hot loop where individual `Box`/`Vec` alloc+free overhead matters.
33
+
34
+ ### typed-arena — Homogeneous Arena
35
+
36
+ ```rust
37
+ use typed_arena::Arena;
38
+
39
+ struct AstNode { kind: u8, children: Vec<&'static AstNode> } // simplified
40
+
41
+ let node_arena: Arena<AstNode> = Arena::new();
42
+ let root = node_arena.alloc(AstNode { kind: 0, children: vec![] });
43
+ // All nodes share arena lifetime. No individual free.
44
+ ```
45
+
46
+ **When to use:** tree/graph structures where all nodes have the same type and same lifetime.
47
+
48
+ ### allocator_api (nightly) — Full Zig Parity
49
+
50
+ ```rust
51
+ #![feature(allocator_api)]
52
+ use std::alloc::Global;
53
+
54
+ // Vec parameterized by allocator — exactly like Zig.
55
+ let v: Vec<u8, &Bump> = Vec::new_in(&arena);
56
+
57
+ // Custom allocator for tracking, limiting, or redirecting allocation
58
+ struct CountingAlloc { inner: Global, count: AtomicUsize }
59
+ unsafe impl Allocator for CountingAlloc { /* ... */ }
60
+ ```
61
+
62
+ **When to use:** when you need allocator-generic data structures on nightly. For stable code, prefer `bumpalo` directly.
63
+
64
+ ### Decision Tree
65
+
66
+ ```
67
+ Need arena allocation?
68
+ ├── All items same type, same lifetime → typed-arena
69
+ ├── Mixed types, same lifetime → bumpalo
70
+ ├── Need allocator-generic containers → allocator_api (nightly)
71
+ └── Just need fewer allocations → SmallVec / ArrayVec / tinyvec (stack-first)
72
+ ```
73
+
74
+ ### Cargo.toml
75
+
76
+ ```toml
77
+ bumpalo = { version = "3", features = ["collections"] }
78
+ typed-arena = "2"
79
+ smallvec = { version = "1", features = ["union", "const_generics"] }
80
+ tinyvec = { version = "1", features = ["alloc"] }
81
+ ```
82
+
83
+ ---
84
+
85
+ ## 2. Compile-Time Computation — const fn, const generics, proc macros
86
+
87
+ Zig's `comptime` runs arbitrary code at compile time. Rust splits this across three mechanisms.
88
+
89
+ ### const fn — Compile-Time Pure Functions
90
+
91
+ ```rust
92
+ const fn fibonacci(n: usize) -> usize {
93
+ match n {
94
+ 0 => 0,
95
+ 1 => 1,
96
+ _ => fibonacci(n - 1) + fibonacci(n - 2),
97
+ }
98
+ }
99
+
100
+ const FIB_20: usize = fibonacci(20); // computed at compile time: 6765
101
+
102
+ // Use in array sizes
103
+ const LOOKUP: [u8; 256] = {
104
+ let mut table = [0u8; 256];
105
+ let mut i = 0;
106
+ while i < 256 {
107
+ table[i] = (i as u8).wrapping_mul(7);
108
+ i += 1;
109
+ }
110
+ table
111
+ };
112
+ ```
113
+
114
+ **Stable since Rust 1.82:** `const fn` supports `match`, loops, `if`, references, mutable locals — nearly full Rust. Use `const { }` blocks (Rust 1.79+) for inline compile-time assertions.
115
+
116
+ ```rust
117
+ fn process<const N: usize>(data: &[u8; N]) {
118
+ const { assert!(N > 0, "N must be positive") }; // compile-time panic if N == 0
119
+ // ...
120
+ }
121
+ ```
122
+
123
+ ### const generics — Type-Level Values
124
+
125
+ ```rust
126
+ struct Buffer<const N: usize> {
127
+ data: [u8; N],
128
+ len: usize,
129
+ }
130
+
131
+ impl<const N: usize> Buffer<N> {
132
+ const fn new() -> Self {
133
+ Self { data: [0; N], len: 0 }
134
+ }
135
+
136
+ fn push(&mut self, byte: u8) -> Result<(), BufferFullError> {
137
+ if self.len >= N { return Err(BufferFullError); }
138
+ self.data[self.len] = byte;
139
+ self.len += 1;
140
+ Ok(())
141
+ }
142
+ }
143
+
144
+ // Compiler enforces: Buffer<16> and Buffer<32> are distinct types.
145
+ let small: Buffer<16> = Buffer::new();
146
+ let large: Buffer<1024> = Buffer::new();
147
+ ```
148
+
149
+ ### proc macros — Code Generation (Zig comptime type creation)
150
+
151
+ When `const fn` is not enough (generating struct fields, impl blocks, or derive logic), proc macros fill the gap.
152
+
153
+ ```rust
154
+ // In a proc-macro crate:
155
+ use proc_macro::TokenStream;
156
+ use quote::quote;
157
+ use syn::{parse_macro_input, DeriveInput};
158
+
159
+ #[proc_macro_derive(Builder)]
160
+ pub fn derive_builder(input: TokenStream) -> TokenStream {
161
+ let input = parse_macro_input!(input as DeriveInput);
162
+ let name = &input.ident;
163
+ // ... generate builder struct and impl
164
+ TokenStream::from(quote! {
165
+ impl #name {
166
+ pub fn builder() -> #name##Builder { /* ... */ }
167
+ }
168
+ })
169
+ }
170
+ ```
171
+
172
+ **Decision tree:**
173
+
174
+ ```
175
+ Need compile-time value computation? → const fn
176
+ Need type parameterized by value? → const generics
177
+ Need to generate new types/impls? → proc macro (derive or attribute)
178
+ Need compile-time string processing? → proc macro
179
+ Need typenum-level arithmetic? → typenum / generic-array (rare)
180
+ ```
181
+
182
+ ---
183
+
184
+ ## 3. Zero-Allocation API Design — No Hidden Costs
185
+
186
+ Zig's philosophy: no operator overloading, no hidden allocation, every cost visible. Rust achieves this with discipline.
187
+
188
+ ### Slice-Based APIs — Caller Owns Memory
189
+
190
+ ```rust
191
+ // BAD: hidden allocation in return type
192
+ fn process(input: &str) -> String {
193
+ input.to_uppercase() // allocates
194
+ }
195
+
196
+ // GOOD: caller provides output buffer, zero allocation
197
+ fn process(input: &[u8], output: &mut [u8]) -> usize {
198
+ let len = input.len().min(output.len());
199
+ for i in 0..len {
200
+ output[i] = input[i].to_ascii_uppercase();
201
+ }
202
+ len // returns bytes written
203
+ }
204
+
205
+ // GOOD: return borrowed data when possible
206
+ fn find_token<'a>(input: &'a str) -> Option<&'a str> {
207
+ input.split_whitespace().next() // no allocation — borrows from input
208
+ }
209
+ ```
210
+
211
+ ### try_* APIs — Fallible Allocation
212
+
213
+ ```rust
214
+ // Allocation can fail explicitly (like Zig's allocator returning error)
215
+ let mut v = Vec::new();
216
+ v.try_reserve(1_000_000)?; // returns Result, not panic
217
+
218
+ // For Box:
219
+ let b = Box::try_new(42)?; // nightly, or use allocator_api
220
+ ```
221
+
222
+ ### SmallVec / ArrayVec — Stack-First Collections
223
+
224
+ ```rust
225
+ use smallvec::SmallVec;
226
+ use arrayvec::ArrayVec;
227
+
228
+ // SmallVec: stack for small counts, heap spillover for large
229
+ let mut tags: SmallVec<[u8; 8]> = SmallVec::new();
230
+ tags.push(1); // on stack if <= 8 elements
231
+
232
+ // ArrayVec: purely stack, fixed capacity, no heap ever
233
+ let mut buf: ArrayVec<u8, 64> = ArrayVec::new();
234
+ buf.try_push(42).map_err(|_| "full")?; // returns error instead of panic
235
+ ```
236
+
237
+ ### Cow — Defer Allocation Until Mutation
238
+
239
+ ```rust
240
+ use std::borrow::Cow;
241
+
242
+ fn normalize(input: &str) -> Cow<'_, str> {
243
+ if input.contains('\t') {
244
+ Cow::Owned(input.replace('\t', " ")) // allocates only when needed
245
+ } else {
246
+ Cow::Borrowed(input) // zero-cost pass-through
247
+ }
248
+ }
249
+ ```
250
+
251
+ ### The #![no_std] Discipline
252
+
253
+ For maximum allocation control, go `#![no_std]`:
254
+
255
+ ```rust
256
+ #![no_std]
257
+ extern crate alloc; // opt-in to heap when needed
258
+
259
+ use alloc::vec::Vec; // explicit: I chose to allocate
260
+ use alloc::string::String; // explicit: I chose to allocate
261
+ ```
262
+
263
+ Even in `std` code, the *mindset* applies: prefer `&[T]` over `Vec<T>` in function signatures, `&str` over `String`, `&Path` over `PathBuf`.
264
+
265
+ ### Clippy Lints for Hidden Allocations
266
+
267
+ ```toml
268
+ # Cargo.toml — catch accidental allocations
269
+ [lints.clippy]
270
+ # These warn on patterns that allocate when a borrow would suffice:
271
+ unnecessary_to_owned = "warn" # .to_string() / .to_vec() when borrow works
272
+ redundant_clone = "warn" # .clone() that's immediately consumed
273
+ large_stack_arrays = "warn" # accidental large stack usage
274
+ vec_init_then_push = "warn" # Vec::new() + push instead of vec![]
275
+ ```
276
+
277
+ ---
278
+
279
+ ## 4. Bit-Level Layout — repr, Packed Structs, Bitfields
280
+
281
+ Zig: `packed struct` with bit-level field control. Rust matches with `#[repr]` attributes and bitfield crates.
282
+
283
+ ### #[repr(C)] — Guaranteed C-Compatible Layout
284
+
285
+ ```rust
286
+ #[repr(C)]
287
+ struct Header {
288
+ magic: [u8; 4],
289
+ version: u16,
290
+ flags: u16,
291
+ length: u32,
292
+ }
293
+ // Layout is C ABI: fields in declaration order, C padding rules.
294
+ // Safe to transmute from/to byte arrays via zerocopy.
295
+ ```
296
+
297
+ ### #[repr(C, packed)] — No Padding
298
+
299
+ ```rust
300
+ #[repr(C, packed)]
301
+ struct WireHeader {
302
+ tag: u8,
303
+ length: u16, // NOT aligned to 2-byte boundary
304
+ checksum: u32,
305
+ }
306
+ // Total size: exactly 7 bytes. No padding.
307
+ // WARNING: taking &self.length is UB if unaligned. Use read_unaligned or zerocopy.
308
+ ```
309
+
310
+ **Safe access pattern:**
311
+
312
+ ```rust
313
+ use std::ptr;
314
+
315
+ impl WireHeader {
316
+ fn length(&self) -> u16 {
317
+ // SAFETY: packed field may be unaligned; ptr::read_unaligned handles this.
318
+ unsafe { ptr::read_unaligned(ptr::addr_of!(self.length)) }
319
+ }
320
+ }
321
+
322
+ // Better: use zerocopy to avoid manual unsafe entirely
323
+ use zerocopy::{FromBytes, IntoBytes, KnownLayout, Immutable};
324
+
325
+ #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
326
+ #[repr(C, packed)]
327
+ struct WireHeader {
328
+ tag: u8,
329
+ length: [u8; 2], // manual byte array avoids alignment issues
330
+ checksum: [u8; 4],
331
+ }
332
+
333
+ impl WireHeader {
334
+ fn length(&self) -> u16 { u16::from_le_bytes(self.length) }
335
+ fn checksum(&self) -> u32 { u32::from_le_bytes(self.checksum) }
336
+ }
337
+ ```
338
+
339
+ ### bitfield — Bit-Level Flag Packing
340
+
341
+ ```rust
342
+ use bitfield::bitfield;
343
+
344
+ bitfield! {
345
+ pub struct Permissions(u8);
346
+ impl Debug;
347
+ pub bool, readable, set_readable: 0;
348
+ pub bool, writable, set_writable: 1;
349
+ pub bool, executable, set_executable: 2;
350
+ pub u8, level, set_level: 5, 3; // bits 3-5
351
+ }
352
+
353
+ let mut p = Permissions(0);
354
+ p.set_readable(true);
355
+ p.set_level(5);
356
+ assert!(p.readable());
357
+ assert_eq!(p.level(), 5);
358
+ ```
359
+
360
+ ### modular-bitfield — Richer Bitfield API
361
+
362
+ ```rust
363
+ use modular_bitfield::prelude::*;
364
+
365
+ #[bitfield(bits = 16)]
366
+ #[derive(Debug)]
367
+ pub struct StatusWord {
368
+ ready: bool, // 1 bit
369
+ error_code: B4, // 4 bits
370
+ #[skip] __: B3, // 3 bits padding
371
+ priority: B8, // 8 bits
372
+ }
373
+ ```
374
+
375
+ ### zerocopy — Safe Zero-Copy Parsing
376
+
377
+ ```rust
378
+ use zerocopy::{FromBytes, IntoBytes, KnownLayout, Immutable, Ref};
379
+
380
+ #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
381
+ #[repr(C)]
382
+ struct Packet {
383
+ header: [u8; 4],
384
+ payload_len: u32,
385
+ }
386
+
387
+ fn parse(bytes: &[u8]) -> Option<&Packet> {
388
+ Ref::<_, Packet>::from_prefix(bytes).map(|(pkt, _rest)| pkt.into_ref()).ok()
389
+ }
390
+ // Zero-copy, zero-allocation, fully safe. No transmute, no pointer cast.
391
+ ```
392
+
393
+ ### Cargo.toml
394
+
395
+ ```toml
396
+ zerocopy = { version = "0.8", features = ["derive"] }
397
+ bitfield = "0.17"
398
+ modular-bitfield = "0.11"
399
+ bytemuck = { version = "1", features = ["derive"] } # alternative to zerocopy
400
+ ```
401
+
402
+ ---
403
+
404
+ ## 5. Scope Guards — errdefer / Deterministic Cleanup
405
+
406
+ Zig's `errdefer` runs cleanup only on error paths. Rust's `Drop` always runs, but `scopeguard` gives fine-grained control.
407
+
408
+ ### scopeguard — The errdefer Equivalent
409
+
410
+ ```rust
411
+ use scopeguard::{defer, guard};
412
+ use std::fs;
413
+
414
+ fn create_and_process(path: &str) -> std::io::Result<()> {
415
+ let file = fs::File::create(path)?;
416
+ // If anything below fails, clean up the file.
417
+ // This is exactly Zig's errdefer.
418
+ let _cleanup = guard((), |_| {
419
+ let _ = fs::remove_file(path);
420
+ });
421
+
422
+ write_data(&file)?;
423
+ validate_data(path)?;
424
+
425
+ // Success: defuse the guard so it does NOT run cleanup.
426
+ std::mem::forget(_cleanup);
427
+ Ok(())
428
+ }
429
+ ```
430
+
431
+ ### defer! — Always-Run Cleanup (like Zig's defer)
432
+
433
+ ```rust
434
+ use scopeguard::defer;
435
+
436
+ fn with_temp_dir() -> anyhow::Result<()> {
437
+ let dir = tempfile::tempdir()?;
438
+ defer! {
439
+ // Runs when scope exits, success or failure.
440
+ println!("Cleaning up {}", dir.path().display());
441
+ // dir's Drop also cleans up, but this shows the pattern.
442
+ }
443
+
444
+ do_work(dir.path())?;
445
+ Ok(())
446
+ }
447
+ ```
448
+
449
+ ### Drop as RAII Cleanup
450
+
451
+ ```rust
452
+ struct TempFile { path: std::path::PathBuf }
453
+
454
+ impl TempFile {
455
+ fn new(path: impl Into<std::path::PathBuf>) -> std::io::Result<Self> {
456
+ let path = path.into();
457
+ std::fs::File::create(&path)?;
458
+ Ok(Self { path })
459
+ }
460
+ }
461
+
462
+ impl Drop for TempFile {
463
+ fn drop(&mut self) {
464
+ let _ = std::fs::remove_file(&self.path);
465
+ }
466
+ }
467
+
468
+ // Usage: file is auto-cleaned when `tmp` goes out of scope.
469
+ let tmp = TempFile::new("/tmp/scratch.dat")?;
470
+ ```
471
+
472
+ ### The errdefer Pattern — Defuse on Success
473
+
474
+ The key insight from Zig's `errdefer`: you want cleanup on error but NOT on success. In Rust:
475
+
476
+ ```rust
477
+ use scopeguard::ScopeGuard;
478
+
479
+ fn deploy(artifact: &Path) -> Result<(), DeployError> {
480
+ let backup = backup_current()?;
481
+
482
+ // errdefer: restore backup if anything fails
483
+ let rollback = guard(backup.clone(), |b| {
484
+ let _ = restore_from_backup(&b);
485
+ });
486
+
487
+ upload(artifact)?;
488
+ health_check()?;
489
+
490
+ // Success path: defuse the rollback guard
491
+ ScopeGuard::into_inner(rollback);
492
+ Ok(())
493
+ }
494
+ ```
495
+
496
+ ### Cargo.toml
497
+
498
+ ```toml
499
+ scopeguard = "1"
500
+ tempfile = "3" # idiomatic RAII temp files/dirs
501
+ ```
502
+
503
+ ---
504
+
505
+ ## Summary: Zig Advantage → Rust Pattern
506
+
507
+ | Zig Feature | Rust Equivalent | Difficulty | Reference |
508
+ |---|---|---|---|
509
+ | Explicit allocator passing | `bumpalo` / `typed-arena` / `allocator_api` | Easy | §1 |
510
+ | `comptime` value computation | `const fn` + `const { }` blocks | Easy | §2 |
511
+ | `comptime` type generation | proc macros (derive / attribute) | Medium | §2 |
512
+ | No hidden allocations | `#![no_std]` / slice-based APIs / `Cow` | Style choice | §3 |
513
+ | `packed struct` / bitfields | `#[repr(C, packed)]` / `bitfield` / `zerocopy` | Easy | §4 |
514
+ | `errdefer` | `scopeguard::guard` + defuse on success | Easy | §5 |
515
+ | `defer` | `scopeguard::defer!` / `Drop` | Easy | §5 |
516
+
517
+ All achievable within Rust's single toolchain. You get Zig's explicitness **plus** the borrow checker, lifetime analysis, trait bounds, and `miri`. The combination is strictly more powerful than either alone.
518
+
519
+ ## When NOT to Use These Patterns
520
+
521
+ - **Arena allocation** overkill for simple CLI tools that allocate once and exit.
522
+ - **Zero-alloc APIs** hurt readability when the function naturally produces owned data. Don't force `&mut [u8]` output buffers on a function that logically returns `String`.
523
+ - **`#[repr(packed)]`** only for wire formats and FFI. Never for regular domain types.
524
+ - **Scope guards** unnecessary when `Drop` on the value itself handles cleanup (e.g., `tempfile::NamedTempFile` already does this).
525
+ - **`const fn`** everything? No — only when the value is genuinely needed at compile time or the function is trivially const-eligible. Don't contort logic just to be const.
526
+
527
+ The goal is **visible costs and explicit control**, not asceticism. Use `String` and `Vec` freely when they're the right tool. Reach for these patterns when allocation behavior matters for correctness or performance.