Skip to documentation
SLOP

tiny.profiling.ingest.inspection

Reference tiny.profiling ingest inspection

Defined in ingest.

API (6)

Actions

Public operations.

No direct callersNo direct callsingestinspection
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callsprivate; no linksrc.profiling.ingest.inspectionscanChunksprivate; no linksrc.profiling.ingest.inspectionscanContentstest; no linksrc.profiling.ingest.inspectiontest: ingestion source and allocation...ingest.inspectionadmitAllocationLine
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate; no linksrc.profiling.ingest.inspectionscanChunksprivate; no linksrc.profiling.ingest.inspectionscanSourcetest; no linksrc.profiling.ingest.inspectiontest: ingestion source and allocation...ingest.inspectionadmitSourceBytes
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsingest.Limitsinspectingest.inspectioninspectSourceingest.inspectioninspect
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsingest.inspectioninspectingest.outputwriteprivate; no linksrc.profiling.ingest.inspectionscanSourceingest.inspectioninspectSource
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsingest.ArtifactIngestionactivateingest.model.IdentityfromStatingest.inspectionmetadataMatches
Static calls · unresolved targets: 1 · external targets: 4.
Called byCallsprivate; no linksrc.profiling.ingest.outputwriteOrdinarySourcesprivate; no linksrc.profiling.ingest.ownerprepareprivate; no linksrc.profiling.ingest.inspectionscanSourceingest.inspectionvisitSource
Static calls · unresolved targets: 0 · external targets: 1.

Source: src/profiling/ingest/inspection.zig

zig
const std = @import("std");const sys = @import("sys");const ingest = @import("root.zig");const model = ingest.model;const LineInspection = struct {    bytes: usize = 0,    first_significant: ?u8 = null,    last_significant: ?u8 = null,    json_depth: usize = 0,    max_json_depth: usize = 0,    key_count: usize = 0,    in_string: bool = false,    escaped: bool = false,    fn observe(self: *LineInspection, byte: u8) error{CapacityOverflow}!void {        const previous_bytes = self.bytes;        self.bytes = std.math.add(usize, self.bytes, 1) catch return error.CapacityOverflow;        std.debug.assert(self.bytes == previous_bytes + 1);        std.debug.assert(self.json_depth <= self.max_json_depth);        if (!isTrimByte(byte)) {            if (self.first_significant == null) self.first_significant = byte;            self.last_significant = byte;        }        if (self.in_string) {            if (self.escaped) {                self.escaped = false;            } else if (byte == '\\') {                self.escaped = true;            } else if (byte == '"') {                self.in_string = false;            }            std.debug.assert(self.json_depth <= self.max_json_depth);            return;        }        if (byte == '"') {            self.in_string = true;        } else if (byte == ':') {            self.key_count = std.math.add(usize, self.key_count, 1) catch                return error.CapacityOverflow;        } else if (byte == '{' or byte == '[') {            self.json_depth = std.math.add(usize, self.json_depth, 1) catch                return error.CapacityOverflow;            self.max_json_depth = @max(self.max_json_depth, self.json_depth);            std.debug.assert(self.json_depth <= self.max_json_depth);        } else if ((byte == '}' or byte == ']') and self.json_depth > 0) {            self.json_depth -= 1;        }        std.debug.assert(self.key_count <= self.bytes);    }    fn isCandidate(self: LineInspection) bool {        const result = self.first_significant == '{' and self.last_significant == '}';        if (result) {            std.debug.assert(self.first_significant == '{');            std.debug.assert(self.last_significant == '}');            std.debug.assert(self.bytes >= 2);        }        return result;    }};const ScanState = struct {    facts: model.SourceFacts,    hasher: std.crypto.hash.sha2.Sha256,    line: LineInspection = .{},    line_number: usize = 0,};pub fn inspect(paths: model.Paths) !model.Limits {    const sources = paths.sources();    std.debug.assert(sources.len == model.source_count);    var facts: model.Facts = undefined;    for (sources, 0..) |source, index| {        std.debug.assert(index < model.source_count);        facts.sources[index] = try inspectSource(source);    }    std.debug.assert(facts.sources.len == model.source_count);    return .{ .paths = paths, .facts = facts };}pub fn inspectSource(source: model.Source) !model.SourceFacts {    std.debug.assert(source.kind.name().len > 0);    return scanSource(source, null, {}, ignoreCandidate);}pub fn visitSource(    source: model.Source,    line_storage: []u8,    context: anytype,    comptime visitCandidate: anytype,) !model.SourceFacts {    std.debug.assert(source.kind.name().len > 0);    return scanSource(source, line_storage, context, visitCandidate);}pub fn metadataMatches(paths: model.Paths, facts: model.Facts) !bool {    const sources = paths.sources();    std.debug.assert(sources.len == facts.sources.len);    for (sources, facts.sources) |source, expected| {        var file = sys.fs.cwd().openFile(            sys.fs.debugIo(),            source.path,            .{},        ) catch |err| switch (err) {            error.FileNotFound => {                if (expected.present) return false;                continue;            },            else => return err,        };        defer file.close(sys.fs.debugIo());        if (!expected.present) return false;        std.debug.assert(expected.present);        const actual = model.Identity.fromStat(try file.stat(sys.fs.debugIo()));        if (!std.meta.eql(expected.identity, actual)) return false;    }    return true;}pub fn admitSourceBytes(bytes: usize) error{StreamTooLong}!void {    std.debug.assert(model.max_source_bytes > 0);    if (bytes >= model.max_source_bytes) return error.StreamTooLong;    std.debug.assert(bytes < model.max_source_bytes);}pub fn admitAllocationLine(bytes: usize, terminated: bool) error{StreamTooLong}!void {    std.debug.assert(model.allocation_reader_bytes > 0);    if (bytes > model.allocation_reader_bytes) return error.StreamTooLong;    if (terminated and bytes == model.allocation_reader_bytes) return error.StreamTooLong;    std.debug.assert(bytes <= model.allocation_reader_bytes);}fn scanSource(    source: model.Source,    line_storage: ?[]u8,    context: anytype,    comptime visitCandidate: anytype,) !model.SourceFacts {    std.debug.assert(source.kind.name().len > 0);    var file = sys.fs.cwd().openFile(sys.fs.debugIo(), source.path, .{}) catch |err| switch (err) {        error.FileNotFound => return .{},        else => return err,    };    defer file.close(sys.fs.debugIo());    const identity = model.Identity.fromStat(try file.stat(sys.fs.debugIo()));    std.debug.assert(identity.size <= std.math.maxInt(u64));    const expected_bytes = std.math.cast(usize, identity.size) orelse        return error.CapacityOverflow;    if (!source.kind.isAllocation()) {        try admitSourceBytes(expected_bytes);    }    return scanContents(        &file,        source,        identity,        expected_bytes,        line_storage,        context,        visitCandidate,    );}fn scanContents(    file: *std.Io.File,    source: model.Source,    identity: model.Identity,    expected_bytes: usize,    line_storage: ?[]u8,    context: anytype,    comptime visitCandidate: anytype,) !model.SourceFacts {    std.debug.assert(source.kind.name().len > 0);    var state = ScanState{        .facts = .{ .present = true, .identity = identity },        .hasher = std.crypto.hash.sha2.Sha256.init(.{}),    };    std.debug.assert(state.facts.present);    try scanChunks(        file,        source,        expected_bytes,        line_storage,        context,        visitCandidate,        &state,    );    if (state.facts.bytes != expected_bytes) return error.InputChanged;    if (state.line.bytes > 0) {        std.debug.assert(state.line_number <= state.facts.lines);        if (source.kind.isAllocation()) try admitAllocationLine(state.line.bytes, false);        state.line_number = std.math.add(usize, state.line_number, 1) catch            return error.CapacityOverflow;        try finishLine(            &state.facts,            &state.line,            line_storage,            state.line_number,            context,            visitCandidate,        );    }    state.hasher.final(&state.facts.digest);    const final_identity = model.Identity.fromStat(try file.stat(sys.fs.debugIo()));    if (!std.meta.eql(identity, final_identity)) return error.InputChanged;    if (identity.size != state.facts.bytes) return error.InputChanged;    std.debug.assert(state.facts.present);    std.debug.assert(state.facts.candidates <= state.facts.lines);    std.debug.assert(state.facts.max_json_depth <= state.facts.max_line_bytes);    std.debug.assert(state.facts.max_key_count <= state.facts.max_line_bytes);    return state.facts;}fn scanChunks(    file: *std.Io.File,    source: model.Source,    expected_bytes: usize,    line_storage: ?[]u8,    context: anytype,    comptime visitCandidate: anytype,    state: *ScanState,) !void {    var reader_buffer: [16 * 1024]u8 = undefined;    var chunk: [16 * 1024]u8 = undefined;    var reader = file.reader(sys.fs.debugIo(), &reader_buffer);    const read_bound = std.math.add(usize, expected_bytes, 1) catch        return error.CapacityOverflow;    for (0..read_bound) |_| {        std.debug.assert(state.facts.bytes <= expected_bytes);        const count = reader.interface.readSliceShort(&chunk) catch |err| switch (err) {            error.ReadFailed => return reader.err orelse error.ReadFailed,        };        std.debug.assert(count <= chunk.len);        if (count == 0) return;        if (count > expected_bytes - state.facts.bytes) return error.InputChanged;        const bytes = chunk[0..count];        std.debug.assert(bytes.len > 0);        state.hasher.update(bytes);        state.facts.bytes = std.math.add(usize, state.facts.bytes, count) catch            return error.CapacityOverflow;        if (!source.kind.isAllocation()) try admitSourceBytes(state.facts.bytes);        for (bytes) |byte| {            std.debug.assert(state.line.bytes <= state.facts.bytes);            if (byte == '\n') {                if (source.kind.isAllocation()) try admitAllocationLine(state.line.bytes, true);                state.line_number = std.math.add(usize, state.line_number, 1) catch                    return error.CapacityOverflow;                try finishLine(                    &state.facts,                    &state.line,                    line_storage,                    state.line_number,                    context,                    visitCandidate,                );                state.line = .{};                std.debug.assert(state.line.bytes == 0);                continue;            }            if (line_storage) |storage| {                if (state.line.bytes >= storage.len) return error.InputChanged;                storage[state.line.bytes] = byte;            }            try state.line.observe(byte);            std.debug.assert(state.line.bytes <= state.facts.bytes);            if (source.kind.isAllocation() and                state.line.bytes > model.allocation_reader_bytes)            {                return error.StreamTooLong;            }        }    }    return error.InputChanged;}fn finishLine(    facts: *model.SourceFacts,    line: *const LineInspection,    line_storage: ?[]u8,    line_number: usize,    context: anytype,    comptime visitCandidate: anytype,) !void {    std.debug.assert(line.bytes <= facts.bytes);    std.debug.assert(facts.candidates <= facts.lines);    facts.lines = std.math.add(usize, facts.lines, 1) catch return error.CapacityOverflow;    facts.max_line_bytes = @max(facts.max_line_bytes, line.bytes);    if (!line.isCandidate()) return;    facts.candidates = std.math.add(usize, facts.candidates, 1) catch        return error.CapacityOverflow;    facts.max_json_depth = @max(facts.max_json_depth, line.max_json_depth);    facts.max_key_count = @max(facts.max_key_count, line.key_count);    std.debug.assert(facts.candidates <= facts.lines);    std.debug.assert(facts.max_json_depth <= facts.max_line_bytes);    std.debug.assert(facts.max_key_count <= facts.max_line_bytes);    if (line_storage) |storage| {        std.debug.assert(line.bytes <= storage.len);        const trimmed = std.mem.trim(u8, storage[0..line.bytes], " \t\r");        std.debug.assert(trimmed.len >= 2);        try visitCandidate(context, trimmed, line_number);    }}fn ignoreCandidate(_: void, _: []const u8, _: usize) error{}!void {}fn isTrimByte(byte: u8) bool {    const result = byte == ' ' or byte == '\t' or byte == '\r';    if (result) std.debug.assert(byte != '\n');    return result;}test "ingestion source and allocation line boundaries match the legacy readers" {    try admitSourceBytes(model.max_source_bytes - 1);    try std.testing.expectError(error.StreamTooLong, admitSourceBytes(model.max_source_bytes));    try admitAllocationLine(model.allocation_reader_bytes - 1, true);    try admitAllocationLine(model.allocation_reader_bytes, false);    try std.testing.expectError(        error.StreamTooLong,        admitAllocationLine(model.allocation_reader_bytes, true),    );    try std.testing.expectError(        error.StreamTooLong,        admitAllocationLine(model.allocation_reader_bytes + 1, false),    );}

Source: src/profiling/ingest/root.zig:2

zig
pub const inspection = @import("inspection.zig");

Audit

Definitions7
Public names7
Members0
Version26.7.0
Revisiondaab053ee433