std: fix json parsing into unions

This commit is contained in:
daurnimator 2020-05-18 02:51:02 +10:00 committed by Andrew Kelley
parent d3ebd42865
commit 978a38ee40

View File

@ -1418,7 +1418,10 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:
if (unionInfo.tag_type) |_| { if (unionInfo.tag_type) |_| {
// try each of the union fields until we find one that matches // try each of the union fields until we find one that matches
inline for (unionInfo.fields) |u_field| { inline for (unionInfo.fields) |u_field| {
if (parseInternal(u_field.field_type, token, tokens, options)) |value| { // take a copy of tokens so we can withhold mutations until success
var tokens_copy = tokens.*;
if (parseInternal(u_field.field_type, token, &tokens_copy, options)) |value| {
tokens.* = tokens_copy;
return @unionInit(T, u_field.name, value); return @unionInit(T, u_field.name, value);
} else |err| { } else |err| {
// Bubble up error.OutOfMemory // Bubble up error.OutOfMemory
@ -1733,6 +1736,14 @@ test "parse into tagged union" {
}; };
testing.expectEqual(T{ .x = 42 }, try parse(T, &TokenStream.init("42"), ParseOptions{})); testing.expectEqual(T{ .x = 42 }, try parse(T, &TokenStream.init("42"), ParseOptions{}));
} }
{ // needs to back out when first union member doesn't match
const T = union(enum) {
A: struct { x: u32 },
B: struct { y: u32 },
};
testing.expectEqual(T{ .B = .{.y = 42} }, try parse(T, &TokenStream.init("{\"y\":42}"), ParseOptions{}));
}
} }
test "parseFree descends into tagged union" { test "parseFree descends into tagged union" {