Printing flags

Suppose I have a packed structure defined like this. The actual number of flags is 21.

    pub const Flags = packed struct(u3) {
        use1: bool = false,
        use2: bool = false,
        use3: bool = false,
    };

I would like to print the flags like this CF_USE1 | CF_USE2 | CF_USE3.

Is there a better way to do it than this?

fn printFlags(pp: *PrettyPrinter, flags: Mod.Instruction.Flags) Error!void {
    var add_pipe = false;
    if (flags.use1) {
        if (add_pipe)
            try pp.text(" | ");
        try pp.text("CF_USE1");
        add_pipe = true;
    }
    if (flags.use2) {
        if (add_pipe)
            try pp.text(" | ");
        try pp.text("CF_USE2");
        add_pipe = true;
    }
    if (flags.use3) {
        if (add_pipe)
            try pp.text(" | ");
        try pp.text("CF_USE3");
        add_pipe = true;
    }
}
const ti = @typeInfo(Flags);
inline for (ti.@"struct".fields) |field| {
    if (@field(flags, field.name)) {
        // Your printing logic here
    }
}

Something like this should work. Using comptime type information to generate an inline for loop over all fields

1 Like

A bit of comptime magic can generate names from each field.

fn printFlags(pp: *PrettyPrinter, flags: Mod.Instruction.Flags) Error!void {
    var add_pipe = false;
    inline for (@typeInfo(Flags).@"struct".fields) |field| {
        if (@field(flags, field.name) == true) {
            if (add_pipe) try pp.text(" | ");
            try pp.text(flagName(field.name));
            add_pipe = true;
        }
    }
}

fn flagName(comptime field_name: []const u8) []const u8 {
    return comptime blk: {
        var upper_name: [field_name.len]u8 = undefined;
        _ = std.ascii.upperString(&upper_name, field_name);

        break :blk "CF_" ++ upper_name;
    };
}
2 Likes