lib/alloc/phase/src/input/root.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 //! ## Package overview
  2 //!
  3 //! When we ingest external input from streams or files, we want to accept
  4 //! bounded payloads using a single reusable byte allocation without allocating
  5 //! on every message or resizing buffers on the fly. We configure an explicit
  6 //! upper bound on accepted length, allocate storage once, and reuse that
  7 //! storage across successive operations while detecting oversized inputs before
  8 //! admitting them.
  9 //!
 10 //! ## One buffer and lookahead
 11 //!
 12 //! The core challenge in bounded ingestion sits at the boundary of the limit.
 13 //! If we configure our system to accept at most `n` bytes and allocate an
 14 //! `n`-byte buffer, filling that buffer completely leaves an ambiguity: did the
 15 //! input stream end precisely at `n` bytes, or does more data remain waiting in
 16 //! the channel? To resolve whether the input fits or exceeds our boundary, this
 17 //! implementation reserves space for one extra byte. For an accepted limit of
 18 //! `n` bytes, the backing buffer holds `n + 1` bytes. When we read from the
 19 //! source into the buffer:
 20 //!
 21 //! - If the source yields between 0 and `n` bytes before reaching end-of-file,
 22 //!   the input fits within our configured boundary and we admit it.
 23 //! - If the source yields `n + 1` bytes, the input exceeds our limit and we
 24 //!   reject it immediately, without allocating a second buffer.
 25 //!
 26 //! We term this calculation *capacity derivation*. The standard helper
 27 //! `deriveCapacity` computes this boundary for an owner. Given a configuration
 28 //! structure containing a byte limit field of type `usize`, it uses checked
 29 //! integer addition to compute `n + 1`. If adding one to the limit overflows
 30 //! `usize`, derivation fails with `error.CapacityOverflow`. When a caller
 31 //! configures a limit of zero, derivation reserves one byte, which allows an
 32 //! empty input to be distinguished from an input containing data.
 33 //!
 34 //! The `deriveCapacity` helper initializes only two fields in the resulting
 35 //! capacity record: the configured limit and the derived `storage_bytes`. The
 36 //! limit field name and `storage_bytes` must be distinct. Any additional fields
 37 //! declared on the capacity type remain undefined, so a custom capacity type
 38 //! that requires extra fields must populate them in a custom derivation
 39 //! function.
 40 //!
 41 //! The generic container `OneRegion(Spec)` produces an allocator-backed owner
 42 //! around this storage model. While `deriveCapacity` enforces the standard `n +
 43 //! 1` sizing rule, a custom derivation function may describe larger storage
 44 //! when required by domain constraints: derivation computes a `Capacity` value,
 45 //! while `init` allocates the storage. The owner asserts that `storage_bytes`
 46 //! strictly exceeds the configured input limit.
 47 //!
 48 //! ## A successful borrow and release
 49 //!
 50 //! Because a single byte buffer is reused across requests, concurrent access
 51 //! would corrupt in-flight payloads. An outstanding borrow represents temporary
 52 //! exclusive access granted to an admitted input. Until that borrow is
 53 //! relinquished, the owner enforces busy protection across subsequent
 54 //! acquisition and preflight calls.
 55 //!
 56 //! The lifecycle of an input owner progresses through three sequential phases:
 57 //! initialization, steady operation, and teardown. Calling `init` enters the
 58 //! initialization phase, calling `activate` advances to steady operation, and
 59 //! calling `deinit` enters teardown. Calling `deinit` requires that no borrow
 60 //! remains outstanding. If startup fails prior to activation, `deinit` can be
 61 //! called directly from the initialization phase to free the buffer.
 62 //!
 63 //! During initialization, `init` derives the capacity and requests a single
 64 //! contiguous slice of `storage_bytes` from the provided allocator. If capacity
 65 //! derivation overflows or the allocator fails, `init` returns an error union
 66 //! of `DeriveError` and `std.mem.Allocator.Error`. Once allocated, the owner
 67 //! retains the byte slice but does not retain an allocator handle. In steady
 68 //! operation, the owner methods do not call the initialization allocator. The
 69 //! absence of a retained allocator on the owner does not prevent arbitrary
 70 //! readers or filesystem code from allocating dynamically or performing
 71 //! external work.
 72 //!
 73 //! Phase transitions are guarded by debug assertions (`std.debug.assert`),
 74 //! which verify that `activate` is called only from the initialization phase
 75 //! and that `deinit` is called with no active borrow. These debug assertions
 76 //! differ from the explicit wrong-phase panics enforced by the separate phase
 77 //! allocator.
 78 //!
 79 //! In steady operation, calling `read` ingests data into the buffer and admits
 80 //! the payload if the returned length does not exceed the configured limit. A
 81 //! successful read returns a borrowed constant slice (`[]const u8`) and sets
 82 //! the internal `in_use` flag. Even an empty zero-byte read establishes an
 83 //! active borrow and marks the owner busy. While `in_use` remains true, any
 84 //! attempt to read, window, or preflight another input returns `in_use_error`.
 85 //! This failure indicates a busy owner and does not increment the capacity
 86 //! rejection counter.
 87 //!
 88 //! When the caller finishes processing the borrowed slice, it invokes
 89 //! `release`. Calling `release` sets `in_use` to false and resets the loaded
 90 //! byte counter to zero. It does not zero or scrub the underlying memory, nor
 91 //! does it reset historical rejection counts or high-water marks.
 92 //!
 93 //! Because reads overwrite the backing buffer, a caller that needs to retain
 94 //! admitted bytes across subsequent operations must copy them into separate
 95 //! storage before calling `release`. A fixed stack array provides a convenient
 96 //! target for preserving small records without allocating heap memory.
 97 //!
 98 //! Copies of an owner struct share the underlying byte slice while duplicating
 99 //! internal bookkeeping. Because copies are not independent owners, callers
100 //! must serialize operations and ensure that cleanup occurs exactly once.
101 //! Calling `deinit` requires that no borrow remains outstanding, transitions
102 //! the phase to teardown, and frees the slice using the same allocator passed
103 //! during initialization. The owner provides no secondary abort or partial
104 //! teardown routines.
105 //!
106 //! In the Issue tool, body storage adopts this borrow discipline. Its
107 //! `BodySource` container pairs a borrowed slice of the input region with an
108 //! optional pointer to the owner. When processing finishes or an empty body
109 //! triggers an early exit, the consumer releases the borrow before reporting
110 //! results. Command-line arguments provided directly in the process invocation
111 //! bypass the input region entirely, leaving the buffer available for file or
112 //! standard-input ingestion.
113 //!
114 //! ## Failure and recovery
115 //!
116 //! When an incoming payload exceeds the configured limit, the owner rejects the
117 //! admission. How the owner responds to this overload depends on whether it is
118 //! configured with a terminal or recoverable policy:
119 //!
120 //! - A terminal owner treats an oversized input as a permanent boundary fault.
121 //!   Upon rejection, it increments a saturating 64-bit rejection counter, sets
122 //!   an internal `terminal` flag, and refuses all subsequent read attempts with
123 //!   `capacity_error` without incrementing the counter again.
124 //! - A recoverable owner increments the rejection counter but leaves `terminal`
125 //!   false. Storage remains immediately available to accept another input
126 //!   without an acknowledgement step.
127 //!
128 //! Recovery denotes the ability to reuse the owned memory buffer for a future
129 //! request: it does not imply stream rewinding, transaction rollback, or
130 //! automatic framing.
131 //!
132 //! When reading from a stream through `Reader.readSliceShort`, capacity
133 //! rejection under the standard derivation helper occurs after reading up to
134 //! `limit + 1` logical bytes into the buffer. The owner does not drain any
135 //! remaining bytes left in the underlying stream. If an external caller
136 //! attempts to read from that same stream again, the retry does not guarantee
137 //! alignment with the start of a logical record. User reader implementations
138 //! may also maintain internal buffers or perform dynamic allocations outside
139 //! the owner's knowledge. If a stream encounters an I/O failure such as
140 //! `ReadFailed`, the failure can consume source bytes and overwrite buffer
141 //! contents. In that situation, no borrow is admitted and the owner's capacity
142 //! rejection counter does not increment.
143 //!
144 //! To avoid reading unwanted bytes when an input size is known beforehand, an
145 //! application can call `preflight`. The `preflight` method accepts an expected
146 //! size as a 64-bit integer, checks that the owner is available, and verifies
147 //! that the size fits within `usize` and does not exceed the limit. If the
148 //! proposed size cannot be represented in `usize` or exceeds the limit,
149 //! `preflight` rejects the request, updates rejection accounting, and returns
150 //! `capacity_error`. A successful preflight verifies available space, but it
151 //! neither reserves storage nor forms an atomic transaction with a subsequent
152 //! read.
153 //!
154 //! Calling `status` returns a snapshot structure by value containing the
155 //! current phase, the `in_use` flag, the configured limit, the declared storage
156 //! size, the currently loaded bytes, the high-water mark of admitted bytes, the
157 //! cumulative rejection count, and the terminal flag for terminal owners. The
158 //! high-water mark records the largest admitted input, ignoring rejected
159 //! attempts. Following `deinit`, the historical counters and declared capacity
160 //! fields remain readable in the returned status snapshot, which means
161 //! `storage_bytes` reports declared storage size rather than live retained heap
162 //! memory.
163 //!
164 //! The Peek image decoding pipeline relies on a recoverable configuration. Its
165 //! loader reads image files into the input buffer, holds the borrow while
166 //! decoding pixel data into external image structures, and releases the owner
167 //! immediately after decoding. If an oversized image is rejected, the owner
168 //! remains active, enabling subsequent file reads to reuse the same memory
169 //! allocation.
170 //!
171 //! ## Whole files versus windows
172 //!
173 //! Reading files introduces distinct concerns regarding whole-file ingestion
174 //! versus positional slice inspection.
175 //!
176 //! Calling `readFile` reads an input file into the bounded buffer using the
177 //! standard library directory interface. When reading an ordinary file whose
178 //! size exceeds the limit, the reader fills the buffer prefix and the owner
179 //! rejects the operation. The acquisition specification provides a
180 //! configuration flag named `map_file_too_big`:
181 //!
182 //! - When `map_file_too_big` is enabled, an underlying `FileTooBig` error
183 //!   returned by the filesystem maps directly into the owner's capacity
184 //!   rejection, incrementing the rejection counter and setting the terminal
185 //!   flag if configured.
186 //! - When `map_file_too_big` is disabled, `FileTooBig` propagates outward as a
187 //!   filesystem error, bypassing rejection accounting and leaving the terminal
188 //!   flag unset.
189 //! - Other filesystem errors, such as missing files or access faults, propagate
190 //!   unchanged under either setting without modifying capacity counters.
191 //!
192 //! When inputs exceed the capacity of our buffer, reading the entire file at
193 //! once is impossible. Instead, we inspect bounded portions of the file using
194 //! `readFileWindow`.
195 //!
196 //! Calling `readFileWindow` requires that file acquisition is enabled, that
197 //! storage is available, and that the requested window length satisfies `0 <
198 //! window_bytes <= limit`. The method reads up to `window_bytes + 1` bytes at a
199 //! specified file offset, admits `min(read_count, window_bytes)`, and returns a
200 //! `FileWindow` structure containing the borrowed slice and a boolean
201 //! `complete` flag.
202 //!
203 //! If the file contains bytes beyond the requested window, the lookahead byte
204 //! is populated, `complete` is set to false, and the admitted slice contains
205 //! exactly `window_bytes`. An incomplete window read does not trigger a
206 //! capacity rejection, even when the owner is configured as terminal. If the
207 //! offset sits at end-of-file, a zero-byte read completes successfully and
208 //! still establishes an active borrow. The `complete` flag describes only the
209 //! result of this specific positional read: it does not provide an
210 //! instantaneous file-length snapshot or guarantee that the file will not grow
211 //! concurrently.
212 //!
213 //! Glom demonstrates how windowed ingestion coordinates with record framing.
214 //! Glom ingests structured transcript files using a terminal input owner with
215 //! preflight enabled. Because individual transcript records vary in length and
216 //! files can grow large, its parser reads a positional window from the file. If
217 //! `complete` is false, the window ended before the end of the file. Glom
218 //! inspects the admitted bytes for the last newline character, processes
219 //! complete lines up to that delimiter, releases the borrow, and advances its
220 //! file offset to resume reading. If a maximum-sized window contains no newline
221 //! delimiter at all, the consumer itself raises a record-framing error. Framing
222 //! logic remains the responsibility of the consumer, while the input region
223 //! guarantees only the bounded byte window.
224 //!
225 //! ## Declaration scope and interface shapes
226 //!
227 //! To integrate an input owner with verification and capacity tooling, we
228 //! encapsulate its configuration within a `Spec` structure. A specification
229 //! packages input limit and capacity types, error sets, status layout, enabled
230 //! acquisition capabilities, overload policy, and a formal capacity
231 //! `Declaration`.
232 //!
233 //! The status structure must declare exactly seven fields for recoverable
234 //! owners or eight fields for terminal owners. While the generic checker
235 //! validates the field count and types, it does not verify that custom field
236 //! mappings are distinct from one another. We must supply distinct field names
237 //! to prevent diagnostic collisions.
238 //!
239 //! The capacity `Declaration` establishes the structural contract of the owner
240 //! for this example:
241 //!
242 //! - Validation of `phase_static` requires valid seal and teardown bindings.
243 //!   The tag describes a claim and does not govern actual allocation behavior
244 //!   or enforce an operational lifetime. The limit source is marked as
245 //!   `.caller`, indicating that limits are supplied at initialization.
246 //! - The storage section specifies covered memory, naming the single
247 //!   steady-state input buffer and describing its purpose. Excluded clauses
248 //!   document runtime resources that sit outside the claim, such as stream
249 //!   reader handles and destination parsing structures.
250 //! - The capacity model defines an expression graph capturing the `n + 1`
251 //!   derivation. An input node binds the limit field, an integer constant node
252 //!   provides the literal 1, and an addition node sums them. An assertion
253 //!   declares that total retained storage matches this expression.
254 //! - The overload policy is declared as `.drop`, documenting that oversized
255 //!   input is rejected while storage remains available for a later attempt. The
256 //!   `.drop` policy does not preserve previously released payload bytes:
257 //!   subsequent reads can overwrite released bytes in the backing buffer.
258 //! - Transitive and foreign operational risks are marked as `.open`,
259 //!   acknowledging that reader streams or filesystem calls can incur effects
260 //!   outside the region boundaries.
261 //! - The declaration lists obligations for the capacity model and the overload
262 //!   policy.
263 //!
264 //! When `OneRegion(Spec)` generates an owner, it constructs fresh bindings
265 //! linking the owner type, the specification, and selectors for `activate` and
266 //! `deinit`. It does not reuse any bindings declared on `Spec.claim`. Claim
267 //! declarations and premise labels such as `.checked_semantic_fact` provide
268 //! structural metadata for verification tools: they do not establish proven
269 //! semantic facts or whole-program safety guarantees.
270 //!
271 //! We validate this generated structure at compile time using
272 //! `alloc_phase.capacity.requireAllocatorRejectingOwnerShape(Storage)`. This
273 //! function performs structural reflection, checking that the owner provides
274 //! required lifecycle functions, exposes an exhaustion error set on receiver
275 //! methods, and presents a compatible claim.
276 //!
277 //! The following test illustrates a specification and recoverable input owner:
278 //!
279 //! ```zig
280 //! const std = @import("std");
281 //! const alloc_phase = @import("alloc_phase");
282 //!
283 //! pub const InputLimits = struct {
284 //!     max_bytes: usize,
285 //! };
286 //!
287 //! pub const InputCapacity = struct {
288 //!     max_bytes: usize,
289 //!     storage_bytes: usize,
290 //!
291 //!     pub fn derive(limits: InputLimits) alloc_phase.input.DeriveError!InputCapacity {
292 //!         return alloc_phase.input.deriveCapacity(InputLimits, InputCapacity, "max_bytes", limits);
293 //!     }
294 //! };
295 //!
296 //! pub const InputExhaustion = error{
297 //!     InputStorageBusy,
298 //!     InputCapacityExceeded,
299 //! };
300 //!
301 //! pub const InputStatus = struct {
302 //!     phase: alloc_phase.capacity.Phase,
303 //!     in_use: bool,
304 //!     max_bytes: usize,
305 //!     storage_bytes: usize,
306 //!     loaded_bytes: usize,
307 //!     high_water_bytes: usize,
308 //!     rejected_count: u64,
309 //! };
310 //!
311 //! pub const Spec = struct {
312 //!     pub const Limits = InputLimits;
313 //!     pub const Capacity = InputCapacity;
314 //!     pub const Exhaustion = InputExhaustion;
315 //!     pub const Status = InputStatus;
316 //!     pub const DeriveError = alloc_phase.input.DeriveError;
317 //!     pub const acquisition: alloc_phase.input.Acquisition = .{
318 //!         .reader = true,
319 //!         .preflight = true,
320 //!     };
321 //!     pub const overload: alloc_phase.input.Overload = .recoverable;
322 //!     pub const limit_field = "max_bytes";
323 //!     pub const loaded_field = "loaded_bytes";
324 //!     pub const high_water_field = "high_water_bytes";
325 //!     pub const rejected_field = "rejected_count";
326 //!     pub const in_use_error: Exhaustion = error.InputStorageBusy;
327 //!     pub const capacity_error: Exhaustion = error.InputCapacityExceeded;
328 //!
329 //!     pub const claim: alloc_phase.capacity.Declaration = .{
330 //!         .source = .{
331 //!             .id = "guide.recoverable_reader",
332 //!             .kind = .phase_static,
333 //!             .limit_source = .caller,
334 //!             .storage = .{
335 //!                 .covered = &.{
336 //!                     .{
337 //!                         .id = "reusable_input_buffer",
338 //!                         .lifetime = .steady,
339 //!                         .detail = "one reusable input and lookahead byte region",
340 //!                     },
341 //!                 },
342 //!                 .excluded = &.{
343 //!                     "stream reader buffering and allocator handles",
344 //!                     "caller payload storage outside the borrowed window",
345 //!                 },
346 //!             },
347 //!             .capacity = .{
348 //!                 .inputs = &.{
349 //!                     alloc_phase.capacity.bindInput(InputLimits, "max_bytes", "max_bytes"),
350 //!                 },
351 //!                 .type_selectors = &.{},
352 //!                 .nodes = &.{
353 //!                     .{ .input = 0 },
354 //!                     .{ .constant = 1 },
355 //!                     .{ .add = .{ .left = 0, .right = 1 } },
356 //!                 },
357 //!                 .assertions = &.{
358 //!                     .{
359 //!                         .scope = .closure_total,
360 //!                         .measure = .retained,
361 //!                         .relation = .exact,
362 //!                         .expression = 2,
363 //!                     },
364 //!                 },
365 //!             },
366 //!             .overload = .{
367 //!                 .kind = .drop,
368 //!                 .detail = "oversized input is rejected while storage remains available for a later attempt",
369 //!             },
370 //!             .risks = .{
371 //!                 .transitive = .{
372 //!                     .status = .open,
373 //!                     .detail = "stream operations may perform external allocations",
374 //!                 },
375 //!                 .foreign = .{
376 //!                     .status = .open,
377 //!                     .detail = "kernel stream handles remain unmanaged",
378 //!                 },
379 //!             },
380 //!             .obligations = &.{
381 //!                 .{ .key = "input_capacity_model", .role = .capacity_model },
382 //!                 .{ .key = "input_overload_policy", .role = .overload },
383 //!             },
384 //!         },
385 //!         .bindings = .{},
386 //!     };
387 //! };
388 //!
389 //! pub const Storage = alloc_phase.input.OneRegion(Spec);
390 //!
391 //! comptime {
392 //!     alloc_phase.capacity.requireAllocatorRejectingOwnerShape(Storage);
393 //! }
394 //!
395 //! test "recoverable input storage lifecycle, borrow discipline, and reuse" {
396 //!     const allocator = std.testing.allocator;
397 //!     var storage = try Storage.init(allocator, .{ .max_bytes = 5 });
398 //!     defer storage.deinit(allocator);
399 //!     defer if (storage.in_use) storage.release();
400 //!
401 //!     storage.activate();
402 //!
403 //!     var first_reader: std.Io.Reader = .fixed("hello");
404 //!     const borrowed = try storage.read(&first_reader);
405 //!
406 //!     try std.testing.expectEqual(@as(usize, 5), borrowed.len);
407 //!     try std.testing.expectEqualStrings("hello", borrowed);
408 //!     try std.testing.expectError(error.InputStorageBusy, storage.preflight(0));
409 //!
410 //!     var preserved: [5]u8 = undefined;
411 //!     @memcpy(&preserved, borrowed);
412 //!
413 //!     storage.release();
414 //!
415 //!     try std.testing.expectEqualStrings("hello", &preserved);
416 //!
417 //!     const status_after_release = storage.status();
418 //!     try std.testing.expect(!status_after_release.in_use);
419 //!     try std.testing.expectEqual(@as(usize, 0), status_after_release.loaded_bytes);
420 //!     try std.testing.expectEqual(@as(usize, 5), status_after_release.high_water_bytes);
421 //!     try std.testing.expectEqual(@as(u64, 0), status_after_release.rejected_count);
422 //!
423 //!     try std.testing.expectError(error.InputCapacityExceeded, storage.preflight(6));
424 //!
425 //!     const status_after_reject = storage.status();
426 //!     try std.testing.expectEqual(@as(u64, 1), status_after_reject.rejected_count);
427 //!
428 //!     var second_reader: std.Io.Reader = .fixed("zig");
429 //!     const second_borrow = try storage.read(&second_reader);
430 //!
431 //!     try std.testing.expectEqualStrings("zig", second_borrow);
432 //!
433 //!     const status_final = storage.status();
434 //!     try std.testing.expect(status_final.in_use);
435 //!     try std.testing.expectEqual(@as(usize, 3), status_final.loaded_bytes);
436 //!     try std.testing.expectEqual(@as(usize, 5), status_final.high_water_bytes);
437 //!
438 //!     try std.testing.expectEqualStrings("hello", &preserved);
439 //!
440 //!     storage.release();
441 //! }
442 //! ```
443 //!
444 //! The source unit tests for `alloc_phase.input` assert capacity derivation
445 //! from 31 to 32 bytes, overflow detection at integer limits, initialization
446 //! failure under allocation faults, exact acceptance of fitting payloads, busy
447 //! errors during active borrows, saturating rejection counters on terminal
448 //! owners, and recoverable reuse following an oversized preflight check.
449 //! Additional property tests assert `n + 1` allocation sizing for limits up to
450 //! 4096 bytes, and consumer test suites exercise windowed reads alongside file
451 //! boundary handling.
452 
453 const one = @import("one.zig");
454 
455 /// Packed boolean structure that enables specific input capabilities on an
456 /// owner at compile time. All four fields default to `false`:
457 ///
458 /// * `reader`: Enables stream acquisition through `read`.
459 ///
460 /// * `file`: Enables filesystem acquisition through `readFile` and
461 /// `readFileWindow`.
462 /// * `preflight`: Enables size admission checks through `preflight`.
463 /// * `map_file_too_big`: Maps `error.FileTooBig` from an underlying `readFile`
464 /// call into a capacity rejection instead of propagating the raw I/O error.
465 ///
466 /// Because an owner must support at least one input mechanism, specification
467 /// validation requires either `reader` or `file` to be enabled. Mapping
468 /// file-size errors requires filesystem support, so `map_file_too_big` can be
469 /// enabled only when `file` is also set to `true`. Individual acquisition
470 /// methods verify their corresponding flags at compile time and raise a compile
471 /// error when invoked without the required capability enabled.
472 pub const Acquisition = one.Acquisition;
473 /// Error set returned when capacity derivation fails.
474 ///
475 /// Members:
476 ///
477 /// * `CapacityOverflow`: Adding one lookahead byte to the configured byte limit
478 /// overflowed the range of `usize`.
479 pub const DeriveError = one.DeriveError;
480 /// Constructs an allocator-backed owner type for a single reusable input buffer
481 /// based on a static specification structure.
482 ///
483 /// The `Spec` type parameter must satisfy several structural requirements:
484 ///
485 /// * `Limits`: Structure defining input limits. It must contain the field
486 /// designated by `limit_field` typed as `usize`.
487 /// * `Capacity`: Structure defining storage requirements. It must expose a
488 /// `derive(limits: Limits) DeriveError!Capacity` function, the field named by
489 /// `limit_field` typed as `usize`, and `storage_bytes` typed as `usize`.
490 /// * `DeriveError`: Error set returned by `Capacity.derive`.
491 /// * `Exhaustion`: Error set returned when storage cannot admit an input.
492 /// * `Status`: Reporting structure returned by `status`. It must be a struct
493 /// containing exactly seven fields for recoverable owners or eight fields for
494 /// terminal owners: `phase: alloc_phase.capacity.Phase`, `in_use: bool`,
495 /// `storage_bytes: usize`, the mapped limit, loaded, and high-water fields
496 /// typed as `usize`, the mapped rejection field typed as `u64`, and
497 /// conditionally `terminal: bool` when `overload` is `terminal`.
498 /// * `acquisition`: An instance of `Acquisition` specifying enabled I/O
499 /// capabilities.
500 /// * `overload`: An instance of `Overload` setting either `.terminal` or
501 /// `.recoverable` behavior.
502 /// * Field mappings: `limit_field`, `loaded_field`, `high_water_field`, and
503 /// `rejected_field` specify field names on `Capacity` or `Status`. Callers must
504 /// supply distinct names for these fields. Compile-time validation verifies
505 /// field presence and total field counts, but this validation does not prove
506 /// that mapped field names are mutually distinct.
507 /// * Error instances: `in_use_error` and `capacity_error` must both have type
508 /// `Spec.Exhaustion`.
509 /// * `claim`: A static `alloc_phase.capacity.Declaration` metadata descriptor.
510 ///
511 /// The owner asserts that `storage_bytes` strictly exceeds the configured byte
512 /// limit. While standard `deriveCapacity` derivation provides an exact `limit +
513 /// 1` layout, custom `Capacity.derive` implementations may describe larger
514 /// storage: derivation computes a `Capacity` value, while `init` allocates.
515 ///
516 /// A successful read operation returns a borrowed `[]const u8` slice pointing
517 /// directly into the owned buffer and marks the owner as in use, including when
518 /// the input is empty. Borrowers must consume or copy these bytes elsewhere
519 /// before calling `release`. Slices must not be accessed after releasing the
520 /// owner.
521 ///
522 /// A struct copy shares allocated storage but duplicates internal bookkeeping.
523 /// Copies are not independent owners: transferring exclusive ownership requires
524 /// callers to stop using the original. Callers must serialize operations and
525 /// ensure cleanup occurs exactly once.
526 ///
527 /// The owner is not thread-safe and performs no internal synchronization.
528 /// Callers accessing an owner across threads must provide external mutual
529 /// exclusion.
530 ///
531 /// Lifecycle checks across initialization, steady operation, and teardown are
532 /// enforced through debug assertions rather than explicit always-executed phase
533 /// panics.
534 pub const OneRegion = one.OneRegion;
535 /// Defines the policy applied when an input exceeds the configured capacity
536 /// limit.
537 ///
538 /// Tags:
539 ///
540 /// * `terminal`: Permanently seals the owner upon capacity rejection. Any
541 /// subsequent acquisition attempt returns the capacity error immediately
542 /// without performing I/O or incrementing rejection counters.
543 /// * `recoverable`: Preserves owner availability across rejections. Oversized
544 /// inputs increment the rejection counter but leave the underlying storage free
545 /// for subsequent attempts.
546 ///
547 /// Recovery designates the ability to reuse the allocated storage for later
548 /// inputs. It does not provide source-position rollback, record framing, or
549 /// automatic input drainage.
550 pub const Overload = one.Overload;
551 /// Derives an instance of `Capacity` from a given `Limits` structure by adding
552 /// one lookahead byte to the configured input limit.
553 ///
554 /// The input limit is retrieved from the field named by `limit_field` on
555 /// `limits`. Both the limit field on `Limits` and `Capacity` and the
556 /// `storage_bytes` field on `Capacity` must be typed as `usize`. When addition
557 /// overflows `usize`, the function returns `error.CapacityOverflow`. A limit of
558 /// zero derives a storage size of one byte.
559 ///
560 /// The returned `Capacity` structure initializes only the field named by
561 /// `limit_field` and `storage_bytes`. Any additional fields present on
562 /// `Capacity` remain undefined. Callers must keep `limit_field` distinct from
563 /// `storage_bytes` so that writing `storage_bytes` does not overwrite the limit
564 /// field.
565 pub const deriveCapacity = one.deriveCapacity;