blob: 97f30d7a7418e1837220210189d3ffae5131924b [file] [log] [blame]
// 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 <type_traits>
namespace impeller {
template <typename EnumType_>
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<enum_name> { \
static constexpr bool kIsMask = true; \
};
//------------------------------------------------------------------------------
/// @brief A mask of typed enums.
///
/// @tparam EnumType_ The type of the enum. Must be an enum class.
///
template <typename EnumType_>
struct Mask {
using EnumType = EnumType_;
using MaskType = typename std::underlying_type<EnumType>::type;
constexpr Mask() = default;
constexpr Mask(const Mask<EnumType>& other) = default;
constexpr Mask(Mask<EnumType>&& other) = default;
constexpr Mask(EnumType type) // NOLINT(google-explicit-constructor)
: mask_(static_cast<MaskType>(type)) {}
explicit constexpr Mask(MaskType mask) : mask_(static_cast<MaskType>(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<EnumType>& other) const {
return mask_ < other.mask_;
}
constexpr bool operator>(const Mask<EnumType>& other) const {
return mask_ > other.mask_;
}
constexpr bool operator>=(const Mask<EnumType>& other) const {
return mask_ >= other.mask_;
}
constexpr bool operator<=(const Mask<EnumType>& other) const {
return mask_ <= other.mask_;
}
constexpr bool operator==(const Mask<EnumType>& other) const {
return mask_ == other.mask_;
}
constexpr bool operator!=(const Mask<EnumType>& other) const {
return mask_ != other.mask_;
}
// Logical operators.
constexpr bool operator!() const { return !mask_; }
// Bitwise operators.
constexpr Mask<EnumType> operator&(const Mask<EnumType>& other) const {
return Mask<EnumType>{mask_ & other.mask_};
}
constexpr Mask<EnumType> operator|(const Mask<EnumType>& other) const {
return Mask<EnumType>{mask_ | other.mask_};
}
constexpr Mask<EnumType> operator^(const Mask<EnumType>& other) const {
return Mask<EnumType>{mask_ ^ other.mask_};
}
constexpr Mask<EnumType> operator~() const { return Mask<EnumType>{~mask_}; }
// Assignment operators.
constexpr Mask<EnumType>& operator=(const Mask<EnumType>&) = default;
constexpr Mask<EnumType>& operator=(Mask<EnumType>&&) = default;
constexpr Mask<EnumType>& operator|=(const Mask<EnumType>& other) {
mask_ |= other.mask_;
return *this;
}
constexpr Mask<EnumType>& operator&=(const Mask<EnumType>& other) {
mask_ &= other.mask_;
return *this;
}
constexpr Mask<EnumType>& operator^=(const Mask<EnumType>& other) {
mask_ ^= other.mask_;
return *this;
}
private:
MaskType mask_ = {};
};
// Construction from Enum Types
template <
typename EnumType,
typename std::enable_if<MaskTraits<EnumType>::kIsMask, bool>::type = true>
inline constexpr Mask<EnumType> operator|(const EnumType& lhs,
const EnumType& rhs) {
return Mask<EnumType>{lhs} | rhs;
}
template <
typename EnumType,
typename std::enable_if<MaskTraits<EnumType>::kIsMask, bool>::type = true>
inline constexpr Mask<EnumType> operator&(const EnumType& lhs,
const EnumType& rhs) {
return Mask<EnumType>{lhs} & rhs;
}
template <
typename EnumType,
typename std::enable_if<MaskTraits<EnumType>::kIsMask, bool>::type = true>
inline constexpr Mask<EnumType> operator^(const EnumType& lhs,
const EnumType& rhs) {
return Mask<EnumType>{lhs} ^ rhs;
}
template <
typename EnumType,
typename std::enable_if<MaskTraits<EnumType>::kIsMask, bool>::type = true>
inline constexpr Mask<EnumType> operator~(const EnumType& other) {
return ~Mask<EnumType>{other};
}
template <
typename EnumType,
typename std::enable_if<MaskTraits<EnumType>::kIsMask, bool>::type = true>
inline constexpr Mask<EnumType> operator|(const EnumType& lhs,
const Mask<EnumType>& rhs) {
return Mask<EnumType>{lhs} | rhs;
}
template <
typename EnumType,
typename std::enable_if<MaskTraits<EnumType>::kIsMask, bool>::type = true>
inline constexpr Mask<EnumType> operator&(const EnumType& lhs,
const Mask<EnumType>& rhs) {
return Mask<EnumType>{lhs} & rhs;
}
template <
typename EnumType,
typename std::enable_if<MaskTraits<EnumType>::kIsMask, bool>::type = true>
inline constexpr Mask<EnumType> operator^(const EnumType& lhs,
const Mask<EnumType>& rhs) {
return Mask<EnumType>{lhs} ^ rhs;
}
// Relational operators with EnumType promotion. These can be replaced by a
// defaulted spaceship operator post C++20.
template <typename EnumType,
typename std::enable_if_t<MaskTraits<EnumType>::kIsMask, bool> = true>
inline constexpr bool operator<(const EnumType& lhs,
const Mask<EnumType>& rhs) {
return Mask<EnumType>{lhs} < rhs;
}
template <typename EnumType,
typename std::enable_if_t<MaskTraits<EnumType>::kIsMask, bool> = true>
inline constexpr bool operator>(const EnumType& lhs,
const Mask<EnumType>& rhs) {
return Mask<EnumType>{lhs} > rhs;
}
template <typename EnumType,
typename std::enable_if_t<MaskTraits<EnumType>::kIsMask, bool> = true>
inline constexpr bool operator<=(const EnumType& lhs,
const Mask<EnumType>& rhs) {
return Mask<EnumType>{lhs} <= rhs;
}
template <typename EnumType,
typename std::enable_if_t<MaskTraits<EnumType>::kIsMask, bool> = true>
inline constexpr bool operator>=(const EnumType& lhs,
const Mask<EnumType>& rhs) {
return Mask<EnumType>{lhs} >= rhs;
}
template <typename EnumType,
typename std::enable_if_t<MaskTraits<EnumType>::kIsMask, bool> = true>
inline constexpr bool operator==(const EnumType& lhs,
const Mask<EnumType>& rhs) {
return Mask<EnumType>{lhs} == rhs;
}
template <typename EnumType,
typename std::enable_if_t<MaskTraits<EnumType>::kIsMask, bool> = true>
inline constexpr bool operator!=(const EnumType& lhs,
const Mask<EnumType>& rhs) {
return Mask<EnumType>{lhs} != rhs;
}
} // namespace impeller
#endif // FLUTTER_IMPELLER_BASE_MASK_H_