Is it possible to use non-exhaustive enums in `zon`?

Hello

In trying to figure out the configuration for zift I wanted to have the indent field be just a non exhaustive enum, with the tabs value being 0, and other value being spaces. However, apparently simply typing the number in the zon like

.{
    .indent = 4,
}

for example, doesn’t work.

Is there a way to do something like this or does it have to be a union(enum) ?

1 Like

I presume you would need to say

.{
    .indent = @enumFromInt(4),
}

For it to have any chance of working. I don’t know if Zon accepts this, however, it would diverge from Zig if it allowed an integer to cast straight to an enum like that.

Can’t you use something like a u8 or u16 instead for indent’s type?

I could, but I want to write .tabs

Indent should be a string and then you write whatever you want the indent characters to be,

1 Like

It’s a little different than your original idea, but a tagged union could work well here:

pub const IndentStyle = union(enum) {
    tabs,
    spaces: u8,
};

Used like:

.{
    .indents = .tabs,
}

or

.{
    .indents = .{ .spaces = 4 },
}
4 Likes

This is also better IMHO.

It’s “just tabs” or “this many spaces”, which is the actual model of the data.

1 Like

@asibahi reading your OP again I realized that you’ve already considered this solution. My bad!

Yeah that’s what I ended up doing.

It is probably better in this case but I think there is use of integer fields that can have some tagged values. The example coming to mind right now is font weight (for a future zig editor or w/e), where the user either writes 350 or .regular.

Tho in that case probably just use a proper config language.

1 Like

Yea, I think I’m the context of configuration this makes sense, but for the language as a whole it’s syntactic sugar that probably wouldn’t break the threshold for being worth it for the core team to implement.

That said, I’m pretty you could get the behavior you’re after by using a custom parsing function on that enum.

hah really? I know this exists in json (or used to) but is it in zon as well?

Using the power of reading the source code, this does not appear to be supported.

The stringify documentation puts non-exhaustive enums in list of types that can’t be serialized.

The serializer uses @tagName.

The parser expects an enum literal.

To find this, I looked at zig std and searched for zon. In there, I looked for the relevant functions, then used the [src] link to read the code, and dug through a few functions until I found the relevant sections. I’ve found the files in codeberg for purposes of permalinks to the relevant lines.

5 Likes

Unbeatable tbh.

2 Likes

Maybe you could do something similar to this:

So basically creating a non-default parse, by directly accessing the Ast yourself.

Oof. Yea, I’m 0/2 on helping out.

I must’ve imagined that the zon API more closely mirrored that of json.

I haven’t touched this stuff yet but just chiming in with my two cents: I think if your type is a nonexhaustive enum (which therefore has a backing integer type), it should succeed when the value is a raw integer that fits in the backing integer type. Same goes for packed structs.

5 Likes