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:
This commit is contained in:
torque 2023-11-06 20:32:40 -08:00
parent d6e1e85ea1
commit 2f90ccba6f
Signed by: torque
SSH Key Fingerprint: SHA256:nCrXefBNo6EbjNSQhv0nXmEg/VuNq3sMF5b8zETw3Tk

View File

@ -287,9 +287,28 @@ pub const Value = union(enum) {
} }
return error.BadValue; return error.BadValue;
}, },
// TODO: if the field is a 0 width type like void, we could parse it inline .scalar, .string => |str, tag| {
// directly from a scalar/string value (i.e. a name with no if (tag == .string and !options.coerce_strings) return error.BadValue;
// corresponding value) 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, else => return error.BadValue,
} }
}, },