tiny.http.ClientResponseStorage
Defined in tiny.http.
Storage provides reusable response slots cut from memory sized by caller limits.
API (12)
Actions
Public operations.
Types and contracts
Public types and contracts.
Fields and members
Public fields and members.
Source
Source: lib/http/src/client/storage.zig:26
zig
/// Storage provides reusable response slots cut from memory sized by caller/// limits. Sizing with zero storage bytes skips allocation entirely, while/// non-zero requirements allocate a single contiguous block up front. That/// allocation is partitioned into three sequential regions: all header entries/// for all slots, followed by all head bytes, and finally all body bytes. Each/// slot draws its corresponding slices from each of these three regions.////// Calling `activate` ends the initialization phase, after which `response`/// hands out a slot's scratch slices. Handing out a slot invokes no allocator./// Specifying an index at or beyond the configured slot count returns/// `error.ClientResponseCapacityExceeded`.////// A response parsed into a slot borrows that slot directly. The backing/// storage must remain alive and unchanged while the response is in use, with/// slot reuse for another parse and calling `deinit` serving as explicit/// invalidation points.pub const Storage = struct { phase: alloc_phase.capacity.Phase, capacity: model.Capacity, bytes: []align(@alignOf(Header)) u8, pub const Limits: type = model.Limits; pub const Capacity: type = model.Capacity; pub const Exhaustion: type = StorageExhaustion; pub const InitError = std.mem.Allocator.Error || error{CapacityOverflow}; pub const claim: alloc_phase.capacity.Declaration = .{ .source = .{ .id = "http.client_response_storage", .kind = .phase_static, .limit_source = .caller, .storage = .{ .covered = &.{ .{ .id = "fixed_parsed_client_response_header_entries_for_eve_451da7e2df60", .lifetime = .steady, .detail = "fixed parsed client-response header entries for every response slot", }, .{ .id = "fixed_response_head_bytes_retaining_borrowed_header_27c2e730fc7e", .lifetime = .steady, .detail = "fixed response-head bytes retaining borrowed header names and values", }, .{ .id = "fixed_buffered_or_decoded_response_body_bytes", .lifetime = .steady, .detail = "fixed buffered or decoded response-body bytes", }, }, .excluded = &.{ "request serialization, URL targets, TLS state, certificate bundles, sockets, and kernel queues", "streaming response header accumulation, chunk fragmentation, and handler-owned output", }, }, .capacity = .{ .inputs = &.{ alloc_phase.capacity.bindInput(Limits, "response_count", "response_count"), alloc_phase.capacity.bindInput(Limits, "header_count_per_response", "header_count_per_response"), alloc_phase.capacity.bindInput(Limits, "head_bytes_per_response", "head_bytes_per_response"), alloc_phase.capacity.bindInput(Limits, "body_bytes_per_response", "body_bytes_per_response"), }, .type_selectors = &.{ alloc_phase.capacity.bindType(Header, "header"), }, .nodes = &.{ .{ .input = 0 }, .{ .input = 1 }, .{ .product = .{ .left = 0, .right = 1 } }, .{ .constant = 1 }, .{ .scale = .{ .node = 3, .coefficient = .{ .size_of_concrete_type = 0 } } }, .{ .product = .{ .left = 2, .right = 4 } }, .{ .input = 2 }, .{ .product = .{ .left = 0, .right = 6 } }, .{ .input = 3 }, .{ .product = .{ .left = 0, .right = 8 } }, .{ .add = .{ .left = 5, .right = 7 } }, .{ .add = .{ .left = 10, .right = 9 } }, }, .assertions = &.{.{ .scope = .closure_total, .measure = .retained, .relation = .exact, .expression = 11, }}, }, .overload = .{ .kind = .terminal, .detail = "direct parse rejects atomically; a network response exceeding its slot terminates that one-shot connection without publishing a response", }, .risks = .{ .transitive = .{ .status = .witnessed, .detail = "response parsing and chunk decoding allocate no storage after activation", }, .foreign = .{ .status = .excluded, .detail = "network reads may discover remote overflow after bounded scratch mutation but never publish an over-capacity response", }, }, .obligations = &.{ .{ .key = "http_client_response_capacity", .role = .capacity_model }, .{ .key = "http_client_response_oom_retry", .role = .custom }, .{ .key = "http_client_response_partition", .role = .custom }, .{ .key = "http_client_response_sealed", .role = .transitive_risk }, .{ .key = "http_client_response_atomic", .role = .overload }, .{ .key = "http_client_response_boundary", .role = .custom }, .{ .key = "http_client_response_network_overload", .role = .overload }, .{ .key = "http_client_response_network_foreign_risk", .role = .foreign_risk }, }, }, .bindings = .{ .owner = @This(), .seal = .{ .family = alloc_phase.capacity.selector(@This().activate), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, .teardown = .{ .family = alloc_phase.capacity.selector(@This().deinit), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, }, }; pub fn init(allocator: std.mem.Allocator, limits: Limits) InitError!Storage { const capacity = try Capacity.derive(limits); const bytes = if (capacity.storage_bytes == 0) @as([]align(@alignOf(Header)) u8, &.{}) else try allocator.alignedAlloc(u8, .of(Header), capacity.storage_bytes); return .{ .phase = .initialization, .capacity = capacity, .bytes = bytes, }; } pub fn activate(self: *Storage) void { std.debug.assert(self.phase == .initialization); std.debug.assert(self.bytes.len == self.capacity.storage_bytes); self.phase = .steady; } pub fn response(self: *Storage, index: usize) Exhaustion!Scratch { std.debug.assert(self.phase == .steady); if (index >= self.capacity.response_count) { return error.ClientResponseCapacityExceeded; } const all_headers = std.mem.bytesAsSlice( Header, self.bytes[0..self.capacity.header_bytes], ); const header_start = index * self.capacity.header_count_per_response; const head_start = self.capacity.header_bytes + index * self.capacity.head_bytes_per_response; const body_region_start = self.capacity.header_bytes + self.capacity.head_bytes; const body_start = body_region_start + index * self.capacity.body_bytes_per_response; return .{ .headers = all_headers[header_start..][0..self.capacity.header_count_per_response], .head = self.bytes[head_start..][0..self.capacity.head_bytes_per_response], .body = self.bytes[body_start..][0..self.capacity.body_bytes_per_response], }; } pub fn deinit(self: *Storage, allocator: std.mem.Allocator) void { std.debug.assert(self.phase != .teardown); std.debug.assert(self.bytes.len == self.capacity.storage_bytes); self.phase = .teardown; if (self.bytes.len != 0) allocator.free(self.bytes); self.bytes = &.{}; }};Source: lib/http/src/root.zig:97
zig
pub const ClientResponseStorage = client.ResponseStorage;Audit
| Definitions | 10 |
|---|---|
| Public names | 10 |
| Members | 3 |
| Version | 26.7.0 |
| Revision | daab053ee433 |