I have an enum, say
pub const Severity = enum {
low,
medium,
high
};
I get a command line string input and parse to this enum.
In case when the input string cannot be parsed, I want to display an error message that lists the enum variants as the accepted inputs.
But I do not want to handcode the variants as string, instead I would like to generate the list of acceptable input string from the enum.
What is the idiomatic way to go about this in Zig? such that I can easily have error message like this
"Error supported input are low, medium, high"
dimdin
August 16, 2024, 2:34pm
2
@typeInfo
returns an enum describing any zig type
.
Using inline for
you can concatenate the enum field names. In the following example I just print the names.
const std = @import("std");
pub const Severity = enum {
low,
medium,
high,
};
pub fn main() void {
inline for (@typeInfo(Severity).Enum.fields) |field| {
std.debug.print("{s}\n", .{field.name});
}
}
1 Like
kudu
August 16, 2024, 2:45pm
3
Or, if you need an array of fleld names:
const names = std.meta.fieldNames(Severity);
2 Likes
UPD: made it more generic.
Something like this:
const std = @import("std");
fn enumToErrorMessage(comptime E: type) []const u8 {
return comptime blk: {
var msg: []const u8 = "error: supported " ++ @typeName(E) ++ " values are ";
const field_names = std.meta.fieldNames(E);
for (field_names, 0..) |field_name, i| {
msg = msg ++ field_name;
if (i < field_names.len - 1) {
msg = msg ++ ", ";
}
}
msg = msg ++ "\n";
break :blk msg;
};
}
const Severity = enum {
low,
medium,
high,
};
pub fn main() !void {
const input_reader = std.io.getStdIn().reader();
const error_writer = std.io.getStdErr().writer();
var input_buf: [8]u8 = undefined;
const input = try input_reader.readUntilDelimiterOrEof(input_buf[0..], '\n');
if (std.meta.stringToEnum(Severity, input.?)) |severity| {
std.debug.print("{}\n", .{severity});
} else {
try error_writer.writeAll(enumToErrorMessage(Severity));
}
}
5 Likes
finlaydotb:
In case when the input string cannot be parsed, I want to display an error message that lists the enum variants as the accepted inputs.
But I do not want to handcode the variants as string, instead I would like to generate the list of acceptable input string from the enum.
I’d suggest looking into std.enums , it has several data structures which may fit your needs. To map from an enum variant to its name at runtime, your best bet is to construct a StaticStringMap with initComptime
. If all you’re interested in is a comma-separated string containing the names of all the variants, you can construct that as well using something like an inline for
loop in a comptime
block.
1 Like