aboutsummaryrefslogtreecommitdiffstats
path: root/yt
diff options
context:
space:
mode:
authorarkady-e1ppa <arkady-e1ppa@yandex-team.com>2024-05-08 19:50:23 +0300
committerarkady-e1ppa <arkady-e1ppa@yandex-team.com>2024-05-08 20:01:56 +0300
commitb9848536fa2642fab34114a1779ab886881495c4 (patch)
treebe492d31a4bd081464e936c3ac6187762731ca7c /yt
parentf2d47d896f4913ff5da2f328149322516fbadde6 (diff)
downloadydb-b9848536fa2642fab34114a1779ab886881495c4.tar.gz
YT-21310: Introduce CYsonStructSource to remove code duplication in TYsonStruct implementation (now with a fixed bug)
94a777c1510546c0a8a7ef3e3b327add7dfc3813
Diffstat (limited to 'yt')
-rw-r--r--yt/yt/core/ytree/yson_struct-inl.h24
-rw-r--r--yt/yt/core/ytree/yson_struct.cpp6
-rw-r--r--yt/yt/core/ytree/yson_struct.h31
-rw-r--r--yt/yt/core/ytree/yson_struct_detail-inl.h440
-rw-r--r--yt/yt/core/ytree/yson_struct_detail.h34
-rw-r--r--yt/yt/core/ytree/yson_struct_enum.h21
-rw-r--r--yt/yt/core/ytree/yson_struct_public.h48
7 files changed, 312 insertions, 292 deletions
diff --git a/yt/yt/core/ytree/yson_struct-inl.h b/yt/yt/core/ytree/yson_struct-inl.h
index 75f5b1db1d..baa01de7b5 100644
--- a/yt/yt/core/ytree/yson_struct-inl.h
+++ b/yt/yt/core/ytree/yson_struct-inl.h
@@ -264,8 +264,7 @@ TYsonStructRegistrar<TStruct>::operator TYsonStructRegistrar<TBase>()
////////////////////////////////////////////////////////////////////////////////
-template <class T>
- requires CExternallySerializable<T>
+template <CExternallySerializable T>
void Serialize(const T& value, NYson::IYsonConsumer* consumer)
{
using TSerializer = typename TGetExternalizedYsonStructTraits<T>::TExternalSerializer;
@@ -273,28 +272,13 @@ void Serialize(const T& value, NYson::IYsonConsumer* consumer)
Serialize(serializer, consumer);
}
-template <class T>
- requires CExternallySerializable<T>
-void DeserializeExternalized(T& value, INodePtr node, bool postprocess, bool setDefaults)
+template <CExternallySerializable T, CYsonStructSource TSource>
+void Deserialize(T& value, TSource source, bool postprocess, bool setDefaults)
{
using TTraits = TGetExternalizedYsonStructTraits<T>;
using TSerializer = typename TTraits::TExternalSerializer;
auto serializer = TSerializer::template CreateWritable<T, TSerializer>(value, setDefaults);
- serializer.Load(node, postprocess, setDefaults);
-}
-
-template <class T>
- requires CExternallySerializable<T>
-void Deserialize(T& value, INodePtr node)
-{
- DeserializeExternalized(value, std::move(node), /*postprocess*/ true, /*setDefaults*/ true);
-}
-
-template <class T>
- requires CExternallySerializable<T>
-void Deserialize(T& value, NYson::TYsonPullParserCursor* cursor)
-{
- Deserialize(value, NYson::ExtractTo<NYTree::INodePtr>(cursor));
+ serializer.Load(std::move(source), postprocess, setDefaults);
}
template <class T>
diff --git a/yt/yt/core/ytree/yson_struct.cpp b/yt/yt/core/ytree/yson_struct.cpp
index b939d17b9a..fbdad0be6b 100644
--- a/yt/yt/core/ytree/yson_struct.cpp
+++ b/yt/yt/core/ytree/yson_struct.cpp
@@ -51,16 +51,16 @@ void TYsonStructBase::Load(
INodePtr node,
bool postprocess,
bool setDefaults,
- const TYPath& path)
+ const NYPath::TYPath& path)
{
- Meta_->LoadStruct(this, node, postprocess, setDefaults, path);
+ Meta_->LoadStruct(this, std::move(node), postprocess, setDefaults, path);
}
void TYsonStructBase::Load(
TYsonPullParserCursor* cursor,
bool postprocess,
bool setDefaults,
- const TYPath& path)
+ const NYPath::TYPath& path)
{
Meta_->LoadStruct(this, cursor, postprocess, setDefaults, path);
}
diff --git a/yt/yt/core/ytree/yson_struct.h b/yt/yt/core/ytree/yson_struct.h
index 19300099bf..5d384840a8 100644
--- a/yt/yt/core/ytree/yson_struct.h
+++ b/yt/yt/core/ytree/yson_struct.h
@@ -1,13 +1,14 @@
#pragma once
#include "node.h"
-#include "yson_struct_enum.h"
+#include "yson_struct_public.h"
#include <yt/yt/core/misc/error.h>
#include <yt/yt/core/misc/mpl.h>
#include <yt/yt/core/misc/property.h>
#include <yt/yt/core/yson/public.h>
+
#include <yt/yt/library/syncmap/map.h>
#include <library/cpp/yt/misc/enum.h>
@@ -62,7 +63,7 @@ public:
virtual ~TYsonStructBase() = default;
void Load(
- NYTree::INodePtr node,
+ INodePtr node,
bool postprocess = true,
bool setDefaults = true,
const NYPath::TYPath& path = {});
@@ -293,21 +294,6 @@ private:
////////////////////////////////////////////////////////////////////////////////
template <class T>
-concept CExternalizedYsonStructTraits = requires {
- typename T::TExternalSerializer;
-};
-
-template <class T>
-concept CExternallySerializable = requires (T t) {
- { GetExternalizedYsonStructTraits(t) } -> CExternalizedYsonStructTraits;
-};
-
-template <CExternallySerializable T>
-using TGetExternalizedYsonStructTraits = decltype(GetExternalizedYsonStructTraits(std::declval<T>()));
-
-////////////////////////////////////////////////////////////////////////////////
-
-template <class T>
TIntrusivePtr<T> CloneYsonStruct(const TIntrusivePtr<const T>& obj);
template <class T>
TIntrusivePtr<T> CloneYsonStruct(const TIntrusivePtr<T>& obj);
@@ -320,15 +306,10 @@ void Serialize(const TYsonStructBase& value, NYson::IYsonConsumer* consumer);
void Deserialize(TYsonStructBase& value, INodePtr node);
void Deserialize(TYsonStructBase& value, NYson::TYsonPullParserCursor* cursor);
-template <class T>
- requires CExternallySerializable<T>
+template <CExternallySerializable T>
void Serialize(const T& value, NYson::IYsonConsumer* consumer);
-template <class T>
- requires CExternallySerializable<T>
-void Deserialize(T& value, INodePtr node);
-template <class T>
- requires CExternallySerializable<T>
-void Deserialize(T& value, NYson::TYsonPullParserCursor* cursor);
+template <CExternallySerializable T, CYsonStructSource TSource>
+void Deserialize(T& value, TSource source, bool postprocess = true, bool setDefaults = true);
template <class T>
TIntrusivePtr<T> UpdateYsonStruct(
diff --git a/yt/yt/core/ytree/yson_struct_detail-inl.h b/yt/yt/core/ytree/yson_struct_detail-inl.h
index 8c02116c43..c34a934c16 100644
--- a/yt/yt/core/ytree/yson_struct_detail-inl.h
+++ b/yt/yt/core/ytree/yson_struct_detail-inl.h
@@ -35,223 +35,175 @@ concept SupportsDontSerializeDefault =
////////////////////////////////////////////////////////////////////////////////
-// Primitive type
template <class T>
-void LoadFromNode(
- T& parameter,
- NYTree::INodePtr node,
- const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> /*recursiveUnrecognizedStrategy*/)
-{
- try {
- Deserialize(parameter, node);
- } catch (const std::exception& ex) {
- THROW_ERROR_EXCEPTION("Error reading parameter %v", path)
- << ex;
- }
-}
-
-// INodePtr
-template <>
-inline void LoadFromNode(
- NYTree::INodePtr& parameter,
- NYTree::INodePtr node,
- const NYPath::TYPath& /*path*/,
- std::optional<EUnrecognizedStrategy> /*recursiveUnrecognizedStrategy*/)
+T DeserializeMapKey(TStringBuf value)
{
- if (!parameter) {
- parameter = node;
+ if constexpr (TEnumTraits<T>::IsEnum) {
+ return ParseEnum<T>(value);
+ } else if constexpr (std::is_same_v<T, TGuid>) {
+ return TGuid::FromString(value);
+ } else if constexpr (TStrongTypedefTraits<T>::IsStrongTypedef) {
+ return T(DeserializeMapKey<typename TStrongTypedefTraits<T>::TUnderlying>(value));
} else {
- parameter = PatchNode(parameter, node);
+ return FromString<T>(value);
}
}
-// TYsonStruct
-template <CYsonStructDerived T>
-void LoadFromNode(
- TIntrusivePtr<T>& parameterValue,
- NYTree::INodePtr node,
- const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+concept CNodePtr = requires (T node) {
+ [] (INodePtr) { } (node);
+};
+
+template <CNodePtr TNodePtr>
+struct TYsonSourceTraits<TNodePtr>
{
- if (!parameterValue) {
- parameterValue = New<T>();
+ static constexpr bool IsValid = true;
+
+ static INodePtr AsNode(TNodePtr& source)
+ {
+ // NRVO.
+ return source;
}
- if (recursiveUnrecognizedStrategy) {
- parameterValue->SetUnrecognizedStrategy(*recursiveUnrecognizedStrategy);
+ static bool IsEmpty(TNodePtr& source)
+ {
+ return source->GetType() == ENodeType::Entity;
}
- parameterValue->Load(node, /*postprocess*/ false, /*setDefaults*/ false, path);
-}
+ static void Advance(TNodePtr& /*source*/)
+ { }
-// YsonStructLite
-template <std::derived_from<TYsonStructLite> T>
-void LoadFromNode(
- T& parameter,
- NYTree::INodePtr node,
- const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> /*recursiveUnrecognizedStrategy*/)
-{
- try {
- parameter.Load(node, /*postprocess*/ false, /*setDefaults*/ false);
- } catch (const std::exception& ex) {
- THROW_ERROR_EXCEPTION("Error reading parameter %v", path)
- << ex;
+ template <class... TArgs, class TFiller>
+ static void FillVector(TNodePtr& source, std::vector<TArgs...>& vector, TFiller filler)
+ {
+ auto listNode = source->AsList();
+ auto size = listNode->GetChildCount();
+ vector.reserve(size);
+ for (int i = 0; i < size; ++i) {
+ filler(vector, std::move(listNode->GetChildOrThrow(i)));
+ }
}
-}
-// ExternalizedYsonStruct
-template <CExternallySerializable T>
-void LoadFromNode(
- T& parameter,
- NYTree::INodePtr node,
- const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> /*recursiveUnrecognizedStrategy*/)
-{
- try {
- DeserializeExternalized(parameter, node, /*postprocess*/ false, /*setDefaults*/ false);
- } catch (const std::exception& ex) {
- THROW_ERROR_EXCEPTION("Error reading parameter %v", path)
- << ex;
+ template <CAnyMap TMap, class TFiller>
+ static void FillMap(TNodePtr& source, TMap& map, TFiller filler)
+ {
+ auto mapNode = source->AsMap();
+
+ // NB: We iterate over temporary object anyway.
+ // Might as well move key/child into the filler
+ for (auto [key, child] : mapNode->GetChildren()) {
+ filler(map, std::move(key), std::move(child));
+ }
}
-}
+};
-// std::optional
-template <class T>
-void LoadFromNode(
- std::optional<T>& parameter,
- NYTree::INodePtr node,
- const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
+template <>
+struct TYsonSourceTraits<NYson::TYsonPullParserCursor*>
{
- if (node->GetType() == NYTree::ENodeType::Entity) {
- parameter = std::nullopt;
- return;
+ static constexpr bool IsValid = true;
+
+ static INodePtr AsNode(NYson::TYsonPullParserCursor*& source)
+ {
+ return NYson::ExtractTo<NYTree::INodePtr>(source);
}
- if (parameter.has_value()) {
- LoadFromNode(*parameter, node, path, recursiveUnrecognizedStrategy);
- } else {
- T value;
- LoadFromNode(value, node, path, recursiveUnrecognizedStrategy);
- parameter = std::move(value);
+ static bool IsEmpty(NYson::TYsonPullParserCursor*& source)
+ {
+ return (*source)->GetType() == NYson::EYsonItemType::EntityValue;
}
-}
-// std::vector
-template <class... T>
-void LoadFromNode(
- std::vector<T...>& parameter,
- NYTree::INodePtr node,
- const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
-{
- auto listNode = node->AsList();
- auto size = listNode->GetChildCount();
- parameter.clear();
- parameter.reserve(size);
- for (int i = 0; i < size; ++i) {
- LoadFromNode(
- parameter.emplace_back(),
- listNode->GetChildOrThrow(i),
- path + "/" + NYPath::ToYPathLiteral(i),
- recursiveUnrecognizedStrategy);
+ static void Advance(NYson::TYsonPullParserCursor*& source)
+ {
+ source->Next();
}
-}
-template <class T>
-T DeserializeMapKey(TStringBuf value)
-{
- if constexpr (TEnumTraits<T>::IsEnum) {
- return ParseEnum<T>(value);
- } else if constexpr (std::is_same_v<T, TGuid>) {
- return TGuid::FromString(value);
- } else if constexpr (TStrongTypedefTraits<T>::IsStrongTypedef) {
- return T(DeserializeMapKey<typename TStrongTypedefTraits<T>::TUnderlying>(value));
- } else {
- return FromString<T>(value);
+ template <class... TArgs, class TFiller>
+ static void FillVector(NYson::TYsonPullParserCursor*& source, std::vector<TArgs...>& vector, TFiller filler)
+ {
+ source->ParseList([&](NYson::TYsonPullParserCursor* cursor) {
+ filler(vector, cursor);
+ });
}
-}
-// For any map.
-template <template <typename...> class Map, class... T, class M = typename Map<T...>::mapped_type>
-void LoadFromNode(
- Map<T...>& parameter,
- NYTree::INodePtr node,
- const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
-{
- auto mapNode = node->AsMap();
- for (const auto& [key, child] : mapNode->GetChildren()) {
- M value;
- LoadFromNode(
- value,
- child,
- path + "/" + NYPath::ToYPathLiteral(key),
- recursiveUnrecognizedStrategy);
- parameter[DeserializeMapKey<typename Map<T...>::key_type>(key)] = std::move(value);
+ template <CAnyMap TMap, class TFiller>
+ static void FillMap(NYson::TYsonPullParserCursor*& source, TMap& map, TFiller filler)
+ {
+ source->ParseMap([&] (NYson::TYsonPullParserCursor* cursor) {
+ auto key = ExtractTo<TString>(cursor);
+ filler(map, std::move(key), source);
+ });
}
-}
+};
////////////////////////////////////////////////////////////////////////////////
-// Primitive type or YsonStructLite
-// See LoadFromNode for further specialization.
-template <class T>
-void LoadFromCursor(
- T& parameter,
- NYson::TYsonPullParserCursor* cursor,
- const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
-{
- LoadFromNode(parameter, NYson::ExtractTo<NYTree::INodePtr>(cursor), path, recursiveUnrecognizedStrategy);
-}
-
-////////////////////////////////////////////////////////////////////////////////
+// NB(arkady-e1ppa): We perform forward declaration of containers
+// so that we can find the correct overload for any composition of them
+// e.g. std::optional<std::vector<T>>.
-template <CYsonStructDerived T>
-void LoadFromCursor(
- TIntrusivePtr<T>& parameterValue,
- NYson::TYsonPullParserCursor* cursor,
+// std::optional
+template <class T, CYsonStructSource TSource>
+void LoadFromSource(
+ std::optional<T>& parameter,
+ TSource source,
const NYPath::TYPath& path,
std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy);
-template <class... T>
-void LoadFromCursor(
- std::vector<T...>& parameter,
- NYson::TYsonPullParserCursor* cursor,
+// std::vector
+template <CStdVector TVector, CYsonStructSource TSource>
+void LoadFromSource(
+ TVector& parameter,
+ TSource source,
const NYPath::TYPath& path,
std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy);
-// std::optional
-template <class T>
-void LoadFromCursor(
- std::optional<T>& parameter,
- NYson::TYsonPullParserCursor* cursor,
+// any map.
+template <CAnyMap TMap, CYsonStructSource TSource>
+void LoadFromSource(
+ TMap& parameter,
+ TSource source,
const NYPath::TYPath& path,
std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy);
-template <template <typename...> class Map, class... T, class M = typename Map<T...>::mapped_type>
-void LoadFromCursor(
- Map<T...>& parameter,
- NYson::TYsonPullParserCursor* cursor,
+////////////////////////////////////////////////////////////////////////////////
+
+// Primitive type
+template <class T, CYsonStructSource TSource>
+void LoadFromSource(
+ T& parameter,
+ TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy);
+ std::optional<EUnrecognizedStrategy> /*ignored*/)
+{
+ using TTraits = TYsonSourceTraits<TSource>;
-////////////////////////////////////////////////////////////////////////////////
+ try {
+ Deserialize(parameter, TTraits::AsNode(source));
+ } catch (const std::exception& ex) {
+ THROW_ERROR_EXCEPTION("Error reading parameter %v", path)
+ << ex;
+ }
+}
// INodePtr
-template <>
-inline void LoadFromCursor(
- NYTree::INodePtr& parameter,
- NYson::TYsonPullParserCursor* cursor,
+template <CYsonStructSource TSource>
+void LoadFromSource(
+ INodePtr& parameter,
+ TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
+ std::optional<EUnrecognizedStrategy> /*ignored*/)
{
+ using TTraits = TYsonSourceTraits<TSource>;
+
try {
- auto node = NYson::ExtractTo<INodePtr>(cursor);
- LoadFromNode(parameter, std::move(node), path, recursiveUnrecognizedStrategy);
+ auto node = TTraits::AsNode(source);
+ if (!parameter) {
+ parameter = std::move(node);
+ } else {
+ parameter = PatchNode(parameter, std::move(node));
+ }
} catch (const std::exception& ex) {
THROW_ERROR_EXCEPTION("Error loading parameter %v", path)
<< ex;
@@ -259,45 +211,82 @@ inline void LoadFromCursor(
}
// TYsonStruct
-template <CYsonStructDerived T>
-void LoadFromCursor(
- TIntrusivePtr<T>& parameterValue,
- NYson::TYsonPullParserCursor* cursor,
+template <CYsonStructDerived T, CYsonStructSource TSource>
+void LoadFromSource(
+ TIntrusivePtr<T>& parameter,
+ TSource source,
const NYPath::TYPath& path,
std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
{
- if (!parameterValue) {
- parameterValue = New<T>();
+ if (!parameter) {
+ parameter = New<T>();
}
if (recursiveUnrecognizedStrategy) {
- parameterValue->SetUnrecognizedStrategy(*recursiveUnrecognizedStrategy);
+ parameter->SetUnrecognizedStrategy(*recursiveUnrecognizedStrategy);
}
- parameterValue->Load(cursor, /*postprocess*/ false, /*setDefaults*/ false, path);
+ parameter->Load(std::move(source), /*postprocess*/ false, /*setDefaults*/ false, path);
+}
+
+// YsonStructLite
+template <std::derived_from<TYsonStructLite> T, CYsonStructSource TSource>
+void LoadFromSource(
+ T& parameter,
+ TSource source,
+ const NYPath::TYPath& path,
+ std::optional<EUnrecognizedStrategy> /*ignored*/)
+{
+ try {
+ parameter.Load(std::move(source), /*postprocess*/ false, /*setDefaults*/ false, path);
+ } catch (const std::exception& ex) {
+ THROW_ERROR_EXCEPTION("Error reading parameter %v", path)
+ << ex;
+ }
+}
+
+// ExternalizedYsonStruct
+template <CExternallySerializable T, CYsonStructSource TSource>
+void LoadFromSource(
+ T& parameter,
+ TSource source,
+ const NYPath::TYPath& path,
+ std::optional<EUnrecognizedStrategy> /*ignored*/)
+{
+ try {
+ Deserialize(parameter, std::move(source), /*postprocess*/ false, /*setDefaults*/ false);
+ } catch (const std::exception& ex) {
+ THROW_ERROR_EXCEPTION("Error reading parameter %v", path)
+ << ex;
+ }
}
// std::optional
-template <class T>
-void LoadFromCursor(
+template <class T, CYsonStructSource TSource>
+void LoadFromSource(
std::optional<T>& parameter,
- NYson::TYsonPullParserCursor* cursor,
+ TSource source,
const NYPath::TYPath& path,
std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
{
+ using TTraits = TYsonSourceTraits<TSource>;
+
try {
- if ((*cursor)->GetType() == NYson::EYsonItemType::EntityValue) {
+ if (TTraits::IsEmpty(source)) {
parameter = std::nullopt;
- cursor->Next();
- } else {
- if (parameter.has_value()) {
- LoadFromCursor(*parameter, cursor, path, recursiveUnrecognizedStrategy);
- } else {
- T value;
- LoadFromCursor(value, cursor, path, recursiveUnrecognizedStrategy);
- parameter = std::move(value);
- }
+ TTraits::Advance(source);
+ return;
+ }
+
+ if (parameter.has_value()) {
+ LoadFromSource(*parameter, std::move(source), path, recursiveUnrecognizedStrategy);
+ return;
}
+
+ T value;
+ LoadFromSource(value, std::move(source), path, recursiveUnrecognizedStrategy);
+ parameter = std::move(value);
+
} catch (const std::exception& ex) {
THROW_ERROR_EXCEPTION("Error loading parameter %v", path)
<< ex;
@@ -305,20 +294,23 @@ void LoadFromCursor(
}
// std::vector
-template <class... T>
-void LoadFromCursor(
- std::vector<T...>& parameter,
- NYson::TYsonPullParserCursor* cursor,
+template <CStdVector TVector, CYsonStructSource TSource>
+void LoadFromSource(
+ TVector& parameter,
+ TSource source,
const NYPath::TYPath& path,
std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
{
+ using TTraits = TYsonSourceTraits<TSource>;
+
try {
parameter.clear();
int index = 0;
- cursor->ParseList([&] (NYson::TYsonPullParserCursor* cursor) {
- LoadFromCursor(
- parameter.emplace_back(),
- cursor,
+
+ TTraits::FillVector(source, parameter, [&] (auto& vector, auto elementSource) {
+ LoadFromSource(
+ vector.emplace_back(),
+ elementSource,
path + "/" + NYPath::ToYPathLiteral(index),
recursiveUnrecognizedStrategy);
++index;
@@ -329,24 +321,28 @@ void LoadFromCursor(
}
}
-// For any map.
-template <template <typename...> class Map, class... T, class M>
-void LoadFromCursor(
- Map<T...>& parameter,
- NYson::TYsonPullParserCursor* cursor,
+// any map.
+template <CAnyMap TMap, CYsonStructSource TSource>
+void LoadFromSource(
+ TMap& parameter,
+ TSource source,
const NYPath::TYPath& path,
std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
{
+ using TTraits = TYsonSourceTraits<TSource>;
+ // TODO(arkady-e1ppa): Remove "typename" when clang-14 is abolished.
+ using TKey = typename TMap::key_type;
+ using TValue = typename TMap::mapped_type;
+
try {
- cursor->ParseMap([&] (NYson::TYsonPullParserCursor* cursor) {
- auto key = ExtractTo<TString>(cursor);
- M value;
- LoadFromCursor(
+ TTraits::FillMap(source, parameter, [&] (TMap& map, const TString& key, auto childSource) {
+ TValue value;
+ LoadFromSource(
value,
- cursor,
+ childSource,
path + "/" + NYPath::ToYPathLiteral(key),
recursiveUnrecognizedStrategy);
- parameter[DeserializeMapKey<typename Map<T...>::key_type>(key)] = std::move(value);
+ map[DeserializeMapKey<TKey>(key)] = std::move(value);
});
} catch (const std::exception& ex) {
THROW_ERROR_EXCEPTION("Error loading parameter %v", path)
@@ -440,9 +436,9 @@ inline void PostprocessRecursive(
}
// std::vector
-template <class T>
+template <CStdVector TVector>
inline void PostprocessRecursive(
- std::vector<T>& parameter,
+ TVector& parameter,
const NYPath::TYPath& path)
{
for (size_t i = 0; i < parameter.size(); ++i) {
@@ -453,9 +449,9 @@ inline void PostprocessRecursive(
}
// any map
-template <template <typename...> class Map, class... T, class M = typename Map<T...>::mapped_type>
+template <CAnyMap TMap>
inline void PostprocessRecursive(
- Map<T...>& parameter,
+ TMap& parameter,
const NYPath::TYPath& path)
{
for (auto& [key, value] : parameter) {
@@ -503,15 +499,15 @@ inline void ResetOnLoad(std::optional<T>& parameter)
}
// std::vector
-template <class T>
-inline void ResetOnLoad(std::vector<T>& parameter)
+template <CStdVector TVector>
+inline void ResetOnLoad(TVector& parameter)
{
parameter.clear();
}
// any map
-template <template <typename...> class Map, class... T, class M = typename Map<T...>::mapped_type>
-inline void ResetOnLoad(Map<T...>& parameter)
+template <CAnyMap TMap>
+inline void ResetOnLoad(TMap& parameter)
{
parameter.clear();
}
@@ -564,7 +560,7 @@ void TYsonStructParameter<TValue>::Load(
if (ResetOnLoad_) {
NPrivate::ResetOnLoad(FieldAccessor_->GetValue(self));
}
- NPrivate::LoadFromNode(
+ NPrivate::LoadFromSource(
FieldAccessor_->GetValue(self),
std::move(node),
options.Path,
@@ -585,7 +581,7 @@ void TYsonStructParameter<TValue>::Load(
if (ResetOnLoad_) {
NPrivate::ResetOnLoad(FieldAccessor_->GetValue(self));
}
- NPrivate::LoadFromCursor(
+ NPrivate::LoadFromSource(
FieldAccessor_->GetValue(self),
cursor,
options.Path,
@@ -607,7 +603,7 @@ void TYsonStructParameter<TValue>::SafeLoad(
TValue oldValue = FieldAccessor_->GetValue(self);
try {
FieldAccessor_->GetValue(self) = TValue();
- NPrivate::LoadFromNode(
+ NPrivate::LoadFromSource(
FieldAccessor_->GetValue(self),
node,
options.Path,
diff --git a/yt/yt/core/ytree/yson_struct_detail.h b/yt/yt/core/ytree/yson_struct_detail.h
index 17da9bf149..91700f89e7 100644
--- a/yt/yt/core/ytree/yson_struct_detail.h
+++ b/yt/yt/core/ytree/yson_struct_detail.h
@@ -1,6 +1,6 @@
#pragma once
-#include "yson_struct_enum.h"
+#include "yson_struct_public.h"
#include <yt/yt/core/yson/public.h>
#include <yt/yt/core/ypath/public.h>
@@ -12,6 +12,38 @@ namespace NYT::NYTree {
////////////////////////////////////////////////////////////////////////////////
+namespace NPrivate {
+
+// Least common denominator between INodePtr
+// and TYsonPullParserCursor.
+// Maybe something else in the future.
+template <class T>
+struct TYsonSourceTraits
+{
+ static constexpr bool IsValid = false;
+
+ static INodePtr AsNode(T& source)
+ requires false;
+
+ static bool IsEmpty(T& source)
+ requires false;
+
+ static void Advance(T& source)
+ requires false;
+
+ template <CStdVector TVector, class TFiller>
+ static void FillVector(T& source, TVector& vector, TFiller filler)
+ requires false;
+
+ template <CAnyMap TMap, class TFiller>
+ static void FillMap(T& source, TMap& map, TFiller filler)
+ requires false;
+};
+
+} // namespace NPrivate
+
+////////////////////////////////////////////////////////////////////////////////
+
template <class TStruct, class TValue>
using TYsonStructField = TValue(TStruct::*);
diff --git a/yt/yt/core/ytree/yson_struct_enum.h b/yt/yt/core/ytree/yson_struct_enum.h
deleted file mode 100644
index a35fba6d0d..0000000000
--- a/yt/yt/core/ytree/yson_struct_enum.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-#include <library/cpp/yt/memory/serialize.h>
-
-#include <library/cpp/yt/misc/enum.h>
-
-namespace NYT::NYTree {
-
-///////////////////////////////////////////////////////////////////////////////
-
-DEFINE_ENUM(EUnrecognizedStrategy,
- (Drop)
- (Keep)
- (KeepRecursive)
- (Throw)
- (ThrowRecursive)
-);
-
-////////////////////////////////////////////////////////////////////////////////
-
-} // namespace NYT::NYTree
diff --git a/yt/yt/core/ytree/yson_struct_public.h b/yt/yt/core/ytree/yson_struct_public.h
new file mode 100644
index 0000000000..495a47b46f
--- /dev/null
+++ b/yt/yt/core/ytree/yson_struct_public.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <library/cpp/yt/memory/serialize.h>
+
+#include <library/cpp/yt/misc/enum.h>
+
+namespace NYT::NYTree {
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEFINE_ENUM(EUnrecognizedStrategy,
+ (Drop)
+ (Keep)
+ (KeepRecursive)
+ (Throw)
+ (ThrowRecursive)
+);
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+concept CExternalizedYsonStructTraits = requires {
+ typename T::TExternalSerializer;
+};
+
+template <class T>
+concept CExternallySerializable = requires (T t) {
+ { GetExternalizedYsonStructTraits(t) } -> CExternalizedYsonStructTraits;
+};
+
+template <CExternallySerializable T>
+using TGetExternalizedYsonStructTraits = decltype(GetExternalizedYsonStructTraits(std::declval<T>()));
+
+////////////////////////////////////////////////////////////////////////////////
+
+namespace NPrivate {
+
+template <class T>
+struct TYsonSourceTraits;
+
+} // namespace NPrivate
+
+template <class T>
+concept CYsonStructSource = NPrivate::TYsonSourceTraits<T>::IsValid;
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT::NYTree