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

View File

@ -270,11 +270,19 @@ pub const Value = union(enum) {
switch (self) { switch (self) {
.map, .inline_map => |map| { .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; if (map.count() != 1) return error.BadValue;
const key = map.keys()[0]; 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| { 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 @unionInit(T, field.name, try map.get(key).?.convertTo(field.type, allocator, options));
} }
return error.BadValue; return error.BadValue;