config: support parsing enums

This commit is contained in:
Mitchell Hashimoto
2023-07-06 17:56:19 -07:00
parent 80e2cd4e78
commit 18e43ddb3f

View File

@ -91,26 +91,37 @@ fn parseIntoField(
.Optional => |opt| opt.child, .Optional => |opt| opt.child,
else => field.type, else => field.type,
}; };
const fieldInfo = @typeInfo(Field);
// If we are a struct and have parseCLI, we call that and use // If we are a struct and have parseCLI, we call that and use
// that to set the value. // that to set the value.
if (fieldInfo == .Struct and @hasDecl(Field, "parseCLI")) { switch (@typeInfo(Field)) {
const fnInfo = @typeInfo(@TypeOf(Field.parseCLI)).Fn; .Struct => if (@hasDecl(Field, "parseCLI")) {
switch (fnInfo.params.len) { const fnInfo = @typeInfo(@TypeOf(Field.parseCLI)).Fn;
// 1 arg = (input) => output switch (fnInfo.params.len) {
1 => @field(dst, field.name) = try Field.parseCLI(value), // 1 arg = (input) => output
1 => @field(dst, field.name) = try Field.parseCLI(value),
// 2 arg = (self, input) => void // 2 arg = (self, input) => void
2 => try @field(dst, field.name).parseCLI(value), 2 => try @field(dst, field.name).parseCLI(value),
// 3 arg = (self, alloc, input) => void // 3 arg = (self, alloc, input) => void
3 => try @field(dst, field.name).parseCLI(alloc, value), 3 => try @field(dst, field.name).parseCLI(alloc, value),
else => @compileError("parseCLI invalid argument count"), else => @compileError("parseCLI invalid argument count"),
} }
return; return;
},
.Enum => {
@field(dst, field.name) = std.meta.stringToEnum(
Field,
value orelse return error.ValueRequired,
) orelse return error.InvalidValue;
return;
},
else => {},
} }
// No parseCLI, magic the value based on the type // No parseCLI, magic the value based on the type
@ -317,6 +328,21 @@ test "parseIntoField: floats" {
try testing.expectEqual(@as(f64, 1.0), data.f64); try testing.expectEqual(@as(f64, 1.0), data.f64);
} }
test "parseIntoField: enums" {
const testing = std.testing;
var arena = ArenaAllocator.init(testing.allocator);
defer arena.deinit();
const alloc = arena.allocator();
const Enum = enum { one, two, three };
var data: struct {
v: Enum,
} = undefined;
try parseIntoField(@TypeOf(data), alloc, &data, "v", "two");
try testing.expectEqual(Enum.two, data.v);
}
test "parseIntoField: optional field" { test "parseIntoField: optional field" {
const testing = std.testing; const testing = std.testing;
var arena = ArenaAllocator.init(testing.allocator); var arena = ArenaAllocator.init(testing.allocator);