From 9de940cbbfd5ada9e17298cd5feb103db6a8a979 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Tue, 9 Jul 2024 09:03:23 -0400 Subject: [PATCH] cli: boolean value support for packed structs Allow standalone boolean values like "true" and "false" to turn on or off all of the struct's fields. --- src/cli/args.zig | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/cli/args.zig b/src/cli/args.zig index 707416e38..0f21ea79b 100644 --- a/src/cli/args.zig +++ b/src/cli/args.zig @@ -285,6 +285,17 @@ fn parsePackedStruct(comptime T: type, v: []const u8) !T { var result: T = .{}; + // Allow standalone boolean values like "true" and "false" to + // turn on or off all of the struct's fields. + bools: { + const b = parseBool(v) catch break :bools; + inline for (info.fields) |field| { + assert(field.type == bool); + @field(result, field.name) = b; + } + return result; + } + // We split each value by "," var iter = std.mem.splitSequence(u8, v, ","); loop: while (iter.next()) |part_raw| { @@ -586,6 +597,34 @@ test "parseIntoField: packed struct negation" { try testing.expect(!data.v.b); } +test "parseIntoField: packed struct true/false" { + const testing = std.testing; + var arena = ArenaAllocator.init(testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + + const Field = packed struct { + a: bool = false, + b: bool = true, + }; + var data: struct { + v: Field, + } = undefined; + + try parseIntoField(@TypeOf(data), alloc, &data, "v", "true"); + try testing.expect(data.v.a); + try testing.expect(data.v.b); + + try parseIntoField(@TypeOf(data), alloc, &data, "v", "false"); + try testing.expect(!data.v.a); + try testing.expect(!data.v.b); + + try testing.expectError( + error.InvalidValue, + parseIntoField(@TypeOf(data), alloc, &data, "v", "true,a"), + ); +} + test "parseIntoField: packed struct whitespace" { const testing = std.testing; var arena = ArenaAllocator.init(testing.allocator);