PranitInitial commit439f83c3 months agoHistory
134 lines · 3.8 KB · Zig
RawDownload
const std = @import("std"); const Allocator = std.mem.Allocator;const max_input_bytes = 4096; pub const Runtime = struct {    expected_terminal_row: u16 = 0,    input: std.ArrayList(u8) = .empty,    is_active: bool = false,    is_disabled: bool = false,    late_response_pending: bool = false,     pub fn deinit(self: *Runtime, alloc: Allocator) void {        self.input.deinit(alloc);    }     pub fn active(self: Runtime) bool {        return self.is_active;    }     pub fn disabled(self: Runtime) bool {        return self.is_disabled;    }     pub fn expectedRow(self: Runtime) u16 {        std.debug.assert(self.is_active);        return self.expected_terminal_row;    }     pub fn retainedInput(self: Runtime) []const u8 {        return self.input.items;    }     pub fn begin(        self: *Runtime,        alloc: Allocator,        expected_row: u16,        first_byte: u8,    ) !void {        std.debug.assert(!self.is_active);        std.debug.assert(expected_row > 0);        self.input.clearRetainingCapacity();        try self.input.append(alloc, first_byte);        self.expected_terminal_row = expected_row;        self.is_active = true;        self.late_response_pending = false;    }     pub fn canRetainBytes(self: Runtime, byte_len: usize) bool {        return byte_len <= max_input_bytes -| self.input.items.len;    }     pub fn retainBytes(        self: *Runtime,        alloc: Allocator,        bytes: []const u8,    ) !void {        std.debug.assert(self.is_active);        if (!self.canRetainBytes(bytes.len)) return error.NativeClearProbeInputOverflow;        try self.input.appendSlice(alloc, bytes);    }     pub fn settle(self: *Runtime) []const u8 {        std.debug.assert(self.is_active);        self.is_active = false;        self.expected_terminal_row = 0;        return self.input.items;    }     pub fn clearSettledInput(self: *Runtime) void {        std.debug.assert(!self.is_active);        self.input.clearRetainingCapacity();    }     pub fn disable(self: *Runtime, await_late_response: bool) void {        self.is_disabled = true;        self.late_response_pending = await_late_response;    }     pub fn awaitingLateResponse(self: Runtime) bool {        return self.late_response_pending;    }     pub fn finishLateResponse(self: *Runtime) void {        self.late_response_pending = false;    }}; test "native clear probe retains input until it settles" {    var runtime = Runtime{};    defer runtime.deinit(std.testing.allocator);     try runtime.begin(std.testing.allocator, 17, 'a');    try runtime.retainBytes(std.testing.allocator, "bc");     try std.testing.expect(runtime.active());    try std.testing.expectEqualStrings("abc", runtime.retainedInput());     const retained = runtime.settle();    try std.testing.expectEqualStrings("abc", retained);    try std.testing.expect(!runtime.active());} test "native clear probe bounds held input" {    const alloc = std.testing.allocator;    var runtime = Runtime{};    defer runtime.deinit(alloc);     try runtime.begin(alloc, 17, 'a');    const fill = try alloc.alloc(u8, max_input_bytes - 1);    defer alloc.free(fill);    @memset(fill, 'b');    try runtime.retainBytes(alloc, fill);     try std.testing.expect(!runtime.canRetainBytes(1));    try std.testing.expectError(        error.NativeClearProbeInputOverflow,        runtime.retainBytes(alloc, "c"),    );} test "native clear probe records disabled late-response window" {    var runtime = Runtime{};     try std.testing.expect(!runtime.disabled());    try std.testing.expect(!runtime.awaitingLateResponse());     runtime.disable(true);    try std.testing.expect(runtime.disabled());    try std.testing.expect(runtime.awaitingLateResponse());     runtime.finishLateResponse();    try std.testing.expect(!runtime.awaitingLateResponse());}