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...@@ -1389,6 +1389,11 @@ fn ParseInternalErrorImpl(comptime T: type, comptime inferred_types: []const typ
1389 UnescapeValidStringError ||1389 UnescapeValidStringError ||
1390 ParseInternalErrorImpl(arrayInfo.child, inferred_types ++ [_]type{T});1390 ParseInternalErrorImpl(arrayInfo.child, inferred_types ++ [_]type{T});
1391 },1391 },
1392 .Vector => |vecInfo| {
1393 return error{ UnexpectedEndOfJson, UnexpectedToken, LengthMismatch } || TokenStream.Error ||
1394 UnescapeValidStringError ||
1395 ParseInternalErrorImpl(vecInfo.child, inferred_types ++ [_]type{T});
1396 },
1392 .Pointer => |ptrInfo| {1397 .Pointer => |ptrInfo| {
1393 var errors = error{AllocatorRequired} || std.mem.Allocator.Error;1398 var errors = error{AllocatorRequired} || std.mem.Allocator.Error;
1394 switch (ptrInfo.size) {1399 switch (ptrInfo.size) {
...@@ -1408,6 +1413,35 @@ fn ParseInternalErrorImpl(comptime T: type, comptime inferred_types: []const typ...@@ -1408,6 +1413,35 @@ fn ParseInternalErrorImpl(comptime T: type, comptime inferred_types: []const typ
1408 unreachable;1413 unreachable;
1409}1414}
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
1411fn parseInternal(1445fn parseInternal(
1412 comptime T: type,1446 comptime T: type,
1413 token: Token,1447 token: Token,
...@@ -1624,26 +1658,8 @@ fn parseInternal(...@@ -1624,26 +1658,8 @@ fn parseInternal(
1624 .Array => |arrayInfo| {1658 .Array => |arrayInfo| {
1625 switch (token) {1659 switch (token) {
1626 .ArrayBegin => {1660 .ArrayBegin => {
1627 var r: T = undefined;1661 const len = @typeInfo(T).Array.len;
1628 var i: usize = 0;1662 return parseInternalArray(T, arrayInfo.child, len, tokens, options);
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;
1647 },1663 },
1648 .String => |stringToken| {1664 .String => |stringToken| {
1649 if (arrayInfo.child != u8) return error.UnexpectedToken;1665 if (arrayInfo.child != u8) return error.UnexpectedToken;
...@@ -1659,6 +1675,15 @@ fn parseInternal(...@@ -1659,6 +1675,15 @@ fn parseInternal(
1659 else => return error.UnexpectedToken,1675 else => return error.UnexpectedToken,
1660 }1676 }
1661 },1677 },
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 },
1662 .Pointer => |ptrInfo| {1687 .Pointer => |ptrInfo| {
1663 const allocator = options.allocator orelse return error.AllocatorRequired;1688 const allocator = options.allocator orelse return error.AllocatorRequired;
1664 switch (ptrInfo.size) {1689 switch (ptrInfo.size) {
...@@ -1804,6 +1829,13 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void {...@@ -1804,6 +1829,13 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void {
1804 parseFree(arrayInfo.child, v, options);1829 parseFree(arrayInfo.child, v, options);
1805 }1830 }
1806 },1831 },
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 },
1807 .Pointer => |ptrInfo| {1839 .Pointer => |ptrInfo| {
1808 const allocator = options.allocator orelse unreachable;1840 const allocator = options.allocator orelse unreachable;
1809 switch (ptrInfo.size) {1841 switch (ptrInfo.size) {
lib/std/json/test.zig+19
...@@ -2550,6 +2550,25 @@ test "parse into double recursive union definition" {...@@ -2550,6 +2550,25 @@ test "parse into double recursive union definition" {
2550 try testing.expectEqual(@as(i64, 58), r.values.array[0].array[0].integer);2550 try testing.expectEqual(@as(i64, 58), r.values.array[0].array[0].integer);
2551}2551}
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
2553test "json.parser.dynamic" {2572test "json.parser.dynamic" {
2554 var p = Parser.init(testing.allocator, false);2573 var p = Parser.init(testing.allocator, false);
2555 defer p.deinit();2574 defer p.deinit();