DoxigAlpha

jsonParse

Function parameters

Parameters

#
source:anytype

Represents any JSON value, potentially containing other JSON values.

Types

#
Value
Represents any JSON value, potentially containing other JSON values.

Source

Implementation

#
pub fn jsonParse(allocator: Allocator, source: anytype, options: ParseOptions) ParseError(@TypeOf(source.*))!@This() {
    // The grammar of the stack is:
    //  (.array | .object .string)*
    var stack = Array.init(allocator);
    defer stack.deinit();

    while (true) {
        // Assert the stack grammar at the top of the stack.
        debug.assert(stack.items.len == 0 or
            stack.items[stack.items.len - 1] == .array or
            (stack.items[stack.items.len - 2] == .object and stack.items[stack.items.len - 1] == .string));

        switch (try source.nextAllocMax(allocator, .alloc_always, options.max_value_len.?)) {
            .allocated_string => |s| {
                return try handleCompleteValue(&stack, allocator, source, Value{ .string = s }, options) orelse continue;
            },
            .allocated_number => |slice| {
                if (options.parse_numbers) {
                    return try handleCompleteValue(&stack, allocator, source, Value.parseFromNumberSlice(slice), options) orelse continue;
                } else {
                    return try handleCompleteValue(&stack, allocator, source, Value{ .number_string = slice }, options) orelse continue;
                }
            },

            .null => return try handleCompleteValue(&stack, allocator, source, .null, options) orelse continue,
            .true => return try handleCompleteValue(&stack, allocator, source, Value{ .bool = true }, options) orelse continue,
            .false => return try handleCompleteValue(&stack, allocator, source, Value{ .bool = false }, options) orelse continue,

            .object_begin => {
                switch (try source.nextAllocMax(allocator, .alloc_always, options.max_value_len.?)) {
                    .object_end => return try handleCompleteValue(&stack, allocator, source, Value{ .object = ObjectMap.init(allocator) }, options) orelse continue,
                    .allocated_string => |key| {
                        try stack.appendSlice(&[_]Value{
                            Value{ .object = ObjectMap.init(allocator) },
                            Value{ .string = key },
                        });
                    },
                    else => unreachable,
                }
            },
            .array_begin => {
                try stack.append(Value{ .array = Array.init(allocator) });
            },
            .array_end => return try handleCompleteValue(&stack, allocator, source, stack.pop().?, options) orelse continue,

            else => unreachable,
        }
    }
}