// Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef FLUTTER_IMPELLER_BASE_MASK_H_ #define FLUTTER_IMPELLER_BASE_MASK_H_ #include namespace impeller { template struct MaskTraits { static constexpr bool kIsMask = false; }; //------------------------------------------------------------------------------ /// @brief Declare this in the "impeller" namespace to make the enum /// maskable. /// #define IMPELLER_ENUM_IS_MASK(enum_name) \ template <> \ struct MaskTraits { \ static constexpr bool kIsMask = true; \ }; //------------------------------------------------------------------------------ /// @brief A mask of typed enums. /// /// @tparam EnumType_ The type of the enum. Must be an enum class. /// template struct Mask { using EnumType = EnumType_; using MaskType = typename std::underlying_type::type; constexpr Mask() = default; constexpr Mask(const Mask& other) = default; constexpr Mask(Mask&& other) = default; constexpr Mask(EnumType type) // NOLINT(google-explicit-constructor) : mask_(static_cast(type)) {} explicit constexpr Mask(MaskType mask) : mask_(static_cast(mask)) {} // All casts must be explicit. explicit constexpr operator MaskType() const { return mask_; } explicit constexpr operator bool() const { return !!mask_; } // The following relational operators can be replaced with a defaulted // spaceship operator post C++20. constexpr bool operator<(const Mask& other) const { return mask_ < other.mask_; } constexpr bool operator>(const Mask& other) const { return mask_ > other.mask_; } constexpr bool operator>=(const Mask& other) const { return mask_ >= other.mask_; } constexpr bool operator<=(const Mask& other) const { return mask_ <= other.mask_; } constexpr bool operator==(const Mask& other) const { return mask_ == other.mask_; } constexpr bool operator!=(const Mask& other) const { return mask_ != other.mask_; } // Logical operators. constexpr bool operator!() const { return !mask_; } // Bitwise operators. constexpr Mask operator&(const Mask& other) const { return Mask{mask_ & other.mask_}; } constexpr Mask operator|(const Mask& other) const { return Mask{mask_ | other.mask_}; } constexpr Mask operator^(const Mask& other) const { return Mask{mask_ ^ other.mask_}; } constexpr Mask operator~() const { return Mask{~mask_}; } // Assignment operators. constexpr Mask& operator=(const Mask&) = default; constexpr Mask& operator=(Mask&&) = default; constexpr Mask& operator|=(const Mask& other) { mask_ |= other.mask_; return *this; } constexpr Mask& operator&=(const Mask& other) { mask_ &= other.mask_; return *this; } constexpr Mask& operator^=(const Mask& other) { mask_ ^= other.mask_; return *this; } private: MaskType mask_ = {}; }; // Construction from Enum Types template < typename EnumType, typename std::enable_if::kIsMask, bool>::type = true> inline constexpr Mask operator|(const EnumType& lhs, const EnumType& rhs) { return Mask{lhs} | rhs; } template < typename EnumType, typename std::enable_if::kIsMask, bool>::type = true> inline constexpr Mask operator&(const EnumType& lhs, const EnumType& rhs) { return Mask{lhs} & rhs; } template < typename EnumType, typename std::enable_if::kIsMask, bool>::type = true> inline constexpr Mask operator^(const EnumType& lhs, const EnumType& rhs) { return Mask{lhs} ^ rhs; } template < typename EnumType, typename std::enable_if::kIsMask, bool>::type = true> inline constexpr Mask operator~(const EnumType& other) { return ~Mask{other}; } template < typename EnumType, typename std::enable_if::kIsMask, bool>::type = true> inline constexpr Mask operator|(const EnumType& lhs, const Mask& rhs) { return Mask{lhs} | rhs; } template < typename EnumType, typename std::enable_if::kIsMask, bool>::type = true> inline constexpr Mask operator&(const EnumType& lhs, const Mask& rhs) { return Mask{lhs} & rhs; } template < typename EnumType, typename std::enable_if::kIsMask, bool>::type = true> inline constexpr Mask operator^(const EnumType& lhs, const Mask& rhs) { return Mask{lhs} ^ rhs; } // Relational operators with EnumType promotion. These can be replaced by a // defaulted spaceship operator post C++20. template ::kIsMask, bool> = true> inline constexpr bool operator<(const EnumType& lhs, const Mask& rhs) { return Mask{lhs} < rhs; } template ::kIsMask, bool> = true> inline constexpr bool operator>(const EnumType& lhs, const Mask& rhs) { return Mask{lhs} > rhs; } template ::kIsMask, bool> = true> inline constexpr bool operator<=(const EnumType& lhs, const Mask& rhs) { return Mask{lhs} <= rhs; } template ::kIsMask, bool> = true> inline constexpr bool operator>=(const EnumType& lhs, const Mask& rhs) { return Mask{lhs} >= rhs; } template ::kIsMask, bool> = true> inline constexpr bool operator==(const EnumType& lhs, const Mask& rhs) { return Mask{lhs} == rhs; } template ::kIsMask, bool> = true> inline constexpr bool operator!=(const EnumType& lhs, const Mask& rhs) { return Mask{lhs} != rhs; } } // namespace impeller #endif // FLUTTER_IMPELLER_BASE_MASK_H_