authorgravatar for jjhellst@gmail.comJanne Hellsten <jjhellst@gmail.com> 2023-04-26 00:52:17+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-04-26 00:52:17+03:00
log61236c2aa1610e0ce470bd64ba930a6430ad6de2
treeb953ea0fe35a0c78f8e21f90ee5e542eb6040d2f
parent5b9e528bc550e7ea9e286fdd2324316f9895d5da
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

std: @Vector support for std.json.parse


2 files changed, 71 insertions(+), 20 deletions(-)

lib/std/json.zig+52-20
......@@ -1389,6 +1389,11 @@ fn ParseInternalErrorImpl(comptime T: type, comptime inferred_types: []const typ
13891389 UnescapeValidStringError ||
13901390 ParseInternalErrorImpl(arrayInfo.child, inferred_types ++ [_]type{T});
13911391 },
1392 .Vector => |vecInfo| {
1393 return error{ UnexpectedEndOfJson, UnexpectedToken, LengthMismatch } || TokenStream.Error ||
1394 UnescapeValidStringError ||
1395 ParseInternalErrorImpl(vecInfo.child, inferred_types ++ [_]type{T});
1396 },
13921397 .Pointer => |ptrInfo| {
13931398 var errors = error{AllocatorRequired} || std.mem.Allocator.Error;
13941399 switch (ptrInfo.size) {
......@@ -1408,6 +1413,35 @@ fn ParseInternalErrorImpl(comptime T: type, comptime inferred_types: []const typ
14081413 unreachable;
14091414}
14101415
1416fn parseInternalArray(
1417 comptime T: type,
1418 comptime Elt: type,
1419 comptime arr_len: usize,
1420 tokens: *TokenStream,
1421 options: ParseOptions,
1422) ParseInternalError(T)!T {
1423 var r: T = undefined;
1424 var i: usize = 0;
1425 var child_options = options;
1426 child_options.allow_trailing_data = true;
1427 errdefer {
1428 // Without the r.len check `r[i]` is not allowed
1429 if (arr_len > 0) while (true) : (i -= 1) {
1430 parseFree(Elt, r[i], options);
1431 if (i == 0) break;
1432 };
1433 }
1434 if (arr_len > 0) while (i < arr_len) : (i += 1) {
1435 r[i] = try parse(Elt, tokens, child_options);
1436 };
1437 const tok = (try tokens.next()) orelse return error.UnexpectedEndOfJson;
1438 switch (tok) {
1439 .ArrayEnd => {},
1440 else => return error.UnexpectedToken,
1441 }
1442 return r;
1443}
1444
14111445fn parseInternal(
14121446 comptime T: type,
14131447 token: Token,
......@@ -1624,26 +1658,8 @@ fn parseInternal(
16241658 .Array => |arrayInfo| {
16251659 switch (token) {
16261660 .ArrayBegin => {
1627 var r: T = undefined;
1628 var i: usize = 0;
1629 var child_options = options;
1630 child_options.allow_trailing_data = true;
1631 errdefer {
1632 // Without the r.len check `r[i]` is not allowed
1633 if (r.len > 0) while (true) : (i -= 1) {
1634 parseFree(arrayInfo.child, r[i], options);
1635 if (i == 0) break;
1636 };
1637 }
1638 while (i < r.len) : (i += 1) {
1639 r[i] = try parse(arrayInfo.child, tokens, child_options);
1640 }
1641 const tok = (try tokens.next()) orelse return error.UnexpectedEndOfJson;
1642 switch (tok) {
1643 .ArrayEnd => {},
1644 else => return error.UnexpectedToken,
1645 }
1646 return r;
1661 const len = @typeInfo(T).Array.len;
1662 return parseInternalArray(T, arrayInfo.child, len, tokens, options);
16471663 },
16481664 .String => |stringToken| {
16491665 if (arrayInfo.child != u8) return error.UnexpectedToken;
......@@ -1659,6 +1675,15 @@ fn parseInternal(
16591675 else => return error.UnexpectedToken,
16601676 }
16611677 },
1678 .Vector => |vecInfo| {
1679 switch (token) {
1680 .ArrayBegin => {
1681 const len = @typeInfo(T).Vector.len;
1682 return parseInternalArray(T, vecInfo.child, len, tokens, options);
1683 },
1684 else => return error.UnexpectedToken,
1685 }
1686 },
16621687 .Pointer => |ptrInfo| {
16631688 const allocator = options.allocator orelse return error.AllocatorRequired;
16641689 switch (ptrInfo.size) {
......@@ -1804,6 +1829,13 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void {
18041829 parseFree(arrayInfo.child, v, options);
18051830 }
18061831 },
1832 .Vector => |vecInfo| {
1833 var i: usize = 0;
1834 var v_len: usize = @typeInfo(@TypeOf(value)).Vector.len;
1835 while (i < v_len) : (i += 1) {
1836 parseFree(vecInfo.child, value[i], options);
1837 }
1838 },
18071839 .Pointer => |ptrInfo| {
18081840 const allocator = options.allocator orelse unreachable;
18091841 switch (ptrInfo.size) {
lib/std/json/test.zig+19
......@@ -2550,6 +2550,25 @@ test "parse into double recursive union definition" {
25502550 try testing.expectEqual(@as(i64, 58), r.values.array[0].array[0].integer);
25512551}
25522552
2553test "parse into vector" {
2554 const options = ParseOptions{ .allocator = testing.allocator };
2555 const T = struct {
2556 vec_i32: @Vector(4, i32),
2557 vec_f32: @Vector(2, f32),
2558 };
2559 var ts = TokenStream.init(
2560 \\{
2561 \\ "vec_f32": [1.5, 2.5],
2562 \\ "vec_i32": [4, 5, 6, 7]
2563 \\}
2564 );
2565 const r = try parse(T, &ts, options);
2566 defer parseFree(T, r, options);
2567 try testing.expectApproxEqAbs(@as(f32, 1.5), r.vec_f32[0], 0.0000001);
2568 try testing.expectApproxEqAbs(@as(f32, 2.5), r.vec_f32[1], 0.0000001);
2569 try testing.expectEqual(@Vector(4, i32){ 4, 5, 6, 7 }, r.vec_i32);
2570}
2571
25532572test "json.parser.dynamic" {
25542573 var p = Parser.init(testing.allocator, false);
25552574 defer p.deinit();