50 lines
1.3 KiB
Zig
50 lines
1.3 KiB
Zig
const std = @import("std");
|
|
|
|
pub fn EnumFlags(comptime E: type) type {
|
|
return packed struct {
|
|
const Self = @This();
|
|
|
|
const BackingInt = @typeInfo(E).@"enum".tag_type;
|
|
|
|
mask: BackingInt,
|
|
|
|
pub const empty: Self = .{ .data = 0 };
|
|
|
|
pub fn from(mask: BackingInt) Self {
|
|
return .{
|
|
.mask = mask,
|
|
};
|
|
}
|
|
|
|
pub fn contains(self: Self, flag: E) bool {
|
|
return (self.mask & @intFromEnum(flag)) != 0;
|
|
}
|
|
|
|
pub fn insert(self: *Self, flag: E) void {
|
|
self.mask |= @intFromEnum(flag);
|
|
}
|
|
|
|
pub fn remove(self: *Self, flag: E) void {
|
|
self.mask &= ~@intFromEnum(flag);
|
|
}
|
|
|
|
pub fn toggle(self: *Self, flag: E) void {
|
|
self.mask ^= @intFromEnum(flag);
|
|
}
|
|
|
|
pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
|
var index: usize = 0;
|
|
inline for (std.meta.fields(E)) |field| {
|
|
const key = @field(E, field.name);
|
|
if (self.contains(key)) {
|
|
if (index > 0) {
|
|
_ = try w.write(" | ");
|
|
}
|
|
try w.print("{s}", .{ field.name });
|
|
index += 1;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|