From d6e1e85ea1f99149e650b48645b6a98888822f84 Mon Sep 17 00:00:00 2001 From: torque Date: Mon, 6 Nov 2023 20:41:53 -0800 Subject: [PATCH] parser: make tagged union field names respect expect_enum_dot It's possible that this change may get reverted in the future, but I think it makes things more consistent and has some other minor benefits, so it probably won't be. Consistency: tagged union fields are enum members by definition in zig, so it makes these act like enumerations that accept values, which is really how tagged unions work in zig. Other benefits: tagged unions do not behave like structs, and having their key start with a leading . helps to distinguish them visually. You could say that it makes communicating intent more precise. Here's an example: by default, given the following type: union(enum) { any: []const u8, int: i32, }; A corresponding nice document would now look like: .int: 42069 Whereas it used to be: int: 42069 My only concern here is that this potentially makes the serialization noisier. But if so that's true of the enum handling, too. --- src/parser/value.zig | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/parser/value.zig b/src/parser/value.zig index bfbc4e8..d7e45e8 100644 --- a/src/parser/value.zig +++ b/src/parser/value.zig @@ -270,11 +270,19 @@ pub const Value = union(enum) { switch (self) { .map, .inline_map => |map| { - // a union may not ever be deserialized from a map with more than one value + // a union may not ever be deserialized from a map with more + // (or less) than one value if (map.count() != 1) return error.BadValue; const key = map.keys()[0]; + const name = if (options.expect_enum_dot) blk: { + if (key.len > 0 and key[0] == '.') + break :blk key[1..] + else + return error.BadValue; + } else key; + inline for (unn.fields) |field| { - if (std.mem.eql(u8, key, field.name)) + if (std.mem.eql(u8, name, field.name)) return @unionInit(T, field.name, try map.get(key).?.convertTo(field.type, allocator, options)); } return error.BadValue;