#pragma once #include #include #include #include #include /* 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 Y_CONST_FUNCTION constexpr size_t GetEnumItemsCount(); namespace NEnumSerializationRuntime { namespace NDetail { template struct TSelectEnumRepresentationType; template > class TMappedArrayView; template > class TMappedDictView; } /// Class with behaviour similar to TMap template using TMappedDictView = NDetail::TMappedDictView::TType, TValueType>; /// Class with behaviour similar to TVector template using TMappedArrayView = NDetail::TMappedArrayView::TType>; /** * Returns names for items in enum or enum class * * @tparam EnumT enum type */ template TMappedDictView GetEnumNamesImpl(); /** * Returns unique items in enum or enum class * * @tparam EnumT enum type */ template ::NEnumSerializationRuntime::TMappedArrayView GetEnumAllValuesImpl(); /** * Returns human-readable comma-separated list of names in enum or enum class * * @tparam EnumT enum type */ template const TString& GetEnumAllNamesImpl(); /** * Returns C++ identifiers for items in enum or enum class * * @tparam EnumT enum type */ template const TVector& GetEnumAllCppNamesImpl(); /** * Converts @c e to a string. Works like @c ToString(e) function, but returns @c TStringBuf instead of @c TString. * Thus works slightly faster and usually avoids any dynamic memory allocation. * @throw yexception is case of unknown enum value */ template TStringBuf ToStringBuf(EnumT e); } /** * Returns names for items in enum or enum class * * @tparam EnumT enum type */ template Y_CONST_FUNCTION ::NEnumSerializationRuntime::TMappedDictView GetEnumNames() { return ::NEnumSerializationRuntime::GetEnumNamesImpl(); } /** * Returns unique items in enum or enum class * * @tparam EnumT enum type */ template Y_CONST_FUNCTION ::NEnumSerializationRuntime::TMappedArrayView GetEnumAllValues() { return ::NEnumSerializationRuntime::GetEnumAllValuesImpl(); } /** * Returns human-readable comma-separated list of names in enum or enum class * * @tparam EnumT enum type */ template Y_CONST_FUNCTION const TString& GetEnumAllNames() { return ::NEnumSerializationRuntime::GetEnumAllNamesImpl(); } /** * Returns C++ identifiers for items in enum or enum class * * @tparam EnumT enum type */ template Y_CONST_FUNCTION const TVector& GetEnumAllCppNames() { return ::NEnumSerializationRuntime::GetEnumAllCppNamesImpl(); } namespace NEnumSerializationRuntime { namespace NDetail { /// Checks that the `From` type can be promoted up to the `To` type without losses template struct TIsPromotable: public std::is_same, To> { static_assert(std::is_integral::value, "`From` type has to be an integer"); static_assert(std::is_integral::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 struct TSelectEnumRepresentationType { using TUnderlyingType = std::underlying_type_t; using TIsSigned = std::is_signed; using TRepresentationType = std::conditional_t< TIsSigned::value, std::conditional_t< TIsPromotable::value, int, long long>, std::conditional_t< TIsPromotable::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 class TMappedViewBase { static_assert(sizeof(std::underlying_type_t) <= 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(key); } static constexpr TRepresentationType CastToRepresentationType(const TEnumType key) noexcept { return static_cast(key); } }; /// Wrapper class with behaviour similar to TVector /// /// @tparam TEnumType enum type at the external interface /// @tparam TRepresentationType designated underlying type of enum /// @tparam TStorage internal container type template class TMappedArrayView: public TMappedViewBase { 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