tiny.profiling.ingest.parser
Defined in ingest.
API (2)
Actions
Public operations.
Types and contracts
Public types and contracts.
Source
Source: src/profiling/ingest/parser.zig
zig
const std = @import("std");const ingest = @import("root.zig");pub const Result = struct { valid: bool, event: ingest.event.Event = .{},};const State = enum(u8) { root, key, key_string, value, value_string, nested, document,};const Step = enum(u8) { next, valid, invalid,};comptime { std.debug.assert(@typeInfo(State).@"enum".field_names.len == 7); std.debug.assert(@typeInfo(Step).@"enum".field_names.len == 3); std.debug.assert(@sizeOf(State) == 1); std.debug.assert(@sizeOf(Step) == 1);}const Parser = struct { state: State = .root, field: ingest.event.Field = .other, matcher: ingest.matching.Matcher = ingest.matching.Matcher.kinds(), event: ingest.event.Event = .{}, fn accept( self: *Parser, scanner: *const std.json.Scanner, token: std.json.Token, key: ?ingest.duplicate.Key, ) Step { std.debug.assert(@backingInt(self.state) < 7); std.debug.assert(@backingInt(self.field) < 21); return switch (self.state) { .root => self.acceptRoot(token), .key => self.acceptKey(token, key), .key_string => self.acceptKeyString(token, key), .value => self.acceptValue(token), .value_string => self.acceptValueString(token), .nested => self.acceptNested(scanner, token), .document => if (token == .end_of_document) .valid else .invalid, }; } fn acceptRoot(self: *Parser, token: std.json.Token) Step { std.debug.assert(self.state == .root); if (token != .object_begin) return .invalid; self.state = .key; std.debug.assert(self.state == .key); return .next; } fn acceptKey( self: *Parser, token: std.json.Token, key: ?ingest.duplicate.Key, ) Step { std.debug.assert(self.state == .key); if (token == .object_end) { self.state = .document; return .next; } return self.acceptKeyPart(token, key); } fn acceptKeyString( self: *Parser, token: std.json.Token, key: ?ingest.duplicate.Key, ) Step { std.debug.assert(self.state == .key_string); return self.acceptKeyPart(token, key); } fn acceptKeyPart( self: *Parser, token: std.json.Token, key: ?ingest.duplicate.Key, ) Step { switch (self.state) { .key => std.debug.assert(self.state == .key), .key_string => std.debug.assert(self.state == .key_string), else => unreachable, } switch (token) { .partial_string, .partial_string_escaped_1, .partial_string_escaped_2, .partial_string_escaped_3, .partial_string_escaped_4, => self.state = .key_string, .string => { const actual = key orelse return .invalid; self.field = ingest.selector.field(actual.hash, actual.bytes); self.state = .value; }, else => return .invalid, } switch (self.state) { .key_string => std.debug.assert(self.state == .key_string), .value => std.debug.assert(self.state == .value), else => unreachable, } return .next; } fn acceptValue(self: *Parser, token: std.json.Token) Step { std.debug.assert(self.state == .value); self.event.clear(self.field); self.matcher = ingest.matching.Matcher.values(self.field); if (ingest.matching.feedToken(&self.matcher, token)) |part| { return self.finishValuePart(part); } switch (token) { .object_begin => self.state = .nested, .array_begin => { self.event.assignArray(self.field); self.state = .nested; }, .number => |number| { self.event.assignNumber(self.field, number); self.state = .key; }, .true, .false, .null => self.state = .key, else => return .invalid, } return .next; } fn acceptValueString(self: *Parser, token: std.json.Token) Step { std.debug.assert(self.state == .value_string); const part = ingest.matching.feedToken(&self.matcher, token) orelse return .invalid; return self.finishValuePart(part); } fn finishValuePart(self: *Parser, part: ingest.matching.StringPart) Step { switch (self.state) { .value => std.debug.assert(self.state == .value), .value_string => std.debug.assert(self.state == .value_string), else => unreachable, } if (part == .partial) { self.state = .value_string; } else { switch (self.field) { .kind => self.event.kind = self.matcher.kind(), .schema => self.event.schema_metric = self.matcher.schemaMetric(), .event => self.event.event_bench_end = self.matcher.eventBenchEnd(), .summary => self.event.summary_memory = self.matcher.summaryMemory(), else => {}, } self.state = .key; } switch (self.state) { .value_string => std.debug.assert(self.state == .value_string), .key => std.debug.assert(self.state == .key), else => unreachable, } return .next; } fn acceptNested( self: *Parser, scanner: *const std.json.Scanner, token: std.json.Token, ) Step { std.debug.assert(self.state == .nested); std.debug.assert(scanner.stackHeight() >= 1); switch (token) { .object_end, .array_end => if (scanner.stackHeight() == 1) { self.state = .key; }, .end_of_document => return .invalid, else => {}, } return .next; }};pub fn line(bytes: []const u8, scratch: ingest.duplicate.Scratch) error{ScratchExceeded}!Result { std.debug.assert(bytes.len >= 2); std.debug.assert(bytes[0] == '{'); std.debug.assert(bytes[bytes.len - 1] == '}'); std.debug.assert(scratch.json_stack.len > 0); std.debug.assert(scratch.key_bytes.len >= bytes.len); std.debug.assert(scratch.objects.len * 8 >= scratch.json_stack.len); @memset(scratch.json_stack, 0); var allocator_storage: [0]u8 = .{}; var fixed = std.heap.FixedBufferAllocator.init(&allocator_storage); var scanner = std.json.Scanner.initCompleteInput(fixed.allocator(), bytes); scanner.stack.bytes.items = scratch.json_stack[0..0]; scanner.stack.bytes.capacity = scratch.json_stack.len; std.debug.assert(scanner.stack.bytes.capacity == scratch.json_stack.len); var duplicates = ingest.duplicate.Tracker.init(scratch); var parser = Parser{}; const token_bound = std.math.add(usize, bytes.len, 2) catch unreachable; std.debug.assert(token_bound > bytes.len); for (0..token_bound) |_| { const token = scanner.next() catch |err| switch (err) { error.OutOfMemory => return error.ScratchExceeded, else => return .{ .valid = false }, }; const observation = try duplicates.observe(&scanner, token); const key: ?ingest.duplicate.Key = switch (observation) { .none => null, .unique => |actual| actual, .duplicate => return .{ .valid = false }, }; switch (parser.accept(&scanner, token, key)) { .next => {}, .valid => return .{ .valid = true, .event = parser.event }, .invalid => return .{ .valid = false }, } } return .{ .valid = false };}Source: src/profiling/ingest/root.zig:7
zig
pub const parser = @import("parser.zig");Audit
| Definitions | 3 |
|---|---|
| Public names | 3 |
| Members | 2 |
| Version | 26.7.0 |
| Revision | daab053ee433 |