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_