| ... | ... | @@ -1511,6 +1511,34 @@ fn parseInternal( |
| 1511 | 1511 | } |
| 1512 | 1512 | }, |
| 1513 | 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 | 1542 | switch (token) { |
| 1515 | 1543 | .ObjectBegin => {}, |
| 1516 | 1544 | else => return error.UnexpectedToken, |
| ... | ... | @@ -2290,7 +2318,7 @@ pub fn stringify( |
| 2290 | 2318 | return value.jsonStringify(options, out_stream); |
| 2291 | 2319 | } |
| 2292 | 2320 | |
| 2293 | | try out_stream.writeByte('{'); |
| 2321 | try out_stream.writeByte(if (S.is_tuple) '[' else '{'); |
| 2294 | 2322 | var field_output = false; |
| 2295 | 2323 | var child_options = options; |
| 2296 | 2324 | if (child_options.whitespace) |*child_whitespace| { |
| ... | ... | @@ -2320,11 +2348,13 @@ pub fn stringify( |
| 2320 | 2348 | if (child_options.whitespace) |child_whitespace| { |
| 2321 | 2349 | try child_whitespace.outputIndent(out_stream); |
| 2322 | 2350 | } |
| 2323 | | try encodeJsonString(Field.name, options, out_stream); |
| 2324 | | try out_stream.writeByte(':'); |
| 2325 | | if (child_options.whitespace) |child_whitespace| { |
| 2326 | | if (child_whitespace.separator) { |
| 2327 | | try out_stream.writeByte(' '); |
| 2351 | if (!S.is_tuple) { |
| 2352 | try encodeJsonString(Field.name, options, out_stream); |
| 2353 | try out_stream.writeByte(':'); |
| 2354 | if (child_options.whitespace) |child_whitespace| { |
| 2355 | if (child_whitespace.separator) { |
| 2356 | try out_stream.writeByte(' '); |
| 2357 | } |
| 2328 | 2358 | } |
| 2329 | 2359 | } |
| 2330 | 2360 | try stringify(@field(value, Field.name), child_options, out_stream); |
| ... | ... | @@ -2335,7 +2365,7 @@ pub fn stringify( |
| 2335 | 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 | 2369 | return; |
| 2340 | 2370 | }, |
| 2341 | 2371 | .ErrorSet => return stringify(@as([]const u8, @errorName(value)), options, out_stream), |
| ... | ... | @@ -2649,6 +2679,10 @@ test "stringify vector" { |
| 2649 | 2679 | try teststringify("[1,1]", @splat(2, @as(u32, 1)), StringifyOptions{}); |
| 2650 | 2680 | } |
| 2651 | 2681 | |
| 2682 | test "stringify tuple" { |
| 2683 | try teststringify("[\"foo\",42]", std.meta.Tuple(&.{ []const u8, usize }){ "foo", 42 }, StringifyOptions{}); |
| 2684 | } |
| 2685 | |
| 2652 | 2686 | fn teststringify(expected: []const u8, value: anytype, options: StringifyOptions) !void { |
| 2653 | 2687 | const ValidationWriter = struct { |
| 2654 | 2688 | const Self = @This(); |