123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- #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;
- } // namespace NDetail
- /// 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();
- /**
- * 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 <typename EnumT>
- TStringBuf ToStringBuf(EnumT e);
- } // namespace NEnumSerializationRuntime
- /**
- * 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;
- };
- } // namespace NDetail
- } // namespace NEnumSerializationRuntime
|