forked from mirror/vulkan-zig
FlagTraits
This commit is contained in:
@@ -1,74 +1,66 @@
|
|||||||
pub fn Flags(comptime E: type) type {
|
const std = @import("std");
|
||||||
comptime {
|
const testing = std.testing;
|
||||||
var bits: u32 = 0;
|
|
||||||
inline for (@typeInfo(E).Enum.fields) |field| {
|
|
||||||
const val: u32 = field.value;
|
|
||||||
std.debug.assert(@popCount(u32, val) == 1);
|
|
||||||
std.debug.assert(bits & val == 0);
|
|
||||||
bits |= val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fn FlagTraits(comptime Self: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Self = @This();
|
pub fn init(flags: var) Self {
|
||||||
bits: u32,
|
var self: u32 = 0;
|
||||||
|
|
||||||
pub const none = Self.init(.{});
|
inline for (std.meta.fields(@TypeOf(flags))) |field| {
|
||||||
pub const all = comptime blk: {
|
self |= @enumToInt(@as(Self, @field(flags, field.name)));
|
||||||
var flags = Self.none;
|
}
|
||||||
inline for (@typeInfo(E).Enum.fields) |field| {
|
|
||||||
flags.bits |= field.value;
|
return @intToEnum(Self, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn merge(lhs: Self, rhs: Self) Self {
|
||||||
|
return @intToEnum(Self, @enumToInt(lhs) | @enumToInt(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn intersect(lhs: Self, rhs: Self) Self {
|
||||||
|
return @intToEnum(Self, @enumToInt(lhs) & @enumToInt(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subtract(lhs: Self, rhs: Self) Self {
|
||||||
|
return @intToEnum(Self, @enumToInt(lhs) & @enumToInt(rhs.complement()));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn complement(self: Self) Self {
|
||||||
|
const all = comptime blk: {
|
||||||
|
var flags: u32 = 0;
|
||||||
|
for (std.meta.fields(Self)) |field| {
|
||||||
|
flags |= field.value;
|
||||||
}
|
}
|
||||||
break :blk flags;
|
break :blk flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(flags: var) Self {
|
return @intToEnum(Self, ~@enumToInt(self) & all);
|
||||||
return .{.bits = Self.toBits(flags)};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn merge(lhs: Self, rhs: Self) Self {
|
|
||||||
return .{.bits = lhs.bits | rhs.bits};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn intersect(lhs: Self, rhs: Self) Self {
|
|
||||||
return .{.bits = lhs.bits & rhs.bits};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn subtract(lhs: Self, rhs: Self) Self {
|
|
||||||
return .{.bits = lhs.bits & rhs.complement().bits};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn complement(self: Self) Self {
|
|
||||||
return .{.bits = ~self.bits & Self.all.bits};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(lhs: Self, rhs: Self) bool {
|
pub fn contains(lhs: Self, rhs: Self) bool {
|
||||||
return lhs.bits & rhs.bits == rhs.bits;
|
return @enumToInt(lhs) & @enumToInt(rhs) == @enumToInt(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equals(lhs: Self, rhs: Self) bool {
|
pub fn format(
|
||||||
return lhs.bits == rhs.bits;
|
self: Self,
|
||||||
|
fmt: []const u8,
|
||||||
|
options: std.fmt.FormatOptions,
|
||||||
|
out_stream: var
|
||||||
|
) @TypeOf(out_stream).Error!void {
|
||||||
|
const bits = @enumToInt(self);
|
||||||
|
var first = true;
|
||||||
|
inline for (std.meta.fields(Self)) |field| {
|
||||||
|
if (@popCount(u32, field.value) != 1) continue;
|
||||||
|
|
||||||
|
if (bits & field.value == field.value) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
try std.fmt.formatBuf(" | ", options, out_stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toBits(flags: var) u32 {
|
try std.fmt.formatBuf(field.name, options, out_stream);
|
||||||
const ty = @TypeOf(flags);
|
|
||||||
|
|
||||||
if (ty == Self) {
|
|
||||||
return flags.bits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (@typeInfo(ty)) {
|
|
||||||
.EnumLiteral => return @enumToInt(@as(E, flags)),
|
|
||||||
.Struct => |struct_info| {
|
|
||||||
var value: u32 = 0;
|
|
||||||
inline for (struct_info.fields) |field| {
|
|
||||||
value |= @enumToInt(@as(E, @field(flags, field.name)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
else => @compileError("Value of type '" ++ @typeName(ty)
|
|
||||||
++ "' cannot be converted into '" ++ @typeName(Self) ++ "'")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user