forked from oven-sh/bun
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbitflags.zig
110 lines (88 loc) · 3.23 KB
/
bitflags.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
const std = @import("std");
pub fn Bitflags(comptime T: type) type {
const tyinfo = @typeInfo(T);
const IntType = tyinfo.Struct.backing_integer.?;
const IntTypeInfo = @typeInfo(IntType);
const IntRepresentingNumOfBits = std.math.IntFittingRange(0, IntTypeInfo.Int.bits);
return struct {
pub inline fn empty() T {
return @bitCast(@as(IntType, 0));
}
pub inline fn intersects(lhs: T, rhs: T) bool {
return asBits(lhs) & asBits(rhs) != 0;
}
pub inline fn fromName(comptime name: []const u8) T {
var this: T = .{};
@field(this, name) = true;
return this;
}
pub inline fn fromNames(comptime names: []const []const u8) T {
var this: T = .{};
inline for (names) |name| {
@field(this, name) = true;
}
return this;
}
pub fn bitwiseOr(lhs: T, rhs: T) T {
return @bitCast(@as(IntType, @bitCast(lhs)) | @as(IntType, @bitCast(rhs)));
}
pub fn bitwiseAnd(lhs: T, rhs: T) T {
return @bitCast(@as(IntType, asBits(lhs) & asBits(rhs)));
}
pub inline fn insert(this: *T, other: T) void {
this.* = bitwiseOr(this.*, other);
}
pub inline fn remove(this: *T, other: T) void {
this.* = @bitCast(asBits(this.*) & ~asBits(other));
}
pub inline fn maskOut(this: T, other: T) T {
return @bitCast(asBits(this) & ~asBits(other));
}
pub fn contains(lhs: T, rhs: T) bool {
return @as(IntType, @bitCast(lhs)) & @as(IntType, @bitCast(rhs)) != 0;
}
pub inline fn leadingZeroes(this: T) IntRepresentingNumOfBits {
return @clz(asBits(this));
}
pub inline fn all() T {
var ret: T = @bitCast(@as(IntType, 0));
@setEvalBranchQuota(5000);
inline for (std.meta.fields(T)) |field| {
if (comptime !std.mem.eql(u8, field.name, "__unused")) {
@field(ret, field.name) = true;
}
}
return ret;
}
pub inline fn not(this: T) T {
return fromBitsTruncate(~asBits(this));
}
pub inline fn difference(lhs: T, rhs: T) T {
// 1100 1100 1100
// 1010 0101 0100
return @bitCast(asBits(lhs) & asBits(not(rhs)));
}
/// Convert from a bits value, unsetting any unknown bits.
pub inline fn fromBitsTruncate(bits: IntType) T {
return bitwiseAnd(@bitCast(bits), all());
}
pub inline fn asBits(this: T) IntType {
return @as(IntType, @bitCast(this));
}
pub fn isEmpty(this: T) bool {
return asBits(this) == 0;
}
pub fn eq(lhs: T, rhs: T) bool {
return asBits(lhs) == asBits(rhs);
}
pub fn eql(lhs: T, rhs: T) bool {
return eq(lhs, rhs);
}
pub fn neq(lhs: T, rhs: T) bool {
return asBits(lhs) != asBits(rhs);
}
pub fn hash(this: *const T, hasher: *std.hash.Wyhash) void {
hasher.update(std.mem.asBytes(this));
}
};
}