aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/misc/enum-inl.h
diff options
context:
space:
mode:
authorbabenko <babenko@yandex-team.com>2023-03-14 09:33:31 +0300
committerbabenko <babenko@yandex-team.com>2023-03-14 09:33:31 +0300
commite10767756146ca0d8e890326e20671aed5182e2b (patch)
tree0d15dded16242ddb4d7b64f5e1d21d425742234e /library/cpp/yt/misc/enum-inl.h
parent9aa65dc165f24925a281f89c975cc5117823934f (diff)
downloadydb-e10767756146ca0d8e890326e20671aed5182e2b.tar.gz
YT-18571: Refactor YT enums to make them Arcadia-friendly
Diffstat (limited to 'library/cpp/yt/misc/enum-inl.h')
-rw-r--r--library/cpp/yt/misc/enum-inl.h261
1 files changed, 138 insertions, 123 deletions
diff --git a/library/cpp/yt/misc/enum-inl.h b/library/cpp/yt/misc/enum-inl.h
index 18a78621a9..ba33290e79 100644
--- a/library/cpp/yt/misc/enum-inl.h
+++ b/library/cpp/yt/misc/enum-inl.h
@@ -15,8 +15,8 @@ namespace NYT {
////////////////////////////////////////////////////////////////////////////////
-#define ENUM__CLASS(name, underlyingType, seq) \
- enum class name : underlyingType \
+#define ENUM__CLASS(enumType, underlyingType, seq) \
+ enum class enumType : underlyingType \
{ \
PP_FOR_EACH(ENUM__DOMAIN_ITEM, seq) \
};
@@ -39,10 +39,27 @@ namespace NYT {
namespace NDetail {
template <typename TValues>
-static constexpr bool AreValuesDistinct(const TValues& values)
+constexpr bool CheckValuesMonotonic(const TValues& values)
{
- for (int i = 0; i < static_cast<int>(values.size()); ++i) {
- for (int j = i + 1; j < static_cast<int>(values.size()); ++j) {
+ if (std::size(values) <= 1) {
+ return true;
+ }
+ for (size_t i = 0; i < std::size(values) - 1; ++i) {
+ if (values[i] > values[i + 1]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename TValues>
+constexpr bool CheckValuesUnique(const TValues& values)
+{
+ if (CheckValuesMonotonic(values)) {
+ return true;
+ }
+ for (size_t i = 0; i < std::size(values); ++i) {
+ for (size_t j = i + 1; j < std::size(values); ++j) {
if (values[i] == values[j]) {
return false;
}
@@ -55,68 +72,61 @@ static constexpr bool AreValuesDistinct(const TValues& values)
////////////////////////////////////////////////////////////////////////////////
-#define ENUM__BEGIN_TRAITS(name, underlyingType, isBit, isStringSerializable, seq) \
- struct TEnumTraitsImpl_##name \
+#define ENUM__BEGIN_TRAITS(enumType, underlyingType, isBit, isStringSerializable, seq) \
+ struct TEnumTraitsImpl_##enumType \
{ \
- using TType = name; \
- using TUnderlying = underlyingType; \
+ using T = enumType; \
+ \
[[maybe_unused]] static constexpr bool IsBitEnum = isBit; \
[[maybe_unused]] static constexpr bool IsStringSerializableEnum = isStringSerializable; \
- [[maybe_unused]] static constexpr int DomainSize = PP_COUNT(seq); \
+ static constexpr int DomainSize = PP_COUNT(seq); \
+ \
+ static constexpr int GetDomainSize() \
+ { \
+ return DomainSize; \
+ } \
\
static constexpr std::array<TStringBuf, DomainSize> Names{{ \
PP_FOR_EACH(ENUM__GET_DOMAIN_NAMES_ITEM, seq) \
}}; \
- static constexpr std::array<TType, DomainSize> Values{{ \
+ static constexpr std::array<T, DomainSize> Values{{ \
PP_FOR_EACH(ENUM__GET_DOMAIN_VALUES_ITEM, seq) \
}}; \
\
static TStringBuf GetTypeName() \
{ \
- static constexpr TStringBuf typeName = PP_STRINGIZE(name); \
- return typeName; \
+ static constexpr TStringBuf Result = PP_STRINGIZE(enumType); \
+ return Result; \
} \
\
- static const TStringBuf* FindLiteralByValue(TType value) \
+ static const std::optional<TStringBuf> FindLiteralByValue(T value) \
{ \
- for (int i = 0; i < DomainSize; ++i) { \
+ for (int i = 0; i < GetDomainSize(); ++i) { \
if (Values[i] == value) { \
- return &Names[i]; \
+ return Names[i]; \
} \
} \
- return nullptr; \
+ return std::nullopt; \
} \
\
- static bool FindValueByLiteral(TStringBuf literal, TType* result) \
+ static std::optional<T> FindValueByLiteral(TStringBuf literal) \
{ \
- for (int i = 0; i < DomainSize; ++i) { \
+ for (int i = 0; i < GetDomainSize(); ++i) { \
if (Names[i] == literal) { \
- *result = Values[i]; \
- return true; \
+ return Values[i]; \
} \
} \
- return false; \
+ return std::nullopt; \
} \
\
- static const std::array<TStringBuf, DomainSize>& GetDomainNames() \
+ static constexpr const std::array<TStringBuf, DomainSize>& GetDomainNames() \
{ \
return Names; \
} \
\
- static const std::array<TType, DomainSize>& GetDomainValues() \
+ static constexpr const std::array<T, DomainSize>& GetDomainValues() \
{ \
return Values; \
- } \
- \
- static TType FromString(TStringBuf str) \
- { \
- TType value; \
- if (!FindValueByLiteral(str, &value)) { \
- throw ::NYT::TSimpleException(Sprintf("Error parsing %s value %s", \
- PP_STRINGIZE(name), \
- TString(str).Quote().c_str()).c_str()); \
- } \
- return value; \
}
#define ENUM__GET_DOMAIN_VALUES_ITEM(item) \
@@ -130,7 +140,7 @@ static constexpr bool AreValuesDistinct(const TValues& values)
ENUM__GET_DOMAIN_VALUES_ITEM_ATOMIC(PP_ELEMENT(seq, 0))
#define ENUM__GET_DOMAIN_VALUES_ITEM_ATOMIC(item) \
- TType::item,
+ T::item,
#define ENUM__GET_DOMAIN_NAMES_ITEM(item) \
PP_IF( \
@@ -161,119 +171,120 @@ static constexpr bool AreValuesDistinct(const TValues& values)
#define ENUM__GET_DOMAIN_NAMES_ITEM_ATOMIC(item) \
TStringBuf(PP_STRINGIZE(item)),
-#define ENUM__DECOMPOSE \
- static std::vector<TType> Decompose(TType value) \
- { \
- std::vector<TType> result; \
- for (int i = 0; i < DomainSize; ++i) { \
- if (static_cast<TUnderlying>(value) & static_cast<TUnderlying>(Values[i])) { \
- result.push_back(Values[i]); \
- } \
- } \
- return result; \
- }
+#define ENUM__VALIDATE_UNIQUE(enumType) \
+ static_assert(::NYT::NDetail::CheckValuesUnique(Values), \
+ "Enumeration " #enumType " contains duplicate values");
-#define ENUM__MINMAX \
- static constexpr TType GetMinValue() \
- { \
- static_assert(!Values.empty()); \
- return *std::min_element(std::begin(Values), std::end(Values)); \
- } \
- \
- static constexpr TType GetMaxValue() \
- { \
- static_assert(!Values.empty()); \
- return *std::max_element(std::begin(Values), std::end(Values)); \
- }
-
-#define ENUM__VALIDATE_UNIQUE(name) \
- static_assert(::NYT::NDetail::AreValuesDistinct(Values), \
- "Enumeration " #name " contains duplicate values");
-
-#define ENUM__END_TRAITS(name) \
+#define ENUM__END_TRAITS(enumType) \
}; \
\
- [[maybe_unused]] inline TEnumTraitsImpl_##name GetEnumTraitsImpl(name) \
+ [[maybe_unused]] inline TEnumTraitsImpl_##enumType GetEnumTraitsImpl(enumType) \
{ \
- return TEnumTraitsImpl_##name(); \
+ return {}; \
} \
\
using ::ToString; \
- [[maybe_unused]] inline TString ToString(name value) \
+ [[maybe_unused]] inline TString ToString(enumType value) \
{ \
- return ::NYT::TEnumTraits<name>::ToString(value); \
+ return ::NYT::TEnumTraits<enumType>::ToString(value); \
}
////////////////////////////////////////////////////////////////////////////////
template <class T>
-std::vector<T> TEnumTraits<T, true>::Decompose(T value)
+constexpr int TEnumTraitsWithKnownDomain<T, true>::GetDomainSize()
{
- return TImpl::Decompose(value);
+ return TEnumTraitsImpl<T>::GetDomainSize();
}
template <class T>
-T TEnumTraits<T, true>::FromString(TStringBuf str)
+constexpr auto TEnumTraitsWithKnownDomain<T, true>::GetDomainNames() -> const std::array<TStringBuf, GetDomainSize()>&
{
- return TImpl::FromString(str);
+ return TEnumTraitsImpl<T>::GetDomainNames();
}
template <class T>
-TString TEnumTraits<T, true>::ToString(TType value)
+constexpr auto TEnumTraitsWithKnownDomain<T, true>::GetDomainValues() -> const std::array<T, GetDomainSize()>&
{
- TString result;
- const auto* literal = FindLiteralByValue(value);
- if (literal) {
- result = *literal;
- } else {
- result = GetTypeName();
- result += "(";
- result += ::ToString(static_cast<TUnderlying>(value));
- result += ")";
- }
- return result;
+ return TEnumTraitsImpl<T>::GetDomainValues();
}
template <class T>
-auto TEnumTraits<T, true>::GetDomainValues() -> const std::array<T, DomainSize>&
+constexpr T TEnumTraitsWithKnownDomain<T, true>::GetMinValue()
+ requires (!TEnumTraitsImpl<T>::IsBitEnum)
{
- return TImpl::GetDomainValues();
+ const auto& values = GetDomainValues();
+ static_assert(!values.empty()); \
+ return *std::min_element(std::begin(values), std::end(values));
}
template <class T>
-auto TEnumTraits<T, true>::GetDomainNames() -> const std::array<TStringBuf, DomainSize>&
+constexpr T TEnumTraitsWithKnownDomain<T, true>::GetMaxValue()
+ requires (!TEnumTraitsImpl<T>::IsBitEnum)
{
- return TImpl::GetDomainNames();
+ const auto& values = GetDomainValues();
+ static_assert(!values.empty()); \
+ return *std::max_element(std::begin(values), std::end(values));
+}
+
+template <class T>
+std::vector<T> TEnumTraitsWithKnownDomain<T, true>::Decompose(T value)
+ requires (TEnumTraitsImpl<T>::IsBitEnum)
+{
+ std::vector<T> result;
+ for (auto domainValue : GetDomainValues()) {
+ if (Any(value & domainValue)) {
+ result.push_back(domainValue);
+ }
+ }
+ return result;
}
+////////////////////////////////////////////////////////////////////////////////
+
template <class T>
-constexpr T TEnumTraits<T, true>::GetMaxValue()
+TStringBuf TEnumTraits<T, true>::GetTypeName()
{
- return TImpl::GetMaxValue();
+ return TEnumTraitsImpl<T>::GetTypeName();
}
template <class T>
-constexpr T TEnumTraits<T, true>::GetMinValue()
+std::optional<T> TEnumTraits<T, true>::FindValueByLiteral(TStringBuf literal)
{
- return TImpl::GetMinValue();
+ return TEnumTraitsImpl<T>::FindValueByLiteral(literal);
}
template <class T>
-bool TEnumTraits<T, true>::FindValueByLiteral(TStringBuf literal, TType* result)
+std::optional<TStringBuf> TEnumTraits<T, true>::FindLiteralByValue(T value)
{
- return TImpl::FindValueByLiteral(literal, result);
+ return TEnumTraitsImpl<T>::FindLiteralByValue(value);
}
template <class T>
-const TStringBuf* TEnumTraits<T, true>::FindLiteralByValue(TType value)
+TString TEnumTraits<T, true>::ToString(T value)
{
- return TImpl::FindLiteralByValue(value);
+ using ::ToString;
+ if (auto optionalLiteral = TEnumTraits<T>::FindLiteralByValue(value)) {
+ return ToString(*optionalLiteral);
+ }
+ TString result;
+ result = TEnumTraits<T>::GetTypeName();
+ result += "(";
+ result += ToString(ToUnderlying(value));
+ result += ")";
+ return result;
}
template <class T>
-TStringBuf TEnumTraits<T, true>::GetTypeName()
+T TEnumTraits<T, true>::FromString(TStringBuf literal)
{
- return TImpl::GetTypeName();
+ auto optionalValue = FindValueByLiteral(literal);
+ if (!optionalValue) {
+ throw ::NYT::TSimpleException(Sprintf("Error parsing %s value %s",
+ GetTypeName().data(),
+ TString(literal).Quote().c_str()).c_str());
+ }
+ return *optionalValue;
}
////////////////////////////////////////////////////////////////////////////////
@@ -298,7 +309,7 @@ template <class E, class T, E Min, E Max>
T& TEnumIndexedVector<E, T, Min, Max>::operator[] (E index)
{
Y_ASSERT(index >= Min && index <= Max);
- return Items_[static_cast<TUnderlying>(index) - static_cast<TUnderlying>(Min)];
+ return Items_[ToUnderlying(index) - ToUnderlying(Min)];
}
template <class E, class T, E Min, E Max>
@@ -342,58 +353,62 @@ bool TEnumIndexedVector<E, T, Min, Max>::IsDomainValue(E value)
#define ENUM__BINARY_BITWISE_OPERATOR(T, assignOp, op) \
[[maybe_unused]] inline constexpr T operator op (T lhs, T rhs) \
{ \
- using TUnderlying = typename TEnumTraits<T>::TUnderlying; \
- return T(static_cast<TUnderlying>(lhs) op static_cast<TUnderlying>(rhs)); \
+ return T(ToUnderlying(lhs) op ToUnderlying(rhs)); \
} \
\
[[maybe_unused]] inline T& operator assignOp (T& lhs, T rhs) \
{ \
- using TUnderlying = typename TEnumTraits<T>::TUnderlying; \
- lhs = T(static_cast<TUnderlying>(lhs) op static_cast<TUnderlying>(rhs)); \
+ lhs = T(ToUnderlying(lhs) op ToUnderlying(rhs)); \
return lhs; \
}
#define ENUM__UNARY_BITWISE_OPERATOR(T, op) \
[[maybe_unused]] inline constexpr T operator op (T value) \
{ \
- using TUnderlying = typename TEnumTraits<T>::TUnderlying; \
- return T(op static_cast<TUnderlying>(value)); \
+ return T(op ToUnderlying(value)); \
}
#define ENUM__BIT_SHIFT_OPERATOR(T, assignOp, op) \
[[maybe_unused]] inline constexpr T operator op (T lhs, size_t rhs) \
{ \
- using TUnderlying = typename TEnumTraits<T>::TUnderlying; \
- return T(static_cast<TUnderlying>(lhs) op rhs); \
+ return T(ToUnderlying(lhs) op rhs); \
} \
\
[[maybe_unused]] inline T& operator assignOp (T& lhs, size_t rhs) \
{ \
- using TUnderlying = typename TEnumTraits<T>::TUnderlying; \
- lhs = T(static_cast<TUnderlying>(lhs) op rhs); \
+ lhs = T(ToUnderlying(lhs) op rhs); \
return lhs; \
}
-#define ENUM__BITWISE_OPS(name) \
- ENUM__BINARY_BITWISE_OPERATOR(name, &=, &) \
- ENUM__BINARY_BITWISE_OPERATOR(name, |=, | ) \
- ENUM__BINARY_BITWISE_OPERATOR(name, ^=, ^) \
- ENUM__UNARY_BITWISE_OPERATOR(name, ~) \
- ENUM__BIT_SHIFT_OPERATOR(name, <<=, << ) \
- ENUM__BIT_SHIFT_OPERATOR(name, >>=, >> )
+#define ENUM__BITWISE_OPS(enumType) \
+ ENUM__BINARY_BITWISE_OPERATOR(enumType, &=, &) \
+ ENUM__BINARY_BITWISE_OPERATOR(enumType, |=, | ) \
+ ENUM__BINARY_BITWISE_OPERATOR(enumType, ^=, ^) \
+ ENUM__UNARY_BITWISE_OPERATOR(enumType, ~) \
+ ENUM__BIT_SHIFT_OPERATOR(enumType, <<=, << ) \
+ ENUM__BIT_SHIFT_OPERATOR(enumType, >>=, >> )
////////////////////////////////////////////////////////////////////////////////
-template <typename E, typename>
-bool Any(E value)
+template <typename E>
+ requires std::is_enum_v<E>
+constexpr std::underlying_type_t<E> ToUnderlying(E value) noexcept
+{
+ return static_cast<std::underlying_type_t<E>>(value);
+}
+
+template <typename E>
+ requires TEnumTraits<E>::IsBitEnum
+constexpr bool Any(E value) noexcept
{
- return static_cast<typename TEnumTraits<E>::TUnderlying>(value) != 0;
+ return ToUnderlying(value) != 0;
}
-template <class E, typename>
-bool None(E value)
+template <typename E>
+ requires TEnumTraits<E>::IsBitEnum
+constexpr bool None(E value) noexcept
{
- return static_cast<typename TEnumTraits<E>::TUnderlying>(value) == 0;
+ return ToUnderlying(value) == 0;
}
////////////////////////////////////////////////////////////////////////////////