authorgravatar for marcus@ramse.seMarcus Ramse <marcus@ramse.se> 2023-03-08 16:04:57+01:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-03-21 15:01:45+02:00
log1e087d3a64e6b504524c32f72b22faffef78b41e
tree792f887aebef9f3e6ac6c1310a953b1e883ecf20
parentcd3575b0f0c808f6c63a7174d9371f65691428eb

std.json: support tuples


2 files changed, 91 insertions(+), 7 deletions(-)

lib/std/json.zig+41-7
...@@ -1511,6 +1511,34 @@ fn parseInternal(...@@ -1511,6 +1511,34 @@ fn parseInternal(
1511 }1511 }
1512 },1512 },
1513 .Struct => |structInfo| {1513 .Struct => |structInfo| {
1514 if (structInfo.is_tuple) {
1515 switch (token) {
1516 .ArrayBegin => {},
1517 else => return error.UnexpectedToken,
1518 }
1519 var r: T = undefined;
1520 var child_options = options;
1521 child_options.allow_trailing_data = true;
1522 var fields_seen: usize = 0;
1523 errdefer {
1524 inline for (0..structInfo.fields.len) |i| {
1525 if (i < fields_seen) {
1526 parseFree(structInfo.fields[i].type, r[i], options);
1527 }
1528 }
1529 }
1530 inline for (0..structInfo.fields.len) |i| {
1531 r[i] = try parse(structInfo.fields[i].type, tokens, child_options);
1532 fields_seen = i + 1;
1533 }
1534 const tok = (try tokens.next()) orelse return error.UnexpectedEndOfJson;
1535 switch (tok) {
1536 .ArrayEnd => {},
1537 else => return error.UnexpectedToken,
1538 }
1539 return r;
1540 }
1541
1514 switch (token) {1542 switch (token) {
1515 .ObjectBegin => {},1543 .ObjectBegin => {},
1516 else => return error.UnexpectedToken,1544 else => return error.UnexpectedToken,
...@@ -2290,7 +2318,7 @@ pub fn stringify(...@@ -2290,7 +2318,7 @@ pub fn stringify(
2290 return value.jsonStringify(options, out_stream);2318 return value.jsonStringify(options, out_stream);
2291 }2319 }
22922320
2293 try out_stream.writeByte('{');2321 try out_stream.writeByte(if (S.is_tuple) '[' else '{');
2294 var field_output = false;2322 var field_output = false;
2295 var child_options = options;2323 var child_options = options;
2296 if (child_options.whitespace) |*child_whitespace| {2324 if (child_options.whitespace) |*child_whitespace| {
...@@ -2320,11 +2348,13 @@ pub fn stringify(...@@ -2320,11 +2348,13 @@ pub fn stringify(
2320 if (child_options.whitespace) |child_whitespace| {2348 if (child_options.whitespace) |child_whitespace| {
2321 try child_whitespace.outputIndent(out_stream);2349 try child_whitespace.outputIndent(out_stream);
2322 }2350 }
2323 try encodeJsonString(Field.name, options, out_stream);2351 if (!S.is_tuple) {
2324 try out_stream.writeByte(':');2352 try encodeJsonString(Field.name, options, out_stream);
2325 if (child_options.whitespace) |child_whitespace| {2353 try out_stream.writeByte(':');
2326 if (child_whitespace.separator) {2354 if (child_options.whitespace) |child_whitespace| {
2327 try out_stream.writeByte(' ');2355 if (child_whitespace.separator) {
2356 try out_stream.writeByte(' ');
2357 }
2328 }2358 }
2329 }2359 }
2330 try stringify(@field(value, Field.name), child_options, out_stream);2360 try stringify(@field(value, Field.name), child_options, out_stream);
...@@ -2335,7 +2365,7 @@ pub fn stringify(...@@ -2335,7 +2365,7 @@ pub fn stringify(
2335 try whitespace.outputIndent(out_stream);2365 try whitespace.outputIndent(out_stream);
2336 }2366 }
2337 }2367 }
2338 try out_stream.writeByte('}');2368 try out_stream.writeByte(if (S.is_tuple) ']' else '}');
2339 return;2369 return;
2340 },2370 },
2341 .ErrorSet => return stringify(@as([]const u8, @errorName(value)), options, out_stream),2371 .ErrorSet => return stringify(@as([]const u8, @errorName(value)), options, out_stream),
...@@ -2649,6 +2679,10 @@ test "stringify vector" {...@@ -2649,6 +2679,10 @@ test "stringify vector" {
2649 try teststringify("[1,1]", @splat(2, @as(u32, 1)), StringifyOptions{});2679 try teststringify("[1,1]", @splat(2, @as(u32, 1)), StringifyOptions{});
2650}2680}
26512681
2682test "stringify tuple" {
2683 try teststringify("[\"foo\",42]", std.meta.Tuple(&.{ []const u8, usize }){ "foo", 42 }, StringifyOptions{});
2684}
2685
2652fn teststringify(expected: []const u8, value: anytype, options: StringifyOptions) !void {2686fn teststringify(expected: []const u8, value: anytype, options: StringifyOptions) !void {
2653 const ValidationWriter = struct {2687 const ValidationWriter = struct {
2654 const Self = @This();2688 const Self = @This();
lib/std/json/test.zig+50
...@@ -2459,6 +2459,56 @@ test "parse into struct ignoring unknown fields" {...@@ -2459,6 +2459,56 @@ test "parse into struct ignoring unknown fields" {
2459 try testing.expectEqualSlices(u8, "zig", r.language);2459 try testing.expectEqualSlices(u8, "zig", r.language);
2460}2460}
24612461
2462test "parse into tuple" {
2463 const options = ParseOptions{ .allocator = testing.allocator };
2464 const Union = union(enum) {
2465 char: u8,
2466 float: f64,
2467 string: []const u8,
2468 };
2469 const T = std.meta.Tuple(&.{
2470 i64,
2471 f64,
2472 bool,
2473 []const u8,
2474 ?bool,
2475 struct {
2476 foo: i32,
2477 bar: []const u8,
2478 },
2479 std.meta.Tuple(&.{ u8, []const u8, u8 }),
2480 Union,
2481 });
2482 var ts = TokenStream.init(
2483 \\[
2484 \\ 420,
2485 \\ 3.14,
2486 \\ true,
2487 \\ "zig",
2488 \\ null,
2489 \\ {
2490 \\ "foo": 1,
2491 \\ "bar": "zero"
2492 \\ },
2493 \\ [4, "två", 42],
2494 \\ 12.34
2495 \\]
2496 );
2497 const r = try parse(T, &ts, options);
2498 defer parseFree(T, r, options);
2499 try testing.expectEqual(@as(i64, 420), r[0]);
2500 try testing.expectEqual(@as(f64, 3.14), r[1]);
2501 try testing.expectEqual(true, r[2]);
2502 try testing.expectEqualSlices(u8, "zig", r[3]);
2503 try testing.expectEqual(@as(?bool, null), r[4]);
2504 try testing.expectEqual(@as(i32, 1), r[5].foo);
2505 try testing.expectEqualSlices(u8, "zero", r[5].bar);
2506 try testing.expectEqual(@as(u8, 4), r[6][0]);
2507 try testing.expectEqualSlices(u8, "två", r[6][1]);
2508 try testing.expectEqual(@as(u8, 42), r[6][2]);
2509 try testing.expectEqual(Union{ .float = 12.34 }, r[7]);
2510}
2511
2462const ParseIntoRecursiveUnionDefinitionValue = union(enum) {2512const ParseIntoRecursiveUnionDefinitionValue = union(enum) {
2463 integer: i64,2513 integer: i64,
2464 array: []const ParseIntoRecursiveUnionDefinitionValue,2514 array: []const ParseIntoRecursiveUnionDefinitionValue,