aboutsummaryrefslogtreecommitdiffstats
path: root/util/generic/serialized_enum.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/generic/serialized_enum.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/generic/serialized_enum.h')
-rw-r--r--util/generic/serialized_enum.h399
1 files changed, 399 insertions, 0 deletions
diff --git a/util/generic/serialized_enum.h b/util/generic/serialized_enum.h
new file mode 100644
index 00000000000..79df2bac22b
--- /dev/null
+++ b/util/generic/serialized_enum.h
@@ -0,0 +1,399 @@
+#pragma once
+
+#include <util/generic/fwd.h>
+#include <util/generic/vector.h>
+#include <util/generic/map.h>
+
+#include <cstddef>
+#include <type_traits>
+
+/*
+
+A file with declarations of enumeration-related functions.
+It doesn't contains definitions. To generate them you have to add
+
+ GENERATE_ENUM_SERIALIZATION_WITH_HEADER(your_header_with_your_enum.h)
+or
+ GENERATE_ENUM_SERIALIZATION(your_header_with_your_enum.h)
+
+in your ya.make
+
+@see https://st.yandex-team.ru/IGNIETFERRO-333
+@see https://wiki.yandex-team.ru/PoiskovajaPlatforma/Build/WritingCmakefiles/#generate-enum-with-header
+
+*/
+
+/**
+ * Returns number of distinct items in enum or enum class
+ *
+ * @tparam EnumT enum type
+ */
+template <typename EnumT>
+Y_CONST_FUNCTION constexpr size_t GetEnumItemsCount();
+
+namespace NEnumSerializationRuntime {
+ namespace NDetail {
+ template <typename EEnum>
+ struct TSelectEnumRepresentationType;
+
+ template <typename TEnumType, typename TRepresentationType, class TStorage = TVector<TRepresentationType>>
+ class TMappedArrayView;
+
+ template <typename TEnumType, typename TRepresentationType, typename TValueType, class TStorage = TMap<TRepresentationType, TValueType>>
+ class TMappedDictView;
+ }
+
+ /// Class with behaviour similar to TMap<EnumT, TValueType>
+ template <typename EnumT, typename TValueType>
+ using TMappedDictView = NDetail::TMappedDictView<EnumT, typename NDetail::TSelectEnumRepresentationType<EnumT>::TType, TValueType>;
+
+ /// Class with behaviour similar to TVector<EnumT>
+ template <typename EnumT>
+ using TMappedArrayView = NDetail::TMappedArrayView<EnumT, typename NDetail::TSelectEnumRepresentationType<EnumT>::TType>;
+
+ /**
+ * Returns names for items in enum or enum class
+ *
+ * @tparam EnumT enum type
+ */
+ template <typename EnumT>
+ TMappedDictView<EnumT, TString> GetEnumNamesImpl();
+ /**
+ * Returns unique items in enum or enum class
+ *
+ * @tparam EnumT enum type
+ */
+ template <typename EnumT>
+ ::NEnumSerializationRuntime::TMappedArrayView<EnumT> GetEnumAllValuesImpl();
+
+ /**
+ * Returns human-readable comma-separated list of names in enum or enum class
+ *
+ * @tparam EnumT enum type
+ */
+ template <typename EnumT>
+ const TString& GetEnumAllNamesImpl();
+
+ /**
+ * Returns C++ identifiers for items in enum or enum class
+ *
+ * @tparam EnumT enum type
+ */
+ template <typename EnumT>
+ const TVector<TString>& GetEnumAllCppNamesImpl();
+}
+
+/**
+ * Returns names for items in enum or enum class
+ *
+ * @tparam EnumT enum type
+ */
+template <typename EnumT>
+Y_CONST_FUNCTION ::NEnumSerializationRuntime::TMappedDictView<EnumT, TString> GetEnumNames() {
+ return ::NEnumSerializationRuntime::GetEnumNamesImpl<EnumT>();
+}
+
+/**
+ * Returns unique items in enum or enum class
+ *
+ * @tparam EnumT enum type
+ */
+template <typename EnumT>
+Y_CONST_FUNCTION ::NEnumSerializationRuntime::TMappedArrayView<EnumT> GetEnumAllValues() {
+ return ::NEnumSerializationRuntime::GetEnumAllValuesImpl<EnumT>();
+}
+
+/**
+ * Returns human-readable comma-separated list of names in enum or enum class
+ *
+ * @tparam EnumT enum type
+ */
+template <typename EnumT>
+Y_CONST_FUNCTION const TString& GetEnumAllNames() {
+ return ::NEnumSerializationRuntime::GetEnumAllNamesImpl<EnumT>();
+}
+
+/**
+ * Returns C++ identifiers for items in enum or enum class
+ *
+ * @tparam EnumT enum type
+ */
+template <typename EnumT>
+Y_CONST_FUNCTION const TVector<TString>& GetEnumAllCppNames() {
+ return ::NEnumSerializationRuntime::GetEnumAllCppNamesImpl<EnumT>();
+}
+
+namespace NEnumSerializationRuntime {
+ namespace NDetail {
+ /// Checks that the `From` type can be promoted up to the `To` type without losses
+ template <typename From, typename To>
+ struct TIsPromotable: public std::is_same<std::common_type_t<From, To>, To> {
+ static_assert(std::is_integral<From>::value, "`From` type has to be an integer");
+ static_assert(std::is_integral<To>::value, "`To` type has to be an integer");
+ };
+
+ /// Selects enum representation type. Works like std::underlying_type_t<>, but promotes small types up to `int`
+ template <typename EEnum>
+ struct TSelectEnumRepresentationType {
+ using TUnderlyingType = std::underlying_type_t<EEnum>;
+ using TIsSigned = std::is_signed<TUnderlyingType>;
+ using TRepresentationType = std::conditional_t<
+ TIsSigned::value,
+ std::conditional_t<
+ TIsPromotable<TUnderlyingType, int>::value,
+ int,
+ long long>,
+ std::conditional_t<
+ TIsPromotable<TUnderlyingType, unsigned>::value,
+ unsigned,
+ unsigned long long>>;
+ using TType = TRepresentationType;
+ static_assert(sizeof(TUnderlyingType) <= sizeof(TType), "size of `TType` is not smaller than the size of `TUnderlyingType`");
+ };
+
+ template <typename TEnumType, typename TRepresentationType>
+ class TMappedViewBase {
+ static_assert(sizeof(std::underlying_type_t<TEnumType>) <= sizeof(TRepresentationType), "Internal type is probably too small to represent all possible values");
+
+ public:
+ static constexpr TEnumType CastFromRepresentationType(const TRepresentationType key) noexcept {
+ return static_cast<TEnumType>(key);
+ }
+
+ static constexpr TRepresentationType CastToRepresentationType(const TEnumType key) noexcept {
+ return static_cast<TRepresentationType>(key);
+ }
+ };
+
+ /// Wrapper class with behaviour similar to TVector<EnumT>
+ ///
+ /// @tparam TEnumType enum type at the external interface
+ /// @tparam TRepresentationType designated underlying type of enum
+ /// @tparam TStorage internal container type
+ template <typename TEnumType, typename TRepresentationType, class TStorage>
+ class TMappedArrayView: public TMappedViewBase<TEnumType, TRepresentationType> {
+ public:
+ using value_type = TEnumType;
+
+ public:
+ TMappedArrayView(const TStorage& a) noexcept
+ : Ref(a)
+ {
+ }
+
+ class TIterator {
+ public:
+ using TSlaveIteratorType = typename TStorage::const_iterator;
+
+ using difference_type = std::ptrdiff_t;
+ using value_type = TEnumType;
+ using pointer = const TEnumType*;
+ using reference = const TEnumType&;
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ public:
+ TIterator(TSlaveIteratorType it)
+ : Slave(std::move(it))
+ {
+ }
+
+ bool operator==(const TIterator& it) const {
+ return Slave == it.Slave;
+ }
+
+ bool operator!=(const TIterator& it) const {
+ return !(*this == it);
+ }
+
+ TEnumType operator*() const {
+ return TMappedArrayView::CastFromRepresentationType(*Slave);
+ }
+
+ TIterator& operator++() {
+ ++Slave;
+ return *this;
+ }
+
+ TIterator& operator--() {
+ --Slave;
+ return *this;
+ }
+
+ TIterator operator++(int) {
+ auto temp = Slave;
+ ++Slave;
+ return temp;
+ }
+
+ TIterator operator--(int) {
+ auto temp = Slave;
+ --Slave;
+ return temp;
+ }
+
+ private:
+ TSlaveIteratorType Slave;
+ };
+
+ TIterator begin() const {
+ return Ref.begin();
+ }
+
+ TIterator end() const {
+ return Ref.end();
+ }
+
+ size_t size() const {
+ return Ref.size();
+ }
+
+ Y_PURE_FUNCTION bool empty() const {
+ return Ref.empty();
+ }
+
+ TEnumType at(size_t index) const {
+ return this->CastFromRepresentationType(Ref.at(index));
+ }
+
+ TEnumType operator[](size_t index) const {
+ return this->CastFromRepresentationType(Ref[index]);
+ }
+
+ // Allocate container and copy view's content into it
+ template <template <class...> class TContainer = TVector>
+ TContainer<TEnumType> Materialize() const {
+ return {begin(), end()};
+ }
+
+ private:
+ const TStorage& Ref;
+ };
+
+ /// Wrapper class with behaviour similar to TMap<EnumT, TValueType>
+ ///
+ /// @tparam TEnumType enum type at the external interface
+ /// @tparam TRepresentationType designated underlying type of enum
+ /// @tparam TValueType mapped value
+ /// @tparam TStorage internal container type
+ template <typename TEnumType, typename TRepresentationType, typename TValueType, class TStorage>
+ class TMappedDictView: public TMappedViewBase<TEnumType, TRepresentationType> {
+ public:
+ using TMappedItemType = std::pair<const TEnumType, const TValueType&>;
+
+ class TDereferenceResultHolder {
+ public:
+ TDereferenceResultHolder(const TRepresentationType enumValue, const TValueType& payload) noexcept
+ : Data(TMappedDictView::CastFromRepresentationType(enumValue), payload)
+ {
+ }
+
+ const TMappedItemType* operator->() const noexcept {
+ return &Data;
+ }
+
+ private:
+ TMappedItemType Data;
+ };
+
+ TMappedDictView(const TStorage& m) noexcept
+ : Ref(m)
+ {
+ }
+
+ class TIterator {
+ public:
+ using TSlaveIteratorType = typename TStorage::const_iterator;
+
+ using difference_type = std::ptrdiff_t;
+ using value_type = TMappedItemType;
+ using pointer = const TMappedItemType*;
+ using reference = const TMappedItemType&;
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ public:
+ TIterator(TSlaveIteratorType it)
+ : Slave(std::move(it))
+ {
+ }
+
+ bool operator==(const TIterator& it) const {
+ return Slave == it.Slave;
+ }
+
+ bool operator!=(const TIterator& it) const {
+ return !(*this == it);
+ }
+
+ TDereferenceResultHolder operator->() const {
+ return {Slave->first, Slave->second};
+ }
+
+ TMappedItemType operator*() const {
+ return {TMappedDictView::CastFromRepresentationType(Slave->first), Slave->second};
+ }
+
+ TIterator& operator++() {
+ ++Slave;
+ return *this;
+ }
+
+ TIterator& operator--() {
+ --Slave;
+ return *this;
+ }
+
+ TIterator operator++(int) {
+ auto temp = Slave;
+ ++Slave;
+ return temp;
+ }
+
+ TIterator operator--(int) {
+ auto temp = Slave;
+ --Slave;
+ return temp;
+ }
+
+ private:
+ TSlaveIteratorType Slave;
+ };
+
+ TIterator begin() const {
+ return Ref.begin();
+ }
+
+ TIterator end() const {
+ return Ref.end();
+ }
+
+ size_t size() const {
+ return Ref.size();
+ }
+
+ Y_PURE_FUNCTION bool empty() const {
+ return Ref.empty();
+ }
+
+ bool contains(const TEnumType key) const {
+ return Ref.contains(this->CastToRepresentationType(key));
+ }
+
+ TIterator find(const TEnumType key) const {
+ return Ref.find(this->CastToRepresentationType(key));
+ }
+
+ const TValueType& at(const TEnumType key) const {
+ return Ref.at(this->CastToRepresentationType(key));
+ }
+
+ // Allocate container and copy view's content into it
+ template <template <class...> class TContainer = TMap>
+ TContainer<TEnumType, TValueType> Materialize() const {
+ return {begin(), end()};
+ }
+
+ private:
+ const TStorage& Ref;
+ };
+ }
+}