aboutsummaryrefslogtreecommitdiffstats
path: root/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp
blob: 80a38fab9149f6b6e6b6d05ae2c3d94ee05ab86c (plain) (blame)
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>; 
}