From 2f90ccba6f80ffd3233366ee433b52331a8d59ea Mon Sep 17 00:00:00 2001 From: torque Date: Mon, 6 Nov 2023 20:32:40 -0800 Subject: [PATCH] parser: accept 0-size tagged union values as scalars Given the type: union(enum) { none: void, any: []const u8, }; Previously your document would have had to be .none: But now this can also be parsed as the simple scalar .none This is much nicer if the tagged union is a member of a larger type, like a struct, since the value can be specified in-line without needing to create a map. my_union: .none Whereas previously this would have had to have been (this style is still supported): my_union: { .none: } or my_union: .none: --- src/parser/value.zig | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/parser/value.zig b/src/parser/value.zig index d7e45e8..0d27ffc 100644 --- a/src/parser/value.zig +++ b/src/parser/value.zig @@ -287,9 +287,28 @@ pub const Value = union(enum) { } return error.BadValue; }, - // TODO: if the field is a 0 width type like void, we could parse it - // directly from a scalar/string value (i.e. a name with no - // corresponding value) + inline .scalar, .string => |str, tag| { + if (tag == .string and !options.coerce_strings) return error.BadValue; + const name = if (options.expect_enum_dot) blk: { + if (str.len > 0 and str[0] == '.') + break :blk str[1..] + else + return error.BadValue; + } else str; + + inline for (unn.fields) |field| { + if (@sizeOf(field.type) != 0) continue; + // this logic may be a little off: comtime_int, + // comptime_float, and type will all have size 0 because + // they can't be used at runtime. On the other hand, trying + // to use them here should result in a compile error? Also, + // it's a 0 sized type so initializing it as undefined + // shouldn't be a problem. As far as I know. + if (std.mem.eql(u8, name, field.name)) + return @unionInit(T, field.name, undefined); + } + return error.BadValue; + }, else => return error.BadValue, } },