#include "enum_runtime.h" #include #include #include namespace NEnumSerializationRuntime { template [[noreturn]] static void ThrowUndefinedValueException(const TEnumRepresentationType key, const TStringBuf className) { throw yexception() << "Undefined value " << key << " in " << className << ". "; } template const TString& TEnumDescriptionBase::ToString(TRepresentationType key) const { const auto it = Names.find(key); if (Y_LIKELY(it != Names.end())) { return it->second; } ThrowUndefinedValueException(key, ClassName); } template std::pair TEnumDescriptionBase::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 auto TEnumDescriptionBase::FromString(const TStringBuf name) const -> TRepresentationType { const auto findResult = TryFromString(name); if (Y_LIKELY(findResult.first)) { return findResult.second; } ThrowUndefinedNameException(name, ClassName, AllEnumNames()); } template void TEnumDescriptionBase::Out(IOutputStream* os, const TRepresentationType key) const { (*os) << this->ToString(key); } template TEnumDescriptionBase::TEnumDescriptionBase(const TInitializationData& enumInitData) : ClassName(enumInitData.ClassName) { const TArrayRef& namesInitializer = enumInitData.NamesInitializer; const TArrayRef& valuesInitializer = enumInitData.ValuesInitializer; const TArrayRef& cppNamesInitializer = enumInitData.CppNamesInitializer; TMap mapValueToName; TMap 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 TEnumDescriptionBase::~TEnumDescriptionBase() = default; // explicit instantiation template class TEnumDescriptionBase; template class TEnumDescriptionBase; template class TEnumDescriptionBase; template class TEnumDescriptionBase; }