Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

Reader

All next*() methods here handle error.BufferUnderrun from std.json.Scanner, and then read from the reader.

Scanner.Reader
pub const Reader = struct

File

lib/std/json/Scanner.zig:1574

Code

pub const Reader = struct {
    scanner: Scanner,
    reader: *std.Io.Reader,

    /// The allocator is only used to track `[]` and `{}` nesting levels.
    pub fn init(allocator: Allocator, io_reader: *std.Io.Reader) @This() {
        return .{
            .scanner = Scanner.initStreaming(allocator),
            .reader = io_reader,
        };
    }
    pub fn deinit(self: *@This()) void {
        self.scanner.deinit();
        self.* = undefined;
    }

    /// Calls `std.json.Scanner.enableDiagnostics`.
    pub fn enableDiagnostics(self: *@This(), diagnostics: *Diagnostics) void {
        self.scanner.enableDiagnostics(diagnostics);
    }

    pub const NextError = std.Io.Reader.Error || Error || Allocator.Error;
    pub const SkipError = Reader.NextError;
    pub const AllocError = Reader.NextError || error{ValueTooLong};
    pub const PeekError = std.Io.Reader.Error || Error;

    /// Equivalent to `nextAllocMax(allocator, when, default_max_value_len);`
    /// See also `std.json.Token` for documentation of `nextAlloc*()` function behavior.
    pub fn nextAlloc(self: *@This(), allocator: Allocator, when: AllocWhen) Reader.AllocError!Token {
        return self.nextAllocMax(allocator, when, default_max_value_len);
    }
    /// See also `std.json.Token` for documentation of `nextAlloc*()` function behavior.
    pub fn nextAllocMax(self: *@This(), allocator: Allocator, when: AllocWhen, max_value_len: usize) Reader.AllocError!Token {
        const token_type = try self.peekNextTokenType();
        switch (token_type) {
            .number, .string => {
                var value_list = std.array_list.Managed(u8).init(allocator);
                errdefer {
                    value_list.deinit();
                }
                if (try self.allocNextIntoArrayListMax(&value_list, when, max_value_len)) |slice| {
                    return if (token_type == .number)
                        Token{ .number = slice }
                    else
                        Token{ .string = slice };
                } else {
                    return if (token_type == .number)
                        Token{ .allocated_number = try value_list.toOwnedSlice() }
                    else
                        Token{ .allocated_string = try value_list.toOwnedSlice() };
                }
            },

            // Simple tokens never alloc.
            .object_begin,
            .object_end,
            .array_begin,
            .array_end,
            .true,
            .false,
            .null,
            .end_of_document,
            => return try self.next(),
        }
    }

    /// Equivalent to `allocNextIntoArrayListMax(value_list, when, default_max_value_len);`
    pub fn allocNextIntoArrayList(self: *@This(), value_list: *std.array_list.Managed(u8), when: AllocWhen) Reader.AllocError!?[]const u8 {
        return self.allocNextIntoArrayListMax(value_list, when, default_max_value_len);
    }
    /// Calls `std.json.Scanner.allocNextIntoArrayListMax` and handles `error.BufferUnderrun`.
    pub fn allocNextIntoArrayListMax(self: *@This(), value_list: *std.array_list.Managed(u8), when: AllocWhen, max_value_len: usize) Reader.AllocError!?[]const u8 {
        while (true) {
            return self.scanner.allocNextIntoArrayListMax(value_list, when, max_value_len) catch |err| switch (err) {
                error.BufferUnderrun => {
                    try self.refillBuffer();
                    continue;
                },
                else => |other_err| return other_err,
            };
        }
    }

    /// Like `std.json.Scanner.skipValue`, but handles `error.BufferUnderrun`.
    pub fn skipValue(self: *@This()) Reader.SkipError!void {
        switch (try self.peekNextTokenType()) {
            .object_begin, .array_begin => {
                try self.skipUntilStackHeight(self.stackHeight());
            },
            .number, .string => {
                while (true) {
                    switch (try self.next()) {
                        .partial_number,
                        .partial_string,
                        .partial_string_escaped_1,
                        .partial_string_escaped_2,
                        .partial_string_escaped_3,
                        .partial_string_escaped_4,
                        => continue,

                        .number, .string => break,

                        else => unreachable,
                    }
                }
            },
            .true, .false, .null => {
                _ = try self.next();
            },

            .object_end, .array_end, .end_of_document => unreachable, // Attempt to skip a non-value token.
        }
    }
    /// Like `std.json.Scanner.skipUntilStackHeight()` but handles `error.BufferUnderrun`.
    pub fn skipUntilStackHeight(self: *@This(), terminal_stack_height: usize) Reader.NextError!void {
        while (true) {
            return self.scanner.skipUntilStackHeight(terminal_stack_height) catch |err| switch (err) {
                error.BufferUnderrun => {
                    try self.refillBuffer();
                    continue;
                },
                else => |other_err| return other_err,
            };
        }
    }

    /// Calls `std.json.Scanner.stackHeight`.
    pub fn stackHeight(self: *const @This()) usize {
        return self.scanner.stackHeight();
    }
    /// Calls `std.json.Scanner.ensureTotalStackCapacity`.
    pub fn ensureTotalStackCapacity(self: *@This(), height: usize) Allocator.Error!void {
        try self.scanner.ensureTotalStackCapacity(height);
    }

    /// See `std.json.Token` for documentation of this function.
    pub fn next(self: *@This()) Reader.NextError!Token {
        while (true) {
            return self.scanner.next() catch |err| switch (err) {
                error.BufferUnderrun => {
                    try self.refillBuffer();
                    continue;
                },
                else => |other_err| return other_err,
            };
        }
    }

    /// See `std.json.Scanner.peekNextTokenType()`.
    pub fn peekNextTokenType(self: *@This()) Reader.PeekError!TokenType {
        while (true) {
            return self.scanner.peekNextTokenType() catch |err| switch (err) {
                error.BufferUnderrun => {
                    try self.refillBuffer();
                    continue;
                },
                else => |other_err| return other_err,
            };
        }
    }

    fn refillBuffer(self: *@This()) std.Io.Reader.Error!void {
        const input = self.reader.peekGreedy(1) catch |err| switch (err) {
            error.ReadFailed => |e| return e,
            error.EndOfStream => return self.scanner.endInput(),
        };
        self.reader.toss(input.len);
        self.scanner.feedInput(input);
    }
}