tiny.syn.span.capacity
Defined in span.
The arithmetic computes, from one limit the caller chooses, how many bytes the storage for a line's marks needs.
API (4)
Types and contracts
Public types and contracts.
Capacity: The sizes that follow from oneLimitsvalue, computed without allocating.DeriveError: The one way sizing can fail.Limits: The one limit the caller chooses for span storage.
Values and defaults
Public values and defaults.
storage_alignment: The byte alignment of oneSpan.
Source
Source: lib/syn/src/span/capacity.zig
zig
//! The arithmetic computes, from one limit the caller chooses, how many bytes the storage for a//! line's marks needs. A caller with a fixed memory budget wants that size before it allocates//! anything, and wants a limit too large to size refused. The number of marks on a line has to be//! bounded by something the caller controls.//!//! The bound is the line length: each kept mark covers at least one byte and no two overlap, so a//! line of n bytes yields at most n marks, and the storage holds as many marks as the limit has//! bytes (*span capacity*). The storage is one region of that many marks, aligned for one mark, so//! its size in bytes is the limit times the size of one mark.//!//! - *text limit*: the longest line, in bytes, whose marks the storage keeps//! - *span*: one marked byte range of a line and its role//! - *span storage*: the caller's buffer that receives one line's marksconst std = @import("std");const model = @import("model.zig");/// The byte alignment of one `Span`. `Storage.init` requests its region at this alignment, so the/// region can be read as an array of `Span` values.pub const storage_alignment: usize = @alignOf(model.Span);/// The one limit the caller chooses for span storage. A caller fills it in once to say how long a/// line may be before its spans are dropped. `Capacity.derive` and `Storage.init` both take it.pub const Limits = struct { /// The text limit, in bytes. A longer line is still scanned but keeps no spans. The storage /// holds exactly this many spans. Zero is allowed and gives storage with no room, so every /// nonempty line is discarded. The README example uses 4096. max_text_bytes: usize,};/// The one way sizing can fail. A caller of `Capacity.derive` or `Storage.init` handles it for a/// limit too large to size. `CapacityOverflow` means the limit times the size of one span does not/// fit in a `usize`. The largest accepted limit is the largest `usize` divided by the size of one/// span.pub const DeriveError = error{CapacityOverflow};/// The sizes that follow from one `Limits` value, computed without allocating. A caller derives it/// before allocating, to learn the exact bytes span storage will take, and the storage keeps its/// own copy.pub const Capacity = struct { /// The limits the sizes were derived from, as given. limits: Limits, /// The span capacity: how many spans the storage holds, equal to `limits.max_text_bytes`. A /// line within the limit never needs more, because each kept span covers at least one byte and /// no two overlap. span_capacity: usize, /// The bytes those spans take: `span_capacity` times the size of one `Span`. span_bytes: usize, /// The bytes `Storage.init` allocates, in one region, equal to `span_bytes`. `Storage.status` /// reports the same number, and the README example checks that the two agree. The byte count is /// zero when the limit is zero, and then `Storage.init` allocates nothing. storage_bytes: usize, /// Returns the sizes for `limits`. A caller computes the storage size ahead of time, for /// example to check a memory budget, and `Storage.init` calls it too. `Capacity.derive` fails /// with `error.CapacityOverflow` when `max_text_bytes` times the size of one `Span` overflows a /// `usize`. The call allocates nothing and reads nothing but its argument. pub fn derive(limits: Limits) DeriveError!Capacity { const span_bytes = std.math.mul( usize, limits.max_text_bytes, @sizeOf(model.Span), ) catch return error.CapacityOverflow; return .{ .limits = limits, .span_capacity = limits.max_text_bytes, .span_bytes = span_bytes, .storage_bytes = span_bytes, }; }};fn modelCapacity(limits: Limits) DeriveError!Capacity { const span_bytes = @as(u128, limits.max_text_bytes) * @sizeOf(model.Span); if (span_bytes > std.math.maxInt(usize)) return error.CapacityOverflow; return .{ .limits = limits, .span_capacity = limits.max_text_bytes, .span_bytes = @intCast(span_bytes), .storage_bytes = @intCast(span_bytes), };}test "syntax span capacity matches an independent byte model" { comptime { @stardustClaim( @import("alloc_phase").capacity.witness(@import("./root.zig").Storage, "syn_span_capacity"), null, null, null, null, null, null, ); } const limits = Limits{ .max_text_bytes = 40 }; try std.testing.expectEqual(try modelCapacity(limits), try Capacity.derive(limits)); try std.testing.expectEqual( @as(usize, 40 * @sizeOf(model.Span)), (try Capacity.derive(limits)).storage_bytes, ); try std.testing.expectEqual( @as(usize, 0), (try Capacity.derive(.{ .max_text_bytes = 0 })).storage_bytes, );}test "syntax span capacity accepts its largest representable text limit" { const max_text_bytes = std.math.maxInt(usize) / @sizeOf(model.Span); const capacity = try Capacity.derive(.{ .max_text_bytes = max_text_bytes }); try std.testing.expectEqual( max_text_bytes * @sizeOf(model.Span), capacity.storage_bytes, ); try std.testing.expectError( error.CapacityOverflow, Capacity.derive(.{ .max_text_bytes = max_text_bytes + 1 }), );}Source: lib/syn/src/span/root.zig:9
zig
pub const capacity = @import("capacity.zig");Audit
| Definitions | 2 |
|---|---|
| Public names | 2 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |