#pragma once namespace rtc { namespace detail { template struct [[gnu::packed]] FlagsImpl { static_assert(sizeof(FlagsT) == sizeof(uint8_t), "Must use uint8_t enum class flags"); uint8_t data = 0; using Flags = FlagsT; FlagsImpl() : data(0) {} FlagsImpl(const Flags &flag) : data(static_cast(flag)) {} FlagsImpl(const FlagsImpl &other) : data(other.data) {} FlagsImpl(const FlagsImpl &&) = delete; FlagsImpl &operator=(const FlagsImpl &rhs) { data = rhs.data; return *this; } FlagsImpl &operator=(const FlagsImpl &&) = delete; FlagsImpl &operator=(const FlagsT &rhs) { data = static_cast(rhs); return *this; } FlagsImpl &operator|=(const FlagsT &flag) { data |= static_cast(flag); return *this; } FlagsImpl &operator|=(const uint8_t &flag) { data |= flag; return *this; } FlagsImpl &operator&=(const FlagsT &flag) { data &= static_cast(flag); return *this; } FlagsImpl &operator&=(const uint8_t &flag) { data &= flag; return *this; } FlagsImpl &operator~() { data = ~data; return *this; } bool operator==(const FlagsT &flag) const { return data & static_cast(flag); } }; template FlagsT operator|(const FlagsT &lhs, const FlagsT &rhs) { const auto lhsInt = static_cast(lhs); const auto rhsInt = static_cast(rhs); return static_cast(lhsInt | rhsInt); } template FlagsT operator&(const FlagsT &lhs, const FlagsT &rhs) { const auto lhsInt = static_cast(lhs); const auto rhsInt = static_cast(rhs); return static_cast(lhsInt & rhsInt); } } // namespace detail } // namespace rtc