From f88bb56ee5be01b83ab35bd7b6c95539a4e04a9d Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 1 Feb 2021 00:22:00 +1100 Subject: [PATCH] std.json union handling should bubble up AllocationRequired --- lib/std/json.zig | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/std/json.zig b/lib/std/json.zig index 1fdd7ce9d6..5e13233d17 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -1454,6 +1454,8 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options: // Parsing some types won't have OutOfMemory in their // error-sets, for the condition to be valid, merge it in. if (@as(@TypeOf(err) || error{OutOfMemory}, err) == error.OutOfMemory) return err; + // Bubble up AllocatorRequired, as it indicates missing option + if (@as(@TypeOf(err) || error{AllocatorRequired}, err) == error.AllocatorRequired) return err; // otherwise continue through the `inline for` } } @@ -1741,18 +1743,6 @@ test "parse into tagged union" { testing.expectEqual(T{ .float = 1.5 }, try parse(T, &TokenStream.init("1.5"), ParseOptions{})); } - { // if union matches string member, fails with NoUnionMembersMatched rather than AllocatorRequired - // Note that this behaviour wasn't necessarily by design, but was - // what fell out of the implementation and may result in interesting - // API breakage if changed - const T = union(enum) { - int: i32, - float: f64, - string: []const u8, - }; - testing.expectError(error.NoUnionMembersMatched, parse(T, &TokenStream.init("\"foo\""), ParseOptions{})); - } - { // failing allocations should be bubbled up instantly without trying next member var fail_alloc = testing.FailingAllocator.init(testing.allocator, 0); const options = ParseOptions{ .allocator = &fail_alloc.allocator }; @@ -1782,6 +1772,25 @@ test "parse into tagged union" { } } +test "parse union bubbles up AllocatorRequired" { + { // string member first in union (and not matching) + const T = union(enum) { + string: []const u8, + int: i32, + }; + testing.expectError(error.AllocatorRequired, parse(T, &TokenStream.init("42"), ParseOptions{})); + } + + { // string member not first in union (and matching) + const T = union(enum) { + int: i32, + float: f64, + string: []const u8, + }; + testing.expectError(error.AllocatorRequired, parse(T, &TokenStream.init("\"foo\""), ParseOptions{})); + } +} + test "parseFree descends into tagged union" { var fail_alloc = testing.FailingAllocator.init(testing.allocator, 1); const options = ParseOptions{ .allocator = &fail_alloc.allocator };