tiny.smg.SuffixIndex
Defined in graph.
API (13)
Actions
Public operations.
Types and contracts
Public types and contracts.
Fields and members
Public fields and members.
Source
Source: tools/smg/src/graph.zig:20
zig
pub const SuffixIndex = struct { pub const Limits = struct { entries: usize, nodes: usize, max_name_bytes: usize, }; pub const Capacity = struct { entries: usize, nodes: usize, max_name_bytes: usize, bytes: usize, pub fn derive(limits: Limits) error{CapacityOverflow}!Capacity { if (limits.nodes > std.math.maxInt(u32)) return error.CapacityOverflow; if (limits.max_name_bytes > std.math.maxInt(u32)) return error.CapacityOverflow; return .{ .entries = limits.entries, .nodes = limits.nodes, .max_name_bytes = limits.max_name_bytes, .bytes = std.math.mul(usize, limits.entries, @sizeOf(SuffixEntry)) catch return error.CapacityOverflow, }; } }; pub const InitError = std.mem.Allocator.Error || error{CapacityOverflow}; pub const claim: alloc_phase.capacity.Declaration = .{ .source = .{ .id = "smg.suffix_index", .kind = .phase_static, .limit_source = .caller, .storage = .{ .covered = &.{ .{ .id = "one_compact_hash_node_and_suffix_start_record_per_d_8a2d437489ef", .lifetime = .steady, .detail = "one compact hash, node, and suffix-start record per dotted-name suffix", }, }, .excluded = &.{ "graph nodes and decoded name storage referenced by index records", "caller-owned resolution result arrays", "linear fallback after graph mutation invalidates the snapshot", }, }, .capacity = .{ .inputs = &.{ alloc_phase.capacity.bindInput(Limits, "entries", "entries"), alloc_phase.capacity.bindInput(Limits, "max_name_bytes", "max_name_bytes"), alloc_phase.capacity.bindInput(Limits, "nodes", "nodes"), }, .type_selectors = &.{}, .nodes = &.{ .{ .input = 0 }, .{ .input = 1 }, .{ .input = 2 }, .{ .add = .{ .left = 0, .right = 1 } }, .{ .add = .{ .left = 3, .right = 2 } }, }, .assertions = &.{.{ .scope = .closure_total, .measure = .retained, .relation = .upper_bound, .expression = 4, }}, }, .overload = .{ .kind = .reject_before_seal, .detail = "checked entry and byte counts plus u32 node and name bounds reject overflow or OOM before activation", }, .risks = .{ .transitive = .{ .status = .open, .detail = "standard hash and sort helpers are allocation-free in the witness but lack a transitive allocation-closure certificate", }, .foreign = .{ .status = .excluded, .detail = "the index is process-local caller-owned memory with no operating-system or callback edge", }, }, .obligations = &.{ .{ .key = "smg_suffix_index_capacity_capacity_model", .role = .capacity_model }, .{ .key = "smg_suffix_index_capacity_overload", .role = .overload }, .{ .key = "smg_suffix_index_oom", .role = .overload }, .{ .key = "smg_suffix_index_sealed_transitive_risk", .role = .transitive_risk }, .{ .key = "smg_suffix_index_sealed_foreign_risk", .role = .foreign_risk }, .{ .key = "smg_suffix_index_invalidation", .role = .custom }, }, }, .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, }, }, }, }; phase: alloc_phase.capacity.Phase, capacity: Capacity, entries: []SuffixEntry, pub fn init(allocator: std.mem.Allocator, limits: Limits) InitError!SuffixIndex { const capacity = try Capacity.derive(limits); const entries = if (capacity.entries == 0) @constCast((&[_]SuffixEntry{})[0..]) else try allocator.alloc(SuffixEntry, capacity.entries); return .{ .phase = .initialization, .capacity = capacity, .entries = entries, }; } pub fn fill(self: *SuffixIndex, nodes: []const model.Node) void { std.debug.assert(self.phase == .initialization); std.debug.assert(nodes.len == self.capacity.nodes); var filled: usize = 0; for (nodes, 0..) |node, node_index| { std.debug.assert(node.name.len <= self.capacity.max_name_bytes); var start: usize = 0; while (start < node.name.len) { std.debug.assert(filled < self.entries.len); self.entries[filled] = .{ .hash = std.hash_map.hashString(node.name[start..]), .node = @intCast(node_index), .start = @intCast(start), }; filled += 1; const dot = std.mem.indexOfScalar(u8, node.name[start..], '.') orelse break; start += dot + 1; } } std.debug.assert(filled == self.entries.len); std.mem.sort(SuffixEntry, self.entries, {}, suffixEntryLess); } pub fn activate(self: *SuffixIndex) void { std.debug.assert(self.phase == .initialization); self.phase = .steady; } pub fn deinit(self: *SuffixIndex, allocator: std.mem.Allocator) void { std.debug.assert(self.phase != .teardown); self.phase = .teardown; if (self.entries.len != 0) allocator.free(self.entries); self.* = undefined; } pub fn hashMatches(self: *const SuffixIndex, hash: u64) []const SuffixEntry { std.debug.assert(self.phase == .steady); const start = suffixHashLowerBound(self.entries, hash); const end = suffixHashUpperBound(self.entries[start..], hash) + start; return self.entries[start..end]; }};Source: tools/smg/src/root.zig:115
zig
pub const SuffixIndex = @import("graph.zig").SuffixIndex;Audit
| Definitions | 11 |
|---|---|
| Public names | 22 |
| Members | 10 |
| Version | 26.7.0 |
| Revision | daab053ee433 |