Skip to content

Commit

Permalink
dom: fix Array.at() + add tests
Browse files Browse the repository at this point in the history
this bug was discovered in simdjzon-rpc. previously the new tests
failed.
  • Loading branch information
travisstaloch committed Oct 9, 2023
1 parent dffc4e3 commit 6467883
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 11 deletions.
23 changes: 12 additions & 11 deletions src/dom.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1504,22 +1504,22 @@ pub const Parser = struct {
return parser.stage2();
}

pub inline fn element(parser: Parser) Element {
return .{
.tape = .{ .doc = &parser.doc, .idx = 1 },
};
pub fn element(parser: *const Parser) Element {
return .{ .tape = .{ .doc = &parser.doc, .idx = 1 } };
}
};

pub const Array = struct {
tape: TapeRef,
pub fn at(a: Array, idx: usize) ?Element {
var it = TapeRefIterator.init(a);
const target_idx = idx + it.tape.idx + idx;
while (true) {
if (it.tape.idx == target_idx)
return Element{ .tape = .{ .doc = it.tape.doc, .idx = it.tape.idx } };
_ = it.next() orelse break;
pub fn at(_a: Array, idx: usize) ?Element {
var i: usize = 0;
const end = _a.tape.after_element() - 1;
var a = Array{ .tape = .{ .idx = _a.tape.idx + 1, .doc = _a.tape.doc } };
while (a.tape.idx < end) {
if (i == idx)
return .{ .tape = a.tape };
a.tape.idx = a.tape.after_element();
i += 1;
}
return null;
}
Expand Down Expand Up @@ -1688,6 +1688,7 @@ const TapeRef = struct {

pub fn get_string_length(tr: TapeRef) u32 {
const string_buf_index = tr.value();
// std.debug.print("get_string_length string_buf_index={}\n", .{string_buf_index});
return mem.readIntLittle(u32, (tr.doc.string_buf.ptr + string_buf_index)[0..@sizeOf(u32)]);
}

Expand Down
46 changes: 46 additions & 0 deletions src/tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,52 @@ test "search tape" {
try testing.expectEqual(@as(i64, 116), try array1.get_int64());
}

test "array of objects" {
var parser = try dom.Parser.initFixedBuffer(allr,
\\[{"a": 1}, {"b": 2}]
, .{});
defer parser.deinit();
try parser.parse();
const ele = parser.element();
try testing.expect(ele.is(.ARRAY));
const array = try ele.get_array();
const array0 = array.at(0) orelse unreachable;
try testing.expect(array0.is(.OBJECT));
const array0_afield = array0.at_key("a") orelse unreachable;
try testing.expect(array0_afield.is(.INT64));
try testing.expectEqual(@as(i64, 1), try array0_afield.get_int64());
}

test "array of objects 2" {
var parser = try dom.Parser.initFixedBuffer(allr,
\\[{"foo": null, "params": [1,2,4], "id": 1},
\\ {"foo": null, "params": [1,2,10], "id": 2}]
, .{});
defer parser.deinit();
try parser.parse();
const ele = parser.element();
try testing.expect(ele.is(.ARRAY));
const array = try ele.get_array();

const array0 = array.at(0) orelse unreachable;
try testing.expect(array0.is(.OBJECT));
const params0 = array0.at_key("params") orelse unreachable;
try testing.expect(params0.is(.ARRAY));
const params0_3 = params0.at(2) orelse unreachable;
try testing.expectEqual(@as(i64, 4), try params0_3.get_int64());
const id0 = array0.at_key("id") orelse unreachable;
try testing.expectEqual(@as(i64, 1), try id0.get_int64());

const array1 = array.at(1) orelse unreachable;
try testing.expect(array1.is(.OBJECT));
const params1 = array1.at_key("params") orelse unreachable;
try testing.expect(params1.is(.ARRAY));
const params1_3 = params1.at(2) orelse unreachable;
try testing.expectEqual(@as(i64, 10), try params1_3.get_int64());
const id1 = array1.at_key("id") orelse unreachable;
try testing.expectEqual(@as(i64, 2), try id1.get_int64());
}

test "json pointer" {
const input =
\\{"a": {"b": [1,2,3], "c": 3.1415, "d": true, "e": "e-string", "f": null}}
Expand Down

0 comments on commit 6467883

Please sign in to comment.