summaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/misc/enum.h
diff options
context:
space:
mode:
authorDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/yt/misc/enum.h
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/yt/misc/enum.h')
-rw-r--r--library/cpp/yt/misc/enum.h243
1 files changed, 243 insertions, 0 deletions
diff --git a/library/cpp/yt/misc/enum.h b/library/cpp/yt/misc/enum.h
new file mode 100644
index 00000000000..894364aa43b
--- /dev/null
+++ b/library/cpp/yt/misc/enum.h
@@ -0,0 +1,243 @@
+#pragma once
+
+#include "preprocessor.h"
+
+#include <util/generic/strbuf.h>
+
+#include <stdexcept>
+#include <type_traits>
+#include <array>
+#include <vector>
+
+#include <library/cpp/yt/exception/exception.h>
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+/*
+ * Smart enumerations augment C++ enum classes with a bunch of reflection
+ * capabilities accessible via TEnumTraits class specialization.
+ *
+ * Please refer to the unit test for an actual example of usage
+ * (unittests/enum_ut.cpp).
+ */
+
+// Actual overload must be provided with defines DEFINE_ENUM_XXX (see below).
+template <class T>
+void GetEnumTraitsImpl(T);
+
+template <
+ class T,
+ bool = std::is_enum<T>::value &&
+ !std::is_convertible<T, int>::value &&
+ !std::is_same<void, decltype(GetEnumTraitsImpl(T()))>::value
+>
+struct TEnumTraits
+{
+ static constexpr bool IsEnum = false;
+ static constexpr bool IsBitEnum = false;
+ static constexpr bool IsStringSerializableEnum = false;
+};
+
+template <class T>
+struct TEnumTraits<T, true>
+{
+ using TImpl = decltype(GetEnumTraitsImpl(T()));
+ using TType = T;
+ using TUnderlying = typename TImpl::TUnderlying;
+
+ static constexpr bool IsEnum = true;
+ static constexpr bool IsBitEnum = TImpl::IsBitEnum;
+ static constexpr bool IsStringSerializableEnum = TImpl::IsStringSerializableEnum;
+
+ static constexpr int DomainSize = TImpl::DomainSize;
+
+ static TStringBuf GetTypeName();
+
+ static const TStringBuf* FindLiteralByValue(TType value);
+ static bool FindValueByLiteral(TStringBuf literal, TType* result);
+
+ static const std::array<TStringBuf, DomainSize>& GetDomainNames();
+ static const std::array<TType, DomainSize>& GetDomainValues();
+
+ static TType FromString(TStringBuf str);
+ static TString ToString(TType value);
+
+ // For non-bit enums only.
+ static constexpr TType GetMinValue();
+ static constexpr TType GetMaxValue();
+
+ // For bit enums only.
+ static std::vector<TType> Decompose(TType value);
+
+ // LLVM SmallDenseMap interop.
+ // This should only be used for enums whose underlying type has big enough range
+ // (see getEmptyKey and getTombstoneKey functions).
+ struct TDenseMapInfo
+ {
+ static inline TType getEmptyKey()
+ {
+ return static_cast<TType>(-1);
+ }
+
+ static inline TType getTombstoneKey()
+ {
+ return static_cast<TType>(-2);
+ }
+
+ static unsigned getHashValue(const TType& key)
+ {
+ return static_cast<unsigned>(key) * 37U;
+ }
+
+ static bool isEqual(const TType& lhs, const TType& rhs)
+ {
+ return lhs == rhs;
+ }
+ };
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! Defines a smart enumeration with a specific underlying type.
+/*!
+ * \param name Enumeration name.
+ * \param seq Enumeration domain encoded as a <em>sequence</em>.
+ * \param underlyingType Underlying type.
+ */
+#define DEFINE_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \
+ ENUM__CLASS(name, underlyingType, seq) \
+ ENUM__BEGIN_TRAITS(name, underlyingType, false, false, seq) \
+ ENUM__MINMAX \
+ ENUM__VALIDATE_UNIQUE(name) \
+ ENUM__END_TRAITS(name)
+
+//! Defines a smart enumeration with a specific underlying type.
+//! Duplicate enumeration values are allowed.
+#define DEFINE_AMBIGUOUS_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \
+ ENUM__CLASS(name, underlyingType, seq) \
+ ENUM__BEGIN_TRAITS(name, underlyingType, false, false, seq) \
+ ENUM__MINMAX \
+ ENUM__END_TRAITS(name)
+
+//! Defines a smart enumeration with the default |int| underlying type.
+#define DEFINE_ENUM(name, seq) \
+ DEFINE_ENUM_WITH_UNDERLYING_TYPE(name, int, seq)
+
+//! Defines a smart enumeration with a specific underlying type.
+/*!
+ * \param name Enumeration name.
+ * \param seq Enumeration domain encoded as a <em>sequence</em>.
+ * \param underlyingType Underlying type.
+ */
+#define DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \
+ ENUM__CLASS(name, underlyingType, seq) \
+ ENUM__BEGIN_TRAITS(name, underlyingType, true, false, seq) \
+ ENUM__DECOMPOSE \
+ ENUM__VALIDATE_UNIQUE(name) \
+ ENUM__END_TRAITS(name) \
+ ENUM__BITWISE_OPS(name)
+
+//! Defines a smart enumeration with a specific underlying type.
+//! Duplicate enumeration values are allowed.
+/*!
+ * \param name Enumeration name.
+ * \param seq Enumeration domain encoded as a <em>sequence</em>.
+ * \param underlyingType Underlying type.
+ */
+#define DEFINE_AMBIGUOUS_BIT_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \
+ ENUM__CLASS(name, underlyingType, seq) \
+ ENUM__BEGIN_TRAITS(name, underlyingType, true, false, seq) \
+ ENUM__DECOMPOSE \
+ ENUM__END_TRAITS(name) \
+ ENUM__BITWISE_OPS(name)
+
+//! Defines a smart enumeration with the default |unsigned| underlying type.
+/*!
+ * \param name Enumeration name.
+ * \param seq Enumeration domain encoded as a <em>sequence</em>.
+ */
+#define DEFINE_BIT_ENUM(name, seq) \
+ DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(name, unsigned, seq)
+
+//! Defines a smart enumeration with a specific underlying type and IsStringSerializable attribute.
+/*!
+ * \param name Enumeration name.
+ * \param seq Enumeration domain encoded as a <em>sequence</em>.
+ * \param underlyingType Underlying type.
+ */
+#define DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \
+ ENUM__CLASS(name, underlyingType, seq) \
+ ENUM__BEGIN_TRAITS(name, underlyingType, false, true, seq) \
+ ENUM__MINMAX \
+ ENUM__VALIDATE_UNIQUE(name) \
+ ENUM__END_TRAITS(name) \
+
+//! Defines a smart enumeration with a specific underlying type and IsStringSerializable attribute.
+//! Duplicate enumeration values are allowed.
+#define DEFINE_AMBIGUOUS_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \
+ ENUM__CLASS(name, underlyingType, seq) \
+ ENUM__BEGIN_TRAITS(name, underlyingType, false, true, seq) \
+ ENUM__MINMAX \
+ ENUM__END_TRAITS(name)
+
+//! Defines a smart enumeration with the default |int| underlying type and IsStringSerializable attribute.
+#define DEFINE_STRING_SERIALIZABLE_ENUM(name, seq) \
+ DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(name, int, seq)
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! A statically sized vector with elements of type |T| indexed by
+//! the items of enumeration type |E|.
+/*!
+ * Items are value-initialized on construction.
+ */
+template <
+ class E,
+ class T,
+ E Min = TEnumTraits<E>::GetMinValue(),
+ E Max = TEnumTraits<E>::GetMaxValue()
+>
+class TEnumIndexedVector
+{
+public:
+ using TIndex = E;
+ using TValue = T;
+
+ TEnumIndexedVector();
+ TEnumIndexedVector(std::initializer_list<T> elements);
+
+ T& operator[] (E index);
+ const T& operator[] (E index) const;
+
+ // STL interop.
+ T* begin();
+ const T* begin() const;
+ T* end();
+ const T* end() const;
+
+ static bool IsDomainValue(E value);
+
+private:
+ using TUnderlying = typename TEnumTraits<E>::TUnderlying;
+ static constexpr int N = static_cast<TUnderlying>(Max) - static_cast<TUnderlying>(Min) + 1;
+ std::array<T, N> Items_;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! Returns |true| iff the enumeration value is not bitwise zero.
+template <typename E, typename = std::enable_if_t<NYT::TEnumTraits<E>::IsBitEnum, E>>
+bool Any(E value);
+
+//! Returns |true| iff the enumeration value is bitwise zero.
+template <typename E, typename = std::enable_if_t<NYT::TEnumTraits<E>::IsBitEnum, E>>
+bool None(E value);
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
+
+#define ENUM_INL_H_
+#include "enum-inl.h"
+#undef ENUM_INL_H_