diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /tools/enum_parser/enum_serialization_runtime | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'tools/enum_parser/enum_serialization_runtime')
4 files changed, 231 insertions, 0 deletions
diff --git a/tools/enum_parser/enum_serialization_runtime/README.md b/tools/enum_parser/enum_serialization_runtime/README.md new file mode 100644 index 0000000000..7d2cbae4ce --- /dev/null +++ b/tools/enum_parser/enum_serialization_runtime/README.md @@ -0,0 +1,2 @@ +This library should not be used or referred directly. +Use `GENERATE_ENUM_SERIALIZATION_WITH_HEADER` and `GENERATE_ENUM_SERIALIZATION` macros instead. diff --git a/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp b/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp new file mode 100644 index 0000000000..73d38b396a --- /dev/null +++ b/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp @@ -0,0 +1,100 @@ +#include "enum_runtime.h" + +#include <util/generic/map.h> +#include <util/generic/yexception.h> +#include <util/stream/output.h> + +namespace NEnumSerializationRuntime { + template <typename TEnumRepresentationType> + [[noreturn]] static void ThrowUndefinedValueException(const TEnumRepresentationType key, const TStringBuf className) { + throw yexception() << "Undefined value " << key << " in " << className << ". "; + } + + template <typename TEnumRepresentationType> + const TString& TEnumDescriptionBase<TEnumRepresentationType>::ToString(TRepresentationType key) const { + const auto it = Names.find(key); + if (Y_LIKELY(it != Names.end())) { + return it->second; + } + ThrowUndefinedValueException(key, ClassName); + } + + template <typename TEnumRepresentationType> + std::pair<bool, TEnumRepresentationType> TEnumDescriptionBase<TEnumRepresentationType>::TryFromString(const TStringBuf name) const { + const auto it = Values.find(name); + if (it != Values.end()) { + return {true, it->second}; + } + return {false, TRepresentationType()}; + } + + [[noreturn]] static void ThrowUndefinedNameException(const TStringBuf name, const TStringBuf className, const TStringBuf allEnumNames) { + ythrow yexception() << "Key '" << name << "' not found in enum " << className << ". Valid options are: " << allEnumNames << ". "; + } + + template <typename TEnumRepresentationType> + auto TEnumDescriptionBase<TEnumRepresentationType>::FromString(const TStringBuf name) const -> TRepresentationType { + const auto findResult = TryFromString(name); + if (Y_LIKELY(findResult.first)) { + return findResult.second; + } + ThrowUndefinedNameException(name, ClassName, AllEnumNames()); + } + + template <typename TEnumRepresentationType> + void TEnumDescriptionBase<TEnumRepresentationType>::Out(IOutputStream* os, const TRepresentationType key) const { + (*os) << this->ToString(key); + } + + template <typename TEnumRepresentationType> + TEnumDescriptionBase<TEnumRepresentationType>::TEnumDescriptionBase(const TInitializationData& enumInitData) + : ClassName(enumInitData.ClassName) + { + const TArrayRef<const TEnumStringPair>& namesInitializer = enumInitData.NamesInitializer; + const TArrayRef<const TEnumStringPair>& valuesInitializer = enumInitData.ValuesInitializer; + const TArrayRef<const TStringBuf>& cppNamesInitializer = enumInitData.CppNamesInitializer; + + TMap<TRepresentationType, TString> mapValueToName; + TMap<TString, TRepresentationType> mapNameToValue; + const bool bijectiveHint = (namesInitializer.data() == valuesInitializer.data() && namesInitializer.size() == valuesInitializer.size()); + if (bijectiveHint) { + for (const TEnumStringPair& it : namesInitializer) { + TString name{it.Name}; + mapValueToName.emplace(it.Key, name); + mapNameToValue.emplace(std::move(name), it.Key); + } + } else { + for (const TEnumStringPair& it : namesInitializer) { + mapValueToName.emplace(it.Key, TString(it.Name)); + } + for (const TEnumStringPair& it : valuesInitializer) { + mapNameToValue.emplace(TString(it.Name), it.Key); + } + } + Names = std::move(mapValueToName); + Values = std::move(mapNameToValue); + + AllValues.reserve(Names.size()); + for (const auto& it : Names) { + if (!AllNames.empty()) { + AllNames += ", "; + } + AllNames += TString::Join('\'', it.second, '\''); + AllValues.push_back(it.first); + } + + AllCppNames.reserve(cppNamesInitializer.size()); + for (const auto& cn : cppNamesInitializer) { + AllCppNames.push_back(TString::Join(enumInitData.CppNamesPrefix, cn)); + } + } + + template <typename TEnumRepresentationType> + TEnumDescriptionBase<TEnumRepresentationType>::~TEnumDescriptionBase() = default; + + // explicit instantiation + template class TEnumDescriptionBase<int>; + template class TEnumDescriptionBase<unsigned>; + template class TEnumDescriptionBase<long long>; + template class TEnumDescriptionBase<unsigned long long>; +} diff --git a/tools/enum_parser/enum_serialization_runtime/enum_runtime.h b/tools/enum_parser/enum_serialization_runtime/enum_runtime.h new file mode 100644 index 0000000000..f157d43109 --- /dev/null +++ b/tools/enum_parser/enum_serialization_runtime/enum_runtime.h @@ -0,0 +1,116 @@ +#pragma once + +#include <util/generic/array_ref.h> +#include <util/generic/strbuf.h> +#include <util/generic/string.h> +#include <util/generic/vector.h> +#include <util/generic/serialized_enum.h> + +#include <utility> + +class IOutputStream; + +namespace NEnumSerializationRuntime { + /// Stores all information about enumeration except its real type + template <typename TEnumRepresentationType> + class TEnumDescriptionBase { + public: + using TRepresentationType = TEnumRepresentationType; + + struct TEnumStringPair { + const TRepresentationType Key; + const TStringBuf Name; + }; + + /// Refers initialization data stored in constexpr-friendly format + struct TInitializationData { + const TArrayRef<const TEnumStringPair> NamesInitializer; + const TArrayRef<const TEnumStringPair> ValuesInitializer; + const TArrayRef<const TStringBuf> CppNamesInitializer; + const TStringBuf CppNamesPrefix; + const TStringBuf ClassName; + }; + + public: + TEnumDescriptionBase(const TInitializationData& enumInitData); + ~TEnumDescriptionBase(); + + const TString& ToString(TRepresentationType key) const; + std::pair<bool, TRepresentationType> TryFromString(const TStringBuf name) const; + TRepresentationType FromString(const TStringBuf name) const; + void Out(IOutputStream* os, const TRepresentationType key) const; + + const TString& AllEnumNames() const noexcept { + return AllNames; + } + + const TVector<TString>& AllEnumCppNames() const noexcept { + return AllCppNames; + } + + const TMap<TRepresentationType, TString>& TypelessEnumNames() const noexcept { + return Names; + } + + const TVector<TRepresentationType>& TypelessEnumValues() const noexcept { + return AllValues; + } + + private: + TMap<TRepresentationType, TString> Names; + TMap<TString, TRepresentationType> Values; + TString AllNames; + TVector<TString> AllCppNames; + TString ClassName; + TVector<TRepresentationType> AllValues; + }; + + /// Wraps TEnumDescriptionBase and performs on-demand casts + template <typename EEnum, typename TEnumRepresentationType = typename NDetail::TSelectEnumRepresentationType<EEnum>::TType> + class TEnumDescription: public NDetail::TMappedViewBase<EEnum, TEnumRepresentationType>, private TEnumDescriptionBase<TEnumRepresentationType> { + public: + using TBase = TEnumDescriptionBase<TEnumRepresentationType>; + using TCast = NDetail::TMappedViewBase<EEnum, TEnumRepresentationType>; + using TBase::AllEnumCppNames; + using TBase::AllEnumNames; + using typename TBase::TEnumStringPair; + using typename TBase::TRepresentationType; + using typename TBase::TInitializationData; + + public: + using TBase::TBase; + + const TString& ToString(const EEnum key) const { + return TBase::ToString(TCast::CastToRepresentationType(key)); + } + + bool FromString(const TStringBuf name, EEnum& ret) const { + const auto findResult = TBase::TryFromString(name); + if (findResult.first) { + ret = TCast::CastFromRepresentationType(findResult.second); + return true; + } + return false; + } + + EEnum FromString(const TStringBuf name) const { + return TCast::CastFromRepresentationType(TBase::FromString(name)); + } + + TMappedDictView<EEnum, TString> EnumNames() const noexcept { + return {TBase::TypelessEnumNames()}; + } + + TMappedArrayView<EEnum> AllEnumValues() const noexcept { + return {TBase::TypelessEnumValues()}; + } + + void Out(IOutputStream* os, const EEnum key) const { + TBase::Out(os, TCast::CastToRepresentationType(key)); + } + + static constexpr TEnumStringPair EnumStringPair(const EEnum key, const TStringBuf name) noexcept { + return {TCast::CastToRepresentationType(key), name}; + } + }; +} diff --git a/tools/enum_parser/enum_serialization_runtime/ya.make b/tools/enum_parser/enum_serialization_runtime/ya.make new file mode 100644 index 0000000000..c18e4aee10 --- /dev/null +++ b/tools/enum_parser/enum_serialization_runtime/ya.make @@ -0,0 +1,13 @@ +LIBRARY() + +OWNER( + g:util + swarmer +) + +SRCS( + enum_runtime.cpp +) + + +END() |