summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2024-02-06 18:23:16 +0300
committerrobot-piglet <[email protected]>2024-02-06 18:55:07 +0300
commit965d041b92ef23a4a6b47046e881bace557570c5 (patch)
tree1732fb1d68a77e09a7cec2bc7b2e44466aad9837
parent420c349c8367feade209024495eea1acfdd5a6be (diff)
Intermediate changes
-rw-r--r--library/cpp/timezone_conversion/ut/convert_ut.cpp17
-rw-r--r--yt/yt/client/object_client/helpers.cpp3
-rw-r--r--yt/yt/core/concurrency/config.h6
-rw-r--r--yt/yt/core/misc/config.h7
-rw-r--r--yt/yt/core/ytree/serialization_traits.h34
-rw-r--r--yt/yt/core/ytree/serialize-inl.h25
-rw-r--r--yt/yt/core/ytree/serialize.h13
-rw-r--r--yt/yt/core/ytree/unittests/yson_struct_ut.cpp325
-rw-r--r--yt/yt/core/ytree/yson_struct-inl.h37
-rw-r--r--yt/yt/core/ytree/yson_struct.h30
10 files changed, 251 insertions, 246 deletions
diff --git a/library/cpp/timezone_conversion/ut/convert_ut.cpp b/library/cpp/timezone_conversion/ut/convert_ut.cpp
index bbf9e9b8263..707b14ef607 100644
--- a/library/cpp/timezone_conversion/ut/convert_ut.cpp
+++ b/library/cpp/timezone_conversion/ut/convert_ut.cpp
@@ -202,3 +202,20 @@ TEST(TimeZoneConversion, TestBaikonur) {
ZonedTm(+5, false, 2019, 1, 11, 23, 55, 23),
ToCivilTime(TInstant::Seconds(1547232923), baikonur));
}
+
+TEST(TimeZoneConversion, DEVTOOLSSUPPORT_41537) {
+ // https://mm.icann.org/pipermail/tz-announce/2024-February/000081.html:
+ // Kazakhstan unifies on UTC+5 beginning 2024-03-01
+ // Asia/Almaty and Asia/Qostanay [...] will transition from UTC+6
+ // on 2024-03-01 at 00:00 to join the western portion
+
+ // > TZ=UTC date --date="2024-03-04 12:34:56" +%s
+ // 1709555696
+ const auto tmAfterTransition = TInstant::Seconds(1709555696);
+ for (const auto* tzName : {"Asia/Almaty", "Asia/Qostanay"}) {
+ const auto tz = GetTimeZone(tzName);
+ CompareCivilTimes(
+ ZonedTm(+5, false, 2024, 3, 4, 17, 34, 56),
+ ToCivilTime(tmAfterTransition, tz));
+ }
+}
diff --git a/yt/yt/client/object_client/helpers.cpp b/yt/yt/client/object_client/helpers.cpp
index 773fe000aca..ac03ca5c90f 100644
--- a/yt/yt/client/object_client/helpers.cpp
+++ b/yt/yt/client/object_client/helpers.cpp
@@ -121,7 +121,8 @@ bool IsVersionedType(EObjectType type)
type == EObjectType::Scion ||
type == EObjectType::ScionMap ||
type == EObjectType::ClusterProxyNode ||
- type == EObjectType::SequoiaMapNode;
+ type == EObjectType::SequoiaMapNode ||
+ type == EObjectType::Pipeline;
}
bool IsUserType(EObjectType type)
diff --git a/yt/yt/core/concurrency/config.h b/yt/yt/core/concurrency/config.h
index 3777d7a8d4b..2b1034d4ce8 100644
--- a/yt/yt/core/concurrency/config.h
+++ b/yt/yt/core/concurrency/config.h
@@ -66,6 +66,9 @@ public:
} // namespace NDetail
+ASSIGN_EXTERNAL_YSON_SERIALIZER(TPeriodicExecutorOptions, NDetail::TPeriodicExecutorOptionsSerializer);
+ASSIGN_EXTERNAL_YSON_SERIALIZER(TRetryingPeriodicExecutorOptions, NDetail::TRetryingPeriodicExecutorOptionsSerializer);
+
////////////////////////////////////////////////////////////////////////////////
class TThroughputThrottlerConfig
@@ -147,6 +150,3 @@ DEFINE_REFCOUNTED_TYPE(TPrefetchingThrottlerConfig)
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT::NConcurrency
-
-ASSIGN_EXTERNAL_YSON_SERIALIZER(NYT::NConcurrency::TPeriodicExecutorOptions, NYT::NConcurrency::NDetail::TPeriodicExecutorOptionsSerializer);
-ASSIGN_EXTERNAL_YSON_SERIALIZER(NYT::NConcurrency::TRetryingPeriodicExecutorOptions, NYT::NConcurrency::NDetail::TRetryingPeriodicExecutorOptionsSerializer);
diff --git a/yt/yt/core/misc/config.h b/yt/yt/core/misc/config.h
index 8170f2cf403..44f09124ebb 100644
--- a/yt/yt/core/misc/config.h
+++ b/yt/yt/core/misc/config.h
@@ -130,7 +130,6 @@ public:
static void Register(TRegistrar registrar);
};
-
////////////////////////////////////////////////////////////////////////////////
class TConstantBackoffOptionsSerializer
@@ -144,9 +143,9 @@ public:
} // namespace NDetail
+ASSIGN_EXTERNAL_YSON_SERIALIZER(TExponentialBackoffOptions, NDetail::TExponentialBackoffOptionsSerializer);
+ASSIGN_EXTERNAL_YSON_SERIALIZER(TConstantBackoffOptions, NDetail::TConstantBackoffOptionsSerializer);
+
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT
-
-ASSIGN_EXTERNAL_YSON_SERIALIZER(NYT::TExponentialBackoffOptions, NYT::NDetail::TExponentialBackoffOptionsSerializer);
-ASSIGN_EXTERNAL_YSON_SERIALIZER(NYT::TConstantBackoffOptions, NYT::NDetail::TConstantBackoffOptionsSerializer);
diff --git a/yt/yt/core/ytree/serialization_traits.h b/yt/yt/core/ytree/serialization_traits.h
deleted file mode 100644
index f73a3ba4751..00000000000
--- a/yt/yt/core/ytree/serialization_traits.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-
-namespace NYT::NYTree {
-
-////////////////////////////////////////////////////////////////////////////////
-
-//! Specialized trait is assumed to have alias for Serializable.
-//! Semanticallly TSerializer should have some way of (de-)serialization.
-template <class T>
-struct TSerializationTraits
-{
- static constexpr bool IsSerializable = false;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-template <class T>
-concept CSerializableByTraits = TSerializationTraits<T>::IsSerializable;
-
-////////////////////////////////////////////////////////////////////////////////
-
-//! NB: Template class specialization is only allowed in namespaces enclosing the original one,
-//! thus you can only use this macro inside namespaces "::", "::NYT", "::NYT::NYTree".
-#define ASSIGN_EXTERNAL_YSON_SERIALIZER(Type, SerializerType) \
- template <> \
- struct ::NYT::NYTree::TSerializationTraits<Type> \
- { \
- [[maybe_unused]] static constexpr bool IsSerializable = true; \
- using TSerializer = SerializerType; \
- }; \
-
-////////////////////////////////////////////////////////////////////////////////
-
-} // namespace NYT::NYTree
diff --git a/yt/yt/core/ytree/serialize-inl.h b/yt/yt/core/ytree/serialize-inl.h
index eea8f121b4f..dac0bce7473 100644
--- a/yt/yt/core/ytree/serialize-inl.h
+++ b/yt/yt/core/ytree/serialize-inl.h
@@ -462,15 +462,6 @@ void Serialize(const TStrongTypedef<T, TTag>& value, NYson::IYsonConsumer* consu
Serialize(value.Underlying(), consumer);
}
-template <class T>
- requires CSerializableByTraits<T>
-void Serialize(const T& value, NYson::IYsonConsumer* consumer)
-{
- using TSerializer = typename TSerializationTraits<T>::TSerializer;
- auto serializer = TSerializer::template CreateReadOnly<T, TSerializer>(value);
- Serialize(serializer, consumer);
-}
-
////////////////////////////////////////////////////////////////////////////////
template <class T>
@@ -661,22 +652,6 @@ void Deserialize(TStrongTypedef<T, TTag>& value, INodePtr node)
Deserialize(value.Underlying(), node);
}
-template <class T>
- requires CSerializableByTraits<T>
-void Deserialize(T& value, INodePtr node)
-{
- using TSerializer = typename TSerializationTraits<T>::TSerializer;
- auto serializer = TSerializer::template CreateWritable<T, TSerializer>(value);
- Deserialize(serializer, node);
-}
-
-template <class T>
- requires CSerializableByTraits<T>
-void Deserialize(T& value, NYson::TYsonPullParserCursor* cursor)
-{
- Deserialize(value, NYson::ExtractTo<NYTree::INodePtr>(cursor));
-}
-
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT::NYTree
diff --git a/yt/yt/core/ytree/serialize.h b/yt/yt/core/ytree/serialize.h
index 8b73fe812f7..e0631963b43 100644
--- a/yt/yt/core/ytree/serialize.h
+++ b/yt/yt/core/ytree/serialize.h
@@ -1,7 +1,6 @@
#pragma once
#include "public.h"
-#include "serialization_traits.h"
#include <yt/yt/core/yson/producer.h>
@@ -154,10 +153,6 @@ void Serialize(
template <class T, class TTag>
void Serialize(const TStrongTypedef<T, TTag>& value, NYson::IYsonConsumer* consumer);
-template <class T>
- requires CSerializableByTraits<T>
-void Serialize(const T& value, NYson::IYsonConsumer* consumer);
-
////////////////////////////////////////////////////////////////////////////////
template <class T>
@@ -263,14 +258,6 @@ void Deserialize(
template <class T, class TTag>
void Deserialize(TStrongTypedef<T, TTag>& value, INodePtr node);
-template <class T>
- requires CSerializableByTraits<T>
-void Deserialize(T& value, INodePtr node);
-
-template <class T>
- requires CSerializableByTraits<T>
-void Deserialize(T& value, NYson::TYsonPullParserCursor* cursor);
-
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT::NYTree
diff --git a/yt/yt/core/ytree/unittests/yson_struct_ut.cpp b/yt/yt/core/ytree/unittests/yson_struct_ut.cpp
index 027b367991e..ae8fea5526a 100644
--- a/yt/yt/core/ytree/unittests/yson_struct_ut.cpp
+++ b/yt/yt/core/ytree/unittests/yson_struct_ut.cpp
@@ -4,7 +4,6 @@
#include <yt/yt/core/ytree/ephemeral_node_factory.h>
#include <yt/yt/core/ytree/fluent.h>
-#include <yt/yt/core/ytree/serialization_traits.h>
#include <yt/yt/core/ytree/tree_builder.h>
#include <yt/yt/core/ytree/tree_visitor.h>
#include <yt/yt/core/ytree/ypath_client.h>
@@ -23,166 +22,6 @@ namespace NYT::NYTree {
namespace {
-struct TTestTraitConfig
-{
- int Field1;
- double Field2;
-};
-
-class TTestTraitConfigSerializer
- : public virtual TExternalizedYsonStruct
-{
-public:
- REGISTER_EXTERNALIZED_YSON_STRUCT(TTestTraitConfig, TTestTraitConfigSerializer);
-
- static void Register(TRegistrar registrar)
- {
- registrar.ExternalClassParameter("field1", &TThat::Field1);
- registrar.ExternalClassParameter("field2", &TThat::Field2);
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-struct TTestProcessorsTraitConfig
-{
- int Field1 = 11;
- int Field2 = 33;
-
- static inline bool PostprocessorCalled = false;
- static inline bool PreprocessorCalled = false;
-};
-
-class TTestProcessorsTraitConfigSerializer
- : public TExternalizedYsonStruct
-{
-public:
- REGISTER_EXTERNALIZED_YSON_STRUCT(TTestProcessorsTraitConfig, TTestProcessorsTraitConfigSerializer);
-
- static void Register(TRegistrar registrar)
- {
- registrar.ExternalClassParameter("field1", &TThat::Field1)
- .Default(42)
- .CheckThat([] (const int& field1) {
- return field1 % 2 == 0;
- });
- registrar.ExternalClassParameter("field2", &TThat::Field2)
- .Default(180);
-
- registrar.ExternalPreprocessor([] (TThat* podstruct) {
- //! NB(arkady-e1ppa): Preprocessor is called twice during deserialization.
- //! Same behavior is present for a normal YsonStructLite so I can't be
- //! bothered fixing this for my struct and introduce inconsistent behavior.
- // EXPECT_FALSE(TThat::PreprocessorCalled);
- EXPECT_FALSE(TThat::PostprocessorCalled);
- TThat::PreprocessorCalled = true;
- podstruct->Field2 = 88;
- });
-
- registrar.ExternalPostprocessor([] (TThat* podstruct) {
- EXPECT_TRUE(TThat::PreprocessorCalled);
- EXPECT_FALSE(TThat::PostprocessorCalled);
- TThat::PostprocessorCalled = true;
- podstruct->Field1 = 37;
- });
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-struct TTestDerivedPodConfig
- : public TTestTraitConfig
-{
- int Field3;
-};
-
-class TTestDerivedPodConfigSerializer
- : public TTestTraitConfigSerializer
-{
-public:
- REGISTER_DERIVED_EXTERNALIZED_YSON_STRUCT(TTestDerivedPodConfig, TTestDerivedPodConfigSerializer, (TTestTraitConfigSerializer));
-
- static void Register(TRegistrar registrar)
- {
- registrar.ExternalClassParameter("field_3", &TThat::Field3);
- }
-};
-
-struct TTestDoubleDerivedPodConfig
- : public TTestDerivedPodConfig
-{
- int Field4;
-};
-
-class TTestDoubleDerivedPodConfigSerializer
- : public TTestDerivedPodConfigSerializer
-{
-public:
- REGISTER_DERIVED_EXTERNALIZED_YSON_STRUCT(TTestDoubleDerivedPodConfig, TTestDoubleDerivedPodConfigSerializer, (TTestDerivedPodConfigSerializer));
-
- static void Register(TRegistrar registrar)
- {
- registrar.ExternalClassParameter("field_4", &TThat::Field4);
- }
-};
-
-struct TTestDerivedSecondBase
-{
- int Field5;
- int Field6;
-};
-
-class TTestDerivedSecondBaseSerializer
- : public virtual TExternalizedYsonStruct
-{
-public:
- REGISTER_EXTERNALIZED_YSON_STRUCT(TTestDerivedSecondBase, TTestDerivedSecondBaseSerializer);
-
- static void Register(TRegistrar registrar)
- {
- registrar.ExternalClassParameter("field_5", &TThat::Field5);
- registrar.ExternalClassParameter("field_6", &TThat::Field6);
- }
-};
-
-struct TTestDerivedTwoBasesConfig
- : public TTestDoubleDerivedPodConfig
- , public TTestDerivedSecondBase
-{ };
-
-class TTestDerivedTwoBasesConfigSerializer
- : public TTestDoubleDerivedPodConfigSerializer
- , public TTestDerivedSecondBaseSerializer
-{
-public:
- REGISTER_DERIVED_EXTERNALIZED_YSON_STRUCT(
- TTestDerivedTwoBasesConfig,
- TTestDerivedTwoBasesConfigSerializer,
- (TTestDoubleDerivedPodConfigSerializer)
- (TTestDerivedSecondBaseSerializer));
-
- static void Register(TRegistrar)
- { }
-};
-
-} // namespace
-
-ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestTraitConfig, TTestTraitConfigSerializer);
-
-ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestProcessorsTraitConfig, TTestProcessorsTraitConfigSerializer);
-
-ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestDerivedPodConfig, TTestDerivedPodConfigSerializer);
-
-ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestDoubleDerivedPodConfig, TTestDoubleDerivedPodConfigSerializer);
-
-ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestDerivedSecondBase, TTestDerivedSecondBaseSerializer);
-
-ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestDerivedTwoBasesConfig, TTestDerivedTwoBasesConfigSerializer);
-
-////////////////////////////////////////////////////////////////////////////////
-
-namespace {
-
using namespace NYson;
////////////////////////////////////////////////////////////////////////////////
@@ -1835,6 +1674,27 @@ TEST(TYsonStructTest, TestOptionalNoInit)
////////////////////////////////////////////////////////////////////////////////
+struct TTestTraitConfig
+{
+ int Field1;
+ double Field2;
+};
+
+class TTestTraitConfigSerializer
+ : public virtual TExternalizedYsonStruct
+{
+public:
+ REGISTER_EXTERNALIZED_YSON_STRUCT(TTestTraitConfig, TTestTraitConfigSerializer);
+
+ static void Register(TRegistrar registrar)
+ {
+ registrar.ExternalClassParameter("field1", &TThat::Field1);
+ registrar.ExternalClassParameter("field2", &TThat::Field2);
+ }
+};
+
+ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestTraitConfig, TTestTraitConfigSerializer);
+
class TFieldTester
: public NYT::NYTree::TYsonStructLite
{
@@ -1849,7 +1709,7 @@ public:
}
};
-TEST(TYsonStructTest, SerializableByTraitsField)
+TEST(TYsonStructTest, ExternalizedYsonStructField)
{
TFieldTester writer = {};
writer.Field = {55, 34,};
@@ -1866,6 +1726,54 @@ TEST(TYsonStructTest, SerializableByTraitsField)
EXPECT_EQ(reader.Field.Field2, 34);
}
+////////////////////////////////////////////////////////////////////////////////
+
+struct TTestProcessorsTraitConfig
+{
+ int Field1 = 11;
+ int Field2 = 33;
+
+ static inline bool PostprocessorCalled = false;
+ static inline bool PreprocessorCalled = false;
+};
+
+class TTestProcessorsTraitConfigSerializer
+ : public TExternalizedYsonStruct
+{
+public:
+ REGISTER_EXTERNALIZED_YSON_STRUCT(TTestProcessorsTraitConfig, TTestProcessorsTraitConfigSerializer);
+
+ static void Register(TRegistrar registrar)
+ {
+ registrar.ExternalClassParameter("field1", &TThat::Field1)
+ .Default(42)
+ .CheckThat([] (const int& field1) {
+ return field1 % 2 == 0;
+ });
+ registrar.ExternalClassParameter("field2", &TThat::Field2)
+ .Default(180);
+
+ registrar.ExternalPreprocessor([] (TThat* podstruct) {
+ //! NB(arkady-e1ppa): Preprocessor is called twice during deserialization.
+ //! Same behavior is present for a normal YsonStructLite so I can't be
+ //! bothered fixing this for my struct and introduce inconsistent behavior.
+ // EXPECT_FALSE(TThat::PreprocessorCalled);
+ EXPECT_FALSE(TThat::PostprocessorCalled);
+ TThat::PreprocessorCalled = true;
+ podstruct->Field2 = 88;
+ });
+
+ registrar.ExternalPostprocessor([] (TThat* podstruct) {
+ EXPECT_TRUE(TThat::PreprocessorCalled);
+ EXPECT_FALSE(TThat::PostprocessorCalled);
+ TThat::PostprocessorCalled = true;
+ podstruct->Field1 = 37;
+ });
+ }
+};
+
+ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestProcessorsTraitConfig, TTestProcessorsTraitConfigSerializer);
+
class TFieldTesterForProcessor
: public NYT::NYTree::TYsonStructLite
{
@@ -1880,7 +1788,7 @@ public:
}
};
-TEST(TYsonStructTest, SerializableByTraitsPostPreprocessors)
+TEST(TYsonStructTest, ExternalizedYsonStructPostPreprocessors)
{
TTestProcessorsTraitConfig::PreprocessorCalled = false;
TTestProcessorsTraitConfig::PostprocessorCalled = false;
@@ -1915,6 +1823,26 @@ TEST(TYsonStructTest, SerializableByTraitsPostPreprocessors)
EXPECT_EQ(reader.Field.Field2, 33);
}
+////////////////////////////////////////////////////////////////////////////////
+
+struct TTestDerivedPodConfig
+ : public TTestTraitConfig
+{
+ int Field3;
+};
+
+class TTestDerivedPodConfigSerializer
+ : public TTestTraitConfigSerializer
+{
+public:
+ REGISTER_DERIVED_EXTERNALIZED_YSON_STRUCT(TTestDerivedPodConfig, TTestDerivedPodConfigSerializer, (TTestTraitConfigSerializer));
+
+ static void Register(TRegistrar registrar)
+ {
+ registrar.ExternalClassParameter("field_3", &TThat::Field3);
+ }
+};
+
class TDerivedFieldTester
: public NYT::NYTree::TYsonStructLite
{
@@ -1929,7 +1857,9 @@ public:
}
};
-TEST(TYsonStructTest, SerializableByTraitsDerivedFromExternalized)
+ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestDerivedPodConfig, TTestDerivedPodConfigSerializer);
+
+TEST(TYsonStructTest, ExternalizedYsonStructDerivedFromExternalized)
{
TDerivedFieldTester writer = {};
writer.Field = {{55, 34}, 37};
@@ -1948,6 +1878,26 @@ TEST(TYsonStructTest, SerializableByTraitsDerivedFromExternalized)
EXPECT_EQ(reader.Field.Field3, 37);
}
+struct TTestDoubleDerivedPodConfig
+ : public TTestDerivedPodConfig
+{
+ int Field4;
+};
+
+class TTestDoubleDerivedPodConfigSerializer
+ : public TTestDerivedPodConfigSerializer
+{
+public:
+ REGISTER_DERIVED_EXTERNALIZED_YSON_STRUCT(TTestDoubleDerivedPodConfig, TTestDoubleDerivedPodConfigSerializer, (TTestDerivedPodConfigSerializer));
+
+ static void Register(TRegistrar registrar)
+ {
+ registrar.ExternalClassParameter("field_4", &TThat::Field4);
+ }
+};
+
+ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestDoubleDerivedPodConfig, TTestDoubleDerivedPodConfigSerializer);
+
class TDoubleDerivedFieldTester
: public NYT::NYTree::TYsonStructLite
{
@@ -1962,7 +1912,7 @@ public:
}
};
-TEST(TYsonStructTest, SerializableByTraitsDoubleDerivedFromExternalized)
+TEST(TYsonStructTest, ExternalizedYsonStructDoubleDerivedFromExternalized)
{
TDoubleDerivedFieldTester writer = {};
writer.Field = {{{55, 34}, 37}, 77};
@@ -1983,6 +1933,49 @@ TEST(TYsonStructTest, SerializableByTraitsDoubleDerivedFromExternalized)
EXPECT_EQ(reader.Field.Field4, 77);
}
+struct TTestDerivedSecondBase
+{
+ int Field5;
+ int Field6;
+};
+
+class TTestDerivedSecondBaseSerializer
+ : public virtual TExternalizedYsonStruct
+{
+public:
+ REGISTER_EXTERNALIZED_YSON_STRUCT(TTestDerivedSecondBase, TTestDerivedSecondBaseSerializer);
+
+ static void Register(TRegistrar registrar)
+ {
+ registrar.ExternalClassParameter("field_5", &TThat::Field5);
+ registrar.ExternalClassParameter("field_6", &TThat::Field6);
+ }
+};
+
+ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestDerivedSecondBase, TTestDerivedSecondBaseSerializer);
+
+struct TTestDerivedTwoBasesConfig
+ : public TTestDoubleDerivedPodConfig
+ , public TTestDerivedSecondBase
+{ };
+
+class TTestDerivedTwoBasesConfigSerializer
+ : public TTestDoubleDerivedPodConfigSerializer
+ , public TTestDerivedSecondBaseSerializer
+{
+public:
+ REGISTER_DERIVED_EXTERNALIZED_YSON_STRUCT(
+ TTestDerivedTwoBasesConfig,
+ TTestDerivedTwoBasesConfigSerializer,
+ (TTestDoubleDerivedPodConfigSerializer)
+ (TTestDerivedSecondBaseSerializer));
+
+ static void Register(TRegistrar)
+ { }
+};
+
+ASSIGN_EXTERNAL_YSON_SERIALIZER(TTestDerivedTwoBasesConfig, TTestDerivedTwoBasesConfigSerializer);
+
class TTwoBasesFieldTester
: public NYT::NYTree::TYsonStructLite
{
@@ -1997,7 +1990,7 @@ public:
}
};
-TEST(TYsonStructTest, SerializableByTraitsDerivedFromTwoExternalizedBases)
+TEST(TYsonStructTest, ExternalizedYsonStructDerivedFromTwoExternalizedBases)
{
TTwoBasesFieldTester writer = {};
writer.Field = {{{{55, 34}, 37}, 77}, {7, 8}};
diff --git a/yt/yt/core/ytree/yson_struct-inl.h b/yt/yt/core/ytree/yson_struct-inl.h
index 60ea056feb4..656b0c5e60b 100644
--- a/yt/yt/core/ytree/yson_struct-inl.h
+++ b/yt/yt/core/ytree/yson_struct-inl.h
@@ -257,6 +257,31 @@ TYsonStructRegistrar<TStruct>::operator TYsonStructRegistrar<TBase>()
////////////////////////////////////////////////////////////////////////////////
template <class T>
+ requires CExternallySerializable<T>
+void Serialize(const T& value, NYson::IYsonConsumer* consumer)
+{
+ using TSerializer = typename TGetExternalizedYsonStructTraits<T>::TExternalSerializer;
+ auto serializer = TSerializer::template CreateReadOnly<T, TSerializer>(value);
+ Serialize(serializer, consumer);
+}
+
+template <class T>
+ requires CExternallySerializable<T>
+void Deserialize(T& value, INodePtr node)
+{
+ using TSerializer = typename TGetExternalizedYsonStructTraits<T>::TExternalSerializer;
+ auto serializer = TSerializer::template CreateWritable<T, TSerializer>(value);
+ Deserialize(serializer, node);
+}
+
+template <class T>
+ requires CExternallySerializable<T>
+void Deserialize(T& value, NYson::TYsonPullParserCursor* cursor)
+{
+ Deserialize(value, NYson::ExtractTo<NYTree::INodePtr>(cursor));
+}
+
+template <class T>
TIntrusivePtr<T> CloneYsonStruct(const TIntrusivePtr<const T>& obj)
{
if (!obj) {
@@ -381,6 +406,7 @@ void UpdateYsonStructField(TIntrusivePtr<TDst>& dst, const TIntrusivePtr<TSrc>&
#undef DEFINE_YSON_STRUCT_LITE
#undef REGISTER_EXTERNALIZED_YSON_STRUCT
#undef REGISTER_DERIVED_EXTERNALIZED_YSON_STRUCT
+#undef ASSIGN_EXTERNAL_YSON_SERIALIZER
#define YSON_STRUCT_IMPL__DECLARE_ALIASES(TStruct) \
private: \
@@ -523,6 +549,17 @@ public: \
} \
YSON_STRUCT_EXTERNAL_SERIALIZER_IMPL__DECLARE_ALIASES(TStruct, TSerializer) \
+#define ASSIGN_EXTERNAL_YSON_SERIALIZER(TStruct, TSerializer) \
+ [[maybe_unused]] constexpr auto GetExternalizedYsonStructTraits(TStruct) \
+ { \
+ struct [[maybe_unused]] TTraits { \
+ using TExternalSerializer = TSerializer; \
+ }; \
+ static_assert(std::derived_from<TTraits::TExternalSerializer, ::NYT::NYTree::TExternalizedYsonStruct>, "External serializer must be derived from TExternalizedYsonStruct"); \
+ return TTraits{}; \
+ } \
+ static_assert(::NYT::NYTree::CExternallySerializable<TStruct>, "You must write this macro in the namespace containing TStruct")
+
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT::NYTree
diff --git a/yt/yt/core/ytree/yson_struct.h b/yt/yt/core/ytree/yson_struct.h
index a3cf015a89b..6c815600aac 100644
--- a/yt/yt/core/ytree/yson_struct.h
+++ b/yt/yt/core/ytree/yson_struct.h
@@ -283,6 +283,21 @@ 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);
@@ -296,6 +311,16 @@ void Deserialize(TYsonStructBase& value, INodePtr node);
void Deserialize(TYsonStructBase& value, NYson::TYsonPullParserCursor* cursor);
template <class T>
+ requires 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 <class T>
TIntrusivePtr<T> UpdateYsonStruct(
const TIntrusivePtr<T>& obj,
const INodePtr& patch);
@@ -352,6 +377,11 @@ void UpdateYsonStructField(TIntrusivePtr<TDst>& dst, const TIntrusivePtr<TSrc>&
#define REGISTER_DERIVED_EXTERNALIZED_YSON_STRUCT(TStruct, TSerializer, TBases)
+//! Assign TSerializer to a TStruct so it can be found during (de-) serialization.
+//! NB(arkady-e1ppa): This macro must be used in the same namespace as the one TStruct is in.
+//! Otherwise ADL will not be able to find proper overload.
+#define ASSIGN_EXTERNAL_YSON_SERIALIZER(TStruct, TSerializer)
+
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT::NYTree