1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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>;
}
|