aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-06-01 15:35:19 +0300
committerarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-06-01 15:35:19 +0300
commit8e7094c87fa7ad049e6ea600a5f90f1c97d683bd (patch)
treed3e66d7ea5843080db0f65be0b7752538f69a84b /tools
parente13a5fc9fa49c7a6508a49f29e21a15fd9dac9ec (diff)
downloadydb-8e7094c87fa7ad049e6ea600a5f90f1c97d683bd.tar.gz
intermediate changes
ref:b1e863e3aa12b888b40dd5ec36411ca050a25bd8
Diffstat (limited to 'tools')
-rw-r--r--tools/enum_parser/enum_parser/main.cpp103
-rw-r--r--tools/enum_parser/enum_serialization_runtime/CMakeLists.txt2
-rw-r--r--tools/enum_parser/enum_serialization_runtime/dispatch_methods.cpp1
-rw-r--r--tools/enum_parser/enum_serialization_runtime/dispatch_methods.h57
-rw-r--r--tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp120
-rw-r--r--tools/enum_parser/enum_serialization_runtime/enum_runtime.h71
-rw-r--r--tools/enum_parser/enum_serialization_runtime/ordered_pairs.cpp1
-rw-r--r--tools/enum_parser/enum_serialization_runtime/ordered_pairs.h71
8 files changed, 370 insertions, 56 deletions
diff --git a/tools/enum_parser/enum_parser/main.cpp b/tools/enum_parser/enum_parser/main.cpp
index 0943c69c1d..1985f2d42f 100644
--- a/tools/enum_parser/enum_parser/main.cpp
+++ b/tools/enum_parser/enum_parser/main.cpp
@@ -11,6 +11,7 @@
#include <util/charset/wide.h>
#include <util/string/builder.h>
+#include <util/string/escape.h>
#include <util/string/strip.h>
#include <util/string/cast.h>
#include <util/string/join.h>
@@ -174,7 +175,7 @@ void GenerateEnum(
out << "namespace { namespace " << nsName << " {\n";
TVector<TString> nameInitializerPairs;
- TVector<TString> valueInitializerPairs;
+ TVector<std::pair<TString, TString>> valueInitializerPairsUnsorted; // data, sort_key
TVector<TString> cppNamesInitializer;
TStringStream jItems;
@@ -197,18 +198,18 @@ void GenerateEnum(
strValue = it.Aliases[0];
OutKey(jEnumItem, "str_value", strValue);
}
- nameInitializerPairs.push_back("TNameBufs::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(strValue) + ")");
+ nameInitializerPairs.push_back("TNameBufsBase::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(strValue) + ")");
cppNamesInitializer.push_back(WrapStringBuf(it.CppName));
for (const auto& alias : it.Aliases) {
- valueInitializerPairs.push_back("TNameBufs::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(alias) + ")");
+ valueInitializerPairsUnsorted.emplace_back("TNameBufsBase::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(alias) + ")", UnescapeC(alias));
OutItem(jAliases, alias);
}
FinishItems(jAliases);
CloseArray(jAliases);
if (!it.Aliases) {
- valueInitializerPairs.push_back("TNameBufs::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(it.CppName) + ")");
+ valueInitializerPairsUnsorted.emplace_back("TNameBufsBase::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(it.CppName) + ")", it.CppName);
}
OutKey(jEnumItem, "aliases", jAliases.Str(), false);
@@ -221,6 +222,8 @@ void GenerateEnum(
CloseArray(jItems);
OutKey(jEnum, "items", jItems.Str(), false);
+ const TString nsNameBufsClass = nsName + "::TNameBufs";
+
auto defineConstArray = [&out, payloadCache = TMap<std::pair<TString, TVector<TString>>, TString>()](const TStringBuf indent, const TStringBuf elementType, const TStringBuf name, const TVector<TString>& items) mutable {
if (items.empty()) { // ISO C++ forbids zero-size array
out << indent << "static constexpr const TArrayRef<const " << elementType << "> " << name << ";\n";
@@ -240,23 +243,21 @@ void GenerateEnum(
out << "\n";
};
- out << " class TNameBufs : public ::NEnumSerializationRuntime::TEnumDescription<" << name << "> {\n";
- out << " public:\n";
- out << " using TBase = ::NEnumSerializationRuntime::TEnumDescription<" << name << ">;\n\n";
- out << " inline TNameBufs();\n\n";
-
- // Instance
- out << " static inline const TNameBufs& Instance() {\n";
- out << " return *SingletonWithPriority<TNameBufs, 0>();\n"; // destroy enum serializers last, because it may be used from destructor of another global object
- out << " }\n";
- out << " };\n\n";
+ out << " using TNameBufsBase = ::NEnumSerializationRuntime::TEnumDescription<" << name << ">;\n\n";
// Initialization data
- defineConstArray(" ", "TNameBufs::TBase::TEnumStringPair", "NAMES_INITIALIZATION_PAIRS", nameInitializerPairs);
- defineConstArray(" ", "TNameBufs::TBase::TEnumStringPair", "VALUES_INITIALIZATION_PAIRS", valueInitializerPairs);
+ defineConstArray(" ", "TNameBufsBase::TEnumStringPair", "NAMES_INITIALIZATION_PAIRS", nameInitializerPairs);
+ {
+ StableSortBy(valueInitializerPairsUnsorted, [](const auto& pair) -> const TString& { return pair.second; });
+ TVector<TString> valueInitializerPairs(Reserve(valueInitializerPairsUnsorted.size()));
+ for (auto& [value, _] : valueInitializerPairsUnsorted) {
+ valueInitializerPairs.push_back(std::move(value));
+ }
+ defineConstArray(" ", "TNameBufsBase::TEnumStringPair", "VALUES_INITIALIZATION_PAIRS", valueInitializerPairs);
+ }
defineConstArray(" ", "TStringBuf", "CPP_NAMES_INITIALIZATION_ARRAY", cppNamesInitializer);
- out << " static constexpr const TNameBufs::TInitializationData ENUM_INITIALIZATION_DATA{\n";
+ out << " static constexpr const TNameBufsBase::TInitializationData ENUM_INITIALIZATION_DATA{\n";
out << " NAMES_INITIALIZATION_PAIRS,\n";
out << " VALUES_INITIALIZATION_PAIRS,\n";
out << " CPP_NAMES_INITIALIZATION_ARRAY,\n";
@@ -264,9 +265,31 @@ void GenerateEnum(
out << " " << WrapStringBuf(name) << "\n";
out << " };\n\n";
+ // Properties
+ out << " static constexpr ::NEnumSerializationRuntime::ESortOrder NAMES_ORDER = ::NEnumSerializationRuntime::GetKeyFieldSortOrder(NAMES_INITIALIZATION_PAIRS);\n";
+ out << " static constexpr ::NEnumSerializationRuntime::ESortOrder VALUES_ORDER = ::NEnumSerializationRuntime::GetNameFieldSortOrder(VALUES_INITIALIZATION_PAIRS);\n";
+ out << "\n";
+
+ // Data holder
+ out << " class TNameBufs : public ::NEnumSerializationRuntime::TEnumDescription<" << name << "> {\n";
+ out << " public:\n";
+ out << " using TBase = ::NEnumSerializationRuntime::TEnumDescription<" << name << ">;\n\n";
+ out << " inline TNameBufs();\n\n";
+
+ // Reference initialization data from class
+ out << " static constexpr const TNameBufsBase::TInitializationData& EnumInitializationData = ENUM_INITIALIZATION_DATA;\n";
+ out << " static constexpr ::NEnumSerializationRuntime::ESortOrder NamesOrder = NAMES_ORDER;\n";
+ out << " static constexpr ::NEnumSerializationRuntime::ESortOrder ValuesOrder = VALUES_ORDER;\n\n";
+
+ // Instance
+ out << " static inline const TNameBufs& Instance() {\n";
+ out << " return *SingletonWithPriority<TNameBufs, 0>();\n"; // destroy enum serializers last, because it may be used from destructor of another global object
+ out << " }\n";
+ out << " };\n\n";
+
// Constructor
out << " inline TNameBufs::TNameBufs()\n";
- out << " : TBase(ENUM_INITIALIZATION_DATA)\n";
+ out << " : TBase(TNameBufs::EnumInitializationData)\n";
out << " {\n";
out << " }\n\n";
@@ -281,17 +304,28 @@ void GenerateEnum(
(*headerOutPtr) << "const TString& ToString(" << name << ");\n";
}
out << "const TString& ToString(" << name << " x) {\n";
- out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n";
+ out << " const " << nsNameBufsClass << "& names = " << nsNameBufsClass << "::Instance();\n";
out << " return names.ToString(x);\n";
out << "}\n\n";
+ // specialization for internal FromStringImpl
+ out << "template<>\n";
+ out << name << " FromStringImpl<" << name << ">(const char* data, size_t len) {\n";
+ out << " return ::NEnumSerializationRuntime::DispatchFromStringImplFn<" << nsNameBufsClass << ", " << name << ">(data, len);\n";
+ out << "}\n\n";
+
+ // specialization for internal TryFromStringImpl
+ out << "template<>\n";
+ out << "bool TryFromStringImpl<" << name << ">(const char* data, size_t len, " << name << "& result) {\n";
+ out << " return ::NEnumSerializationRuntime::DispatchTryFromStringImplFn<" << nsNameBufsClass << ", " << name << ">(data, len, result);\n";
+ out << "}\n\n";
+
// outer FromString
if (headerOutPtr) {
(*headerOutPtr) << "bool FromString(const TString& name, " << name << "& ret);\n";
}
out << "bool FromString(const TString& name, " << name << "& ret) {\n";
- out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n";
- out << " return names.FromString(name, ret);\n";
+ out << " return ::TryFromStringImpl<" << name << ">(name.data(), name.size(), ret);\n";
out << "}\n\n";
// outer FromString
@@ -299,28 +333,13 @@ void GenerateEnum(
(*headerOutPtr) << "bool FromString(const TStringBuf& name, " << name << "& ret);\n";
}
out << "bool FromString(const TStringBuf& name, " << name << "& ret) {\n";
- out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n";
- out << " return names.FromString(name, ret);\n";
- out << "}\n\n";
-
- // specialization for internal FromStringImpl
- out << "template<>\n";
- out << name << " FromStringImpl<" << name << ">(const char* data, size_t len) {\n";
- out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n";
- out << " return names.FromString(TStringBuf(data, len));\n";
- out << "}\n\n";
-
- // specialization for internal TryFromStringImpl
- out << "template<>\n";
- out << "bool TryFromStringImpl<" << name << ">(const char* data, size_t len, " << name << "& result) {\n";
- out << " return FromString(TStringBuf(data, len), result);\n";
+ out << " return ::TryFromStringImpl<" << name << ">(name.data(), name.size(), ret);\n";
out << "}\n\n";
// outer Out
out << "template<>\n";
out << "void Out<" << name << ">(IOutputStream& os, TTypeTraits<" << name << ">::TFuncParam n) {\n";
- out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n";
- out << " return names.Out(&os, n);\n";
+ out << " return ::NEnumSerializationRuntime::DispatchOutFn<" << nsNameBufsClass << ">(os, n);\n";
out << "}\n\n";
// specializations for NEnumSerializationRuntime function family
@@ -328,28 +347,28 @@ void GenerateEnum(
// template<> GetEnumAllValues
out << " template<>\n";
out << " TMappedArrayView<" << name <<"> GetEnumAllValuesImpl<" << name << ">() {\n";
- out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n";
+ out << " const " << nsNameBufsClass << "& names = " << nsNameBufsClass << "::Instance();\n";
out << " return names.AllEnumValues();\n";
out << " }\n\n";
// template<> GetEnumAllNames
out << " template<>\n";
out << " const TString& GetEnumAllNamesImpl<" << name << ">() {\n";
- out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n";
+ out << " const " << nsNameBufsClass << "& names = " << nsNameBufsClass << "::Instance();\n";
out << " return names.AllEnumNames();\n";
out << " }\n\n";
// template<> GetEnumNames<EnumType>
out << " template<>\n";
out << " TMappedDictView<" << name << ", TString> GetEnumNamesImpl<" << name << ">() {\n";
- out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n";
+ out << " const " << nsNameBufsClass << "& names = " << nsNameBufsClass << "::Instance();\n";
out << " return names.EnumNames();\n";
out << " }\n\n";
// template<> GetEnumAllCppNames, see IGNIETFERRO-534
out << " template<>\n";
out << " const TVector<TString>& GetEnumAllCppNamesImpl<" << name << ">() {\n";
- out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n";
+ out << " const " << nsNameBufsClass << "& names = " << nsNameBufsClass << "::Instance();\n";
out << " return names.AllEnumCppNames();\n";
out << " }\n";
diff --git a/tools/enum_parser/enum_serialization_runtime/CMakeLists.txt b/tools/enum_parser/enum_serialization_runtime/CMakeLists.txt
index 0da66ac23f..4a351266c6 100644
--- a/tools/enum_parser/enum_serialization_runtime/CMakeLists.txt
+++ b/tools/enum_parser/enum_serialization_runtime/CMakeLists.txt
@@ -13,5 +13,7 @@ target_link_libraries(tools-enum_parser-enum_serialization_runtime PUBLIC
yutil
)
target_sources(tools-enum_parser-enum_serialization_runtime PRIVATE
+ ${CMAKE_SOURCE_DIR}/tools/enum_parser/enum_serialization_runtime/dispatch_methods.cpp
${CMAKE_SOURCE_DIR}/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp
+ ${CMAKE_SOURCE_DIR}/tools/enum_parser/enum_serialization_runtime/ordered_pairs.cpp
)
diff --git a/tools/enum_parser/enum_serialization_runtime/dispatch_methods.cpp b/tools/enum_parser/enum_serialization_runtime/dispatch_methods.cpp
new file mode 100644
index 0000000000..cda48368bf
--- /dev/null
+++ b/tools/enum_parser/enum_serialization_runtime/dispatch_methods.cpp
@@ -0,0 +1 @@
+#include "dispatch_methods.h"
diff --git a/tools/enum_parser/enum_serialization_runtime/dispatch_methods.h b/tools/enum_parser/enum_serialization_runtime/dispatch_methods.h
new file mode 100644
index 0000000000..db752ae710
--- /dev/null
+++ b/tools/enum_parser/enum_serialization_runtime/dispatch_methods.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "ordered_pairs.h"
+
+#include <util/generic/strbuf.h>
+#include <util/stream/fwd.h>
+
+namespace NEnumSerializationRuntime {
+ // compile-time conversion method selection
+
+ constexpr size_t LINEAR_SEARCH_KEYS_SIZE_THRESHOLD = 6;
+ constexpr size_t LINEAR_SEARCH_VALUES_SIZE_THRESHOLD = 2;
+
+ template <class TNameBufs, typename EEnum>
+ inline void DispatchOutFn(IOutputStream& os, EEnum n) {
+ constexpr auto order = TNameBufs::NamesOrder;
+ if constexpr (order >= ::NEnumSerializationRuntime::ESortOrder::DirectMapping) {
+ return TNameBufs::OutDirect(&os, n, TNameBufs::EnumInitializationData);
+ } else if constexpr (std::size(TNameBufs::EnumInitializationData.NamesInitializer) <= LINEAR_SEARCH_KEYS_SIZE_THRESHOLD) {
+ return TNameBufs::OutFullScan(&os, n, TNameBufs::EnumInitializationData);
+ } else if constexpr (order >= ::NEnumSerializationRuntime::ESortOrder::Ascending) {
+ return TNameBufs::OutSorted(&os, n, TNameBufs::EnumInitializationData);
+ } else {
+ const TNameBufs& names = TNameBufs::Instance();
+ return names.Out(&os, n);
+ }
+ }
+
+ template <class TNameBufs, typename EEnum>
+ inline EEnum DispatchFromStringImplFn(const char* data, size_t len) {
+ const TStringBuf name{data, len};
+ constexpr auto order = TNameBufs::ValuesOrder;
+ static_assert(order >= ::NEnumSerializationRuntime::ESortOrder::Ascending, "enum_parser produced unsorted output"); // comment this line to use run-time sort for temporary workaround
+ if constexpr (std::size(TNameBufs::EnumInitializationData.ValuesInitializer) <= LINEAR_SEARCH_VALUES_SIZE_THRESHOLD) {
+ return TNameBufs::FromStringFullScan(name, TNameBufs::EnumInitializationData);
+ } else if constexpr (order >= ::NEnumSerializationRuntime::ESortOrder::Ascending) {
+ return TNameBufs::FromStringSorted(name, TNameBufs::EnumInitializationData);
+ } else {
+ const TNameBufs& names = TNameBufs::Instance();
+ return names.FromString(name);
+ }
+ }
+
+ template <class TNameBufs, typename EEnum>
+ inline bool DispatchTryFromStringImplFn(const char* data, size_t len, EEnum& result) {
+ const TStringBuf name{data, len};
+ constexpr auto order = TNameBufs::ValuesOrder;
+ if constexpr (std::size(TNameBufs::EnumInitializationData.ValuesInitializer) <= LINEAR_SEARCH_VALUES_SIZE_THRESHOLD) {
+ return TNameBufs::TryFromStringFullScan(name, result, TNameBufs::EnumInitializationData);
+ } else if constexpr (order >= ::NEnumSerializationRuntime::ESortOrder::Ascending) {
+ return TNameBufs::TryFromStringSorted(name, result, TNameBufs::EnumInitializationData);
+ } else {
+ const TNameBufs& names = TNameBufs::Instance();
+ return names.FromString(name, result);
+ }
+ }
+}
diff --git a/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp b/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp
index 2e7cc7f826..465f46b3e0 100644
--- a/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp
+++ b/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp
@@ -1,5 +1,6 @@
#include "enum_runtime.h"
+#include <util/generic/algorithm.h>
#include <util/generic/map.h>
#include <util/generic/yexception.h>
#include <util/stream/output.h>
@@ -28,11 +29,57 @@ namespace NEnumSerializationRuntime {
return {false, TRepresentationType()};
}
+ template <class TContainer, class TNeedle, class TGetKey>
+ static typename TContainer::value_type const* FindPtrInSortedContainer(const TContainer& vec, const TNeedle& needle, TGetKey&& getKey) {
+ const auto it = LowerBoundBy(vec.begin(), vec.end(), needle, getKey);
+ if (it == vec.end()) {
+ return nullptr;
+ }
+ if (getKey(*it) != needle) {
+ return nullptr;
+ }
+ return std::addressof(*it);
+ }
+
+ template <typename TEnumRepresentationType>
+ std::pair<bool, TEnumRepresentationType> TEnumDescriptionBase<TEnumRepresentationType>::TryFromStringSorted(const TStringBuf name, const TInitializationData& enumInitData) {
+ const auto& vec = enumInitData.ValuesInitializer;
+ const auto* ptr = FindPtrInSortedContainer(vec, name, std::mem_fn(&TEnumStringPair::Name));
+ if (ptr) {
+ return {true, ptr->Key};
+ }
+ return {false, TRepresentationType()};
+ }
+
+ template <typename TEnumRepresentationType>
+ std::pair<bool, TEnumRepresentationType> TEnumDescriptionBase<TEnumRepresentationType>::TryFromStringFullScan(const TStringBuf name, const TInitializationData& enumInitData) {
+ const auto& vec = enumInitData.ValuesInitializer;
+ const auto* ptr = FindIfPtr(vec, [&](const auto& item) { return item.Name == name; });
+ if (ptr) {
+ return {true, ptr->Key};
+ }
+ 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>
+ [[noreturn]] static void ThrowUndefinedNameException(const TStringBuf name, const typename TEnumDescriptionBase<TEnumRepresentationType>::TInitializationData& enumInitData) {
+ auto exc = __LOCATION__ + yexception() << "Key '" << name << "' not found in enum " << enumInitData.ClassName << ". Valid options are: ";
+ const auto& vec = enumInitData.NamesInitializer;
+ for (size_t i = 0; i < vec.size(); ++i) {
+ if (i != 0) {
+ exc << ", ";
+ }
+ exc << '\'' << vec[i].Name << '\'';
+ }
+ exc << ". ";
+ throw exc;
+ }
+
+ template <typename TEnumRepresentationType>
auto TEnumDescriptionBase<TEnumRepresentationType>::FromString(const TStringBuf name) const -> TRepresentationType {
const auto findResult = TryFromString(name);
if (Y_LIKELY(findResult.first)) {
@@ -42,8 +89,79 @@ namespace NEnumSerializationRuntime {
}
template <typename TEnumRepresentationType>
+ TEnumRepresentationType TEnumDescriptionBase<TEnumRepresentationType>::FromStringFullScan(const TStringBuf name, const TInitializationData& enumInitData) {
+ const auto findResult = TryFromStringFullScan(name, enumInitData);
+ if (Y_LIKELY(findResult.first)) {
+ return findResult.second;
+ }
+ ThrowUndefinedNameException<TEnumRepresentationType>(name, enumInitData);
+ }
+
+ template <typename TEnumRepresentationType>
+ TEnumRepresentationType TEnumDescriptionBase<TEnumRepresentationType>::FromStringSorted(const TStringBuf name, const TInitializationData& enumInitData) {
+ const auto findResult = TryFromStringSorted(name, enumInitData);
+ if (Y_LIKELY(findResult.first)) {
+ return findResult.second;
+ }
+ ThrowUndefinedNameException<TEnumRepresentationType>(name, enumInitData);
+ }
+
+ template <typename TEnumRepresentationType>
+ TStringBuf TEnumDescriptionBase<TEnumRepresentationType>::ToStringBuf(TRepresentationType key) const {
+ return this->ToString(key);
+ }
+
+ template <typename TEnumRepresentationType>
+ TStringBuf TEnumDescriptionBase<TEnumRepresentationType>::ToStringBufFullScan(const TRepresentationType key, const TInitializationData& enumInitData) {
+ const auto& vec = enumInitData.NamesInitializer;
+ const auto* ptr = FindIfPtr(vec, [&](const auto& item) { return item.Key == key; });
+ if (Y_UNLIKELY(!ptr)) {
+ ThrowUndefinedValueException(key, enumInitData.ClassName);
+ }
+ return ptr->Name;
+ }
+
+ template <typename TEnumRepresentationType>
+ TStringBuf TEnumDescriptionBase<TEnumRepresentationType>::ToStringBufSorted(const TRepresentationType key, const TInitializationData& enumInitData) {
+ const auto& vec = enumInitData.NamesInitializer;
+ const auto* ptr = FindPtrInSortedContainer(vec, key, std::mem_fn(&TEnumStringPair::Key));
+ if (Y_UNLIKELY(!ptr)) {
+ ThrowUndefinedValueException(key, enumInitData.ClassName);
+ }
+ return ptr->Name;
+ }
+
+ template <typename TEnumRepresentationType>
+ TStringBuf TEnumDescriptionBase<TEnumRepresentationType>::ToStringBufDirect(const TRepresentationType key, const TInitializationData& enumInitData) {
+ const auto& vec = enumInitData.NamesInitializer;
+ if (Y_UNLIKELY(vec.empty() || key < vec.front().Key)) {
+ ThrowUndefinedValueException(key, enumInitData.ClassName);
+ }
+ const size_t index = static_cast<size_t>(key - vec.front().Key);
+ if (Y_UNLIKELY(index >= vec.size())) {
+ ThrowUndefinedValueException(key, enumInitData.ClassName);
+ }
+ return vec[index].Name;
+ }
+
+ template <typename TEnumRepresentationType>
void TEnumDescriptionBase<TEnumRepresentationType>::Out(IOutputStream* os, const TRepresentationType key) const {
- (*os) << this->ToString(key);
+ (*os) << this->ToStringBuf(key);
+ }
+
+ template <typename TEnumRepresentationType>
+ void TEnumDescriptionBase<TEnumRepresentationType>::OutFullScan(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData) {
+ (*os) << ToStringBufFullScan(key, enumInitData);
+ }
+
+ template <typename TEnumRepresentationType>
+ void TEnumDescriptionBase<TEnumRepresentationType>::OutSorted(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData) {
+ (*os) << ToStringBufSorted(key, enumInitData);
+ }
+
+ template <typename TEnumRepresentationType>
+ void TEnumDescriptionBase<TEnumRepresentationType>::OutDirect(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData) {
+ (*os) << ToStringBufDirect(key, enumInitData);
}
template <typename TEnumRepresentationType>
diff --git a/tools/enum_parser/enum_serialization_runtime/enum_runtime.h b/tools/enum_parser/enum_serialization_runtime/enum_runtime.h
index 83c7a49b0a..cac142608d 100644
--- a/tools/enum_parser/enum_serialization_runtime/enum_runtime.h
+++ b/tools/enum_parser/enum_serialization_runtime/enum_runtime.h
@@ -1,26 +1,24 @@
#pragma once
+#include "dispatch_methods.h"
+#include "ordered_pairs.h"
+
#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 <util/stream/fwd.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;
- };
+ using TEnumStringPair = ::NEnumSerializationRuntime::TEnumStringPair<TRepresentationType>;
/// Refers initialization data stored in constexpr-friendly format
struct TInitializationData {
@@ -36,9 +34,24 @@ namespace NEnumSerializationRuntime {
~TEnumDescriptionBase();
const TString& ToString(TRepresentationType key) const;
+
+ TStringBuf ToStringBuf(TRepresentationType key) const;
+ static TStringBuf ToStringBufFullScan(const TRepresentationType key, const TInitializationData& enumInitData);
+ static TStringBuf ToStringBufSorted(const TRepresentationType key, const TInitializationData& enumInitData);
+ static TStringBuf ToStringBufDirect(const TRepresentationType key, const TInitializationData& enumInitData);
+
std::pair<bool, TRepresentationType> TryFromString(const TStringBuf name) const;
+ static std::pair<bool, TRepresentationType> TryFromStringFullScan(const TStringBuf name, const TInitializationData& enumInitData);
+ static std::pair<bool, TRepresentationType> TryFromStringSorted(const TStringBuf name, const TInitializationData& enumInitData);
+
TRepresentationType FromString(const TStringBuf name) const;
+ static TRepresentationType FromStringFullScan(const TStringBuf name, const TInitializationData& enumInitData);
+ static TRepresentationType FromStringSorted(const TStringBuf name, const TInitializationData& enumInitData);
+
void Out(IOutputStream* os, const TRepresentationType key) const;
+ static void OutFullScan(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData);
+ static void OutSorted(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData);
+ static void OutDirect(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData);
const TString& AllEnumNames() const noexcept {
return AllNames;
@@ -77,6 +90,15 @@ namespace NEnumSerializationRuntime {
using typename TBase::TRepresentationType;
using typename TBase::TInitializationData;
+ private:
+ static bool MapFindResult(std::pair<bool, TEnumRepresentationType> findResult, EEnum& ret) {
+ if (findResult.first) {
+ ret = TCast::CastFromRepresentationType(findResult.second);
+ return true;
+ }
+ return false;
+ }
+
public:
using TBase::TBase;
@@ -85,18 +107,29 @@ namespace NEnumSerializationRuntime {
}
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;
+ return MapFindResult(TBase::TryFromString(name), ret);
}
EEnum FromString(const TStringBuf name) const {
return TCast::CastFromRepresentationType(TBase::FromString(name));
}
+ static bool TryFromStringFullScan(const TStringBuf name, EEnum& ret, const TInitializationData& enumInitData) {
+ return MapFindResult(TBase::TryFromStringFullScan(name, enumInitData), ret);
+ }
+
+ static bool TryFromStringSorted(const TStringBuf name, EEnum& ret, const TInitializationData& enumInitData) {
+ return MapFindResult(TBase::TryFromStringSorted(name, enumInitData), ret);
+ }
+
+ static EEnum FromStringFullScan(const TStringBuf name, const TInitializationData& enumInitData) {
+ return TCast::CastFromRepresentationType(TBase::FromStringFullScan(name, enumInitData));
+ }
+
+ static EEnum FromStringSorted(const TStringBuf name, const TInitializationData& enumInitData) {
+ return TCast::CastFromRepresentationType(TBase::FromStringSorted(name, enumInitData));
+ }
+
TMappedDictView<EEnum, TString> EnumNames() const noexcept {
return {TBase::TypelessEnumNames()};
}
@@ -109,6 +142,18 @@ namespace NEnumSerializationRuntime {
TBase::Out(os, TCast::CastToRepresentationType(key));
}
+ static void OutFullScan(IOutputStream* os, const EEnum key, const TInitializationData& enumInitData) {
+ TBase::OutFullScan(os, TCast::CastToRepresentationType(key), enumInitData);
+ }
+
+ static void OutSorted(IOutputStream* os, const EEnum key, const TInitializationData& enumInitData) {
+ TBase::OutSorted(os, TCast::CastToRepresentationType(key), enumInitData);
+ }
+
+ static void OutDirect(IOutputStream* os, const EEnum key, const TInitializationData& enumInitData) {
+ TBase::OutDirect(os, TCast::CastToRepresentationType(key), enumInitData);
+ }
+
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/ordered_pairs.cpp b/tools/enum_parser/enum_serialization_runtime/ordered_pairs.cpp
new file mode 100644
index 0000000000..00d1d05129
--- /dev/null
+++ b/tools/enum_parser/enum_serialization_runtime/ordered_pairs.cpp
@@ -0,0 +1 @@
+#include "ordered_pairs.h"
diff --git a/tools/enum_parser/enum_serialization_runtime/ordered_pairs.h b/tools/enum_parser/enum_serialization_runtime/ordered_pairs.h
new file mode 100644
index 0000000000..874c709418
--- /dev/null
+++ b/tools/enum_parser/enum_serialization_runtime/ordered_pairs.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include <util/generic/array_ref.h>
+#include <util/generic/strbuf.h>
+
+namespace NEnumSerializationRuntime {
+ enum class ESortOrder: int {
+ Unordered = 0,
+ Ascending = 1,
+ StrictlyAscending = 2,
+ DirectMapping = 3,
+ };
+
+ template <typename TEnumRepresentationType>
+ struct TEnumStringPair {
+ const TEnumRepresentationType Key;
+ const TStringBuf Name;
+ };
+
+ template <typename TEnumRepresentationType>
+ constexpr ESortOrder GetKeyFieldSortOrder(const TArrayRef<const TEnumStringPair<TEnumRepresentationType>> initializer) {
+ if (initializer.empty()) {
+ return ESortOrder::DirectMapping;
+ }
+ bool direct = true;
+ bool strict = true;
+ bool sorted = true;
+ TEnumRepresentationType expected = initializer.data()[0].Key;
+ for (size_t i = 1; i < initializer.size(); ++i) {
+ const auto& prev = initializer.data()[i - 1].Key;
+ const auto& next = initializer.data()[i - 0].Key;
+ if (++expected != next) {
+ direct = false;
+ }
+ if (prev >= next) {
+ strict = false;
+ }
+ if (prev > next) {
+ sorted = false;
+ break;
+ }
+ }
+ return direct ? ESortOrder::DirectMapping
+ : strict ? ESortOrder::StrictlyAscending
+ : sorted ? ESortOrder::Ascending
+ : ESortOrder::Unordered;
+ }
+
+ template <typename TEnumRepresentationType>
+ constexpr ESortOrder GetNameFieldSortOrder(const TArrayRef<const TEnumStringPair<TEnumRepresentationType>> initializer) {
+ if (initializer.empty()) {
+ return ESortOrder::DirectMapping;
+ }
+ bool strict = true;
+ bool sorted = true;
+ for (size_t i = 1; i < initializer.size(); ++i) {
+ const std::string_view prev = initializer.data()[i - 1].Name;
+ const std::string_view next = initializer.data()[i - 0].Name;
+ if (prev >= next) {
+ strict = false;
+ }
+ if (prev > next) {
+ sorted = false;
+ break;
+ }
+ }
+ return strict ? ESortOrder::StrictlyAscending
+ : sorted ? ESortOrder::Ascending
+ : ESortOrder::Unordered;
+ }
+}