webgpu/dawn/include/dawn/EnumClassBitmasks.h
1// Copyright 2017 The Dawn Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef INCLUDE_DAWN_ENUMCLASSBITMASKS_H_
16#define INCLUDE_DAWN_ENUMCLASSBITMASKS_H_
17
18#include <type_traits>
19
20// The operators in dawn:: namespace need be introduced into other namespaces with
21// using-declarations for C++ Argument Dependent Lookup to work.
22#define DAWN_IMPORT_BITMASK_OPERATORS \
23 using dawn::operator|; \
24 using dawn::operator&; \
25 using dawn::operator^; \
26 using dawn::operator~; \
27 using dawn::operator&=; \
28 using dawn::operator|=; \
29 using dawn::operator^=; \
30 using dawn::HasZeroOrOneBits;
31
32namespace dawn {
33
34template <typename T>
35struct IsDawnBitmask {
36 static constexpr bool enable = false;
37};
38
39template <typename T, typename Enable = void>
40struct LowerBitmask {
41 static constexpr bool enable = false;
42};
43
44template <typename T>
45struct LowerBitmask<T, typename std::enable_if<IsDawnBitmask<T>::enable>::type> {
46 static constexpr bool enable = true;
47 using type = T;
48 constexpr static T Lower(T t) { return t; }
49};
50
51template <typename T>
52struct BoolConvertible {
53 using Integral = typename std::underlying_type<T>::type;
54
55 // NOLINTNEXTLINE(runtime/explicit)
56 explicit constexpr BoolConvertible(Integral value) : value(value) {}
57 constexpr operator bool() const { return value != 0; }
58 constexpr operator T() const { return static_cast<T>(value); }
59
60 Integral value;
61};
62
63template <typename T>
64struct LowerBitmask<BoolConvertible<T>> {
65 static constexpr bool enable = true;
66 using type = T;
67 static constexpr type Lower(BoolConvertible<T> t) { return t; }
68};
69
70template <
71 typename T1,
72 typename T2,
73 typename = typename std::enable_if<LowerBitmask<T1>::enable && LowerBitmask<T2>::enable>::type>
74constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator|(T1 left, T2 right) {
75 using T = typename LowerBitmask<T1>::type;
76 using Integral = typename std::underlying_type<T>::type;
77 return BoolConvertible<T>(static_cast<Integral>(LowerBitmask<T1>::Lower(left)) |
78 static_cast<Integral>(LowerBitmask<T2>::Lower(right)));
79}
80
81template <
82 typename T1,
83 typename T2,
84 typename = typename std::enable_if<LowerBitmask<T1>::enable && LowerBitmask<T2>::enable>::type>
85constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator&(T1 left, T2 right) {
86 using T = typename LowerBitmask<T1>::type;
87 using Integral = typename std::underlying_type<T>::type;
88 return BoolConvertible<T>(static_cast<Integral>(LowerBitmask<T1>::Lower(left)) &
89 static_cast<Integral>(LowerBitmask<T2>::Lower(right)));
90}
91
92template <
93 typename T1,
94 typename T2,
95 typename = typename std::enable_if<LowerBitmask<T1>::enable && LowerBitmask<T2>::enable>::type>
96constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator^(T1 left, T2 right) {
97 using T = typename LowerBitmask<T1>::type;
98 using Integral = typename std::underlying_type<T>::type;
99 return BoolConvertible<T>(static_cast<Integral>(LowerBitmask<T1>::Lower(left)) ^
100 static_cast<Integral>(LowerBitmask<T2>::Lower(right)));
101}
102
103template <typename T1>
104constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator~(T1 t) {
105 using T = typename LowerBitmask<T1>::type;
106 using Integral = typename std::underlying_type<T>::type;
107 return BoolConvertible<T>(~static_cast<Integral>(LowerBitmask<T1>::Lower(t)));
108}
109
110template <
111 typename T,
112 typename T2,
113 typename = typename std::enable_if<IsDawnBitmask<T>::enable && LowerBitmask<T2>::enable>::type>
114constexpr T& operator&=(T& l, T2 right) {
115 T r = LowerBitmask<T2>::Lower(right);
116 l = l & r;
117 return l;
118}
119
120template <
121 typename T,
122 typename T2,
123 typename = typename std::enable_if<IsDawnBitmask<T>::enable && LowerBitmask<T2>::enable>::type>
124constexpr T& operator|=(T& l, T2 right) {
125 T r = LowerBitmask<T2>::Lower(right);
126 l = l | r;
127 return l;
128}
129
130template <
131 typename T,
132 typename T2,
133 typename = typename std::enable_if<IsDawnBitmask<T>::enable && LowerBitmask<T2>::enable>::type>
134constexpr T& operator^=(T& l, T2 right) {
135 T r = LowerBitmask<T2>::Lower(right);
136 l = l ^ r;
137 return l;
138}
139
140template <typename T>
141constexpr bool HasZeroOrOneBits(T value) {
142 using Integral = typename std::underlying_type<T>::type;
143 return (static_cast<Integral>(value) & (static_cast<Integral>(value) - 1)) == 0;
144}
145
146} // namespace dawn
147
148#endif // INCLUDE_DAWN_ENUMCLASSBITMASKS_H_