authorgravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2021-01-31 23:39:15+11:00
committergravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2021-01-31 23:41:32+11:00
log33c0a01b08262d5ad0c666d8fbeb35dfcb36b5ef
tree53d0bc43faf7e604c24b276ab1c8bbcbd475c6ce
parentfdc875ed0080cd2542a854a8cd6c627b25e9b7a4
signature Commit is signed but in an unrecognized format.

std.json support for comptime fields

Closes #6231

1 files changed, 26 insertions(+), 3 deletions(-)

lib/std/json.zig+26-3
...@@ -1471,7 +1471,7 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:...@@ -1471,7 +1471,7 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:
1471 var fields_seen = [_]bool{false} ** structInfo.fields.len;1471 var fields_seen = [_]bool{false} ** structInfo.fields.len;
1472 errdefer {1472 errdefer {
1473 inline for (structInfo.fields) |field, i| {1473 inline for (structInfo.fields) |field, i| {
1474 if (fields_seen[i]) {1474 if (fields_seen[i] and !field.is_comptime) {
1475 parseFree(field.field_type, @field(r, field.name), options);1475 parseFree(field.field_type, @field(r, field.name), options);
1476 }1476 }
1477 }1477 }
...@@ -1504,7 +1504,15 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:...@@ -1504,7 +1504,15 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:
1504 parseFree(field.field_type, @field(r, field.name), options);1504 parseFree(field.field_type, @field(r, field.name), options);
1505 }1505 }
1506 }1506 }
1507 @field(r, field.name) = try parse(field.field_type, tokens, options);1507 if (field.is_comptime) {
1508 const value = try parse(field.field_type, tokens, options);
1509 defer parseFree(field.field_type, value, options);
1510 if (value != @field(r, field.name)) {
1511 return error.UnexpectedValue;
1512 }
1513 } else {
1514 @field(r, field.name) = try parse(field.field_type, tokens, options);
1515 }
1508 fields_seen[i] = true;1516 fields_seen[i] = true;
1509 found = true;1517 found = true;
1510 break;1518 break;
...@@ -1518,7 +1526,9 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:...@@ -1518,7 +1526,9 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:
1518 inline for (structInfo.fields) |field, i| {1526 inline for (structInfo.fields) |field, i| {
1519 if (!fields_seen[i]) {1527 if (!fields_seen[i]) {
1520 if (field.default_value) |default| {1528 if (field.default_value) |default| {
1521 @field(r, field.name) = default;1529 if (!field.is_comptime) {
1530 @field(r, field.name) = default;
1531 }
1522 } else {1532 } else {
1523 return error.MissingField;1533 return error.MissingField;
1524 }1534 }
...@@ -1789,6 +1799,19 @@ test "parseFree descends into tagged union" {...@@ -1789,6 +1799,19 @@ test "parseFree descends into tagged union" {
1789 testing.expectEqual(@as(usize, 1), fail_alloc.deallocations);1799 testing.expectEqual(@as(usize, 1), fail_alloc.deallocations);
1790}1800}
17911801
1802test "parse with comptime field" {
1803 const T = struct {
1804 comptime a: i32 = 0,
1805 b: bool,
1806 };
1807 testing.expectEqual(T{ .a = 0, .b = true }, try parse(T, &TokenStream.init(
1808 \\{
1809 \\ "a": 0,
1810 \\ "b": true
1811 \\}
1812 ), ParseOptions{}));
1813}
1814
1792test "parse into struct with no fields" {1815test "parse into struct with no fields" {
1793 const T = struct {};1816 const T = struct {};
1794 testing.expectEqual(T{}, try parse(T, &TokenStream.init("{}"), ParseOptions{}));1817 testing.expectEqual(T{}, try parse(T, &TokenStream.init("{}"), ParseOptions{}));