diff options
author | robot-piglet <[email protected]> | 2024-02-06 18:23:16 +0300 |
---|---|---|
committer | robot-piglet <[email protected]> | 2024-02-06 18:55:07 +0300 |
commit | 965d041b92ef23a4a6b47046e881bace557570c5 (patch) | |
tree | 1732fb1d68a77e09a7cec2bc7b2e44466aad9837 | |
parent | 420c349c8367feade209024495eea1acfdd5a6be (diff) |
Intermediate changes
-rw-r--r-- | library/cpp/timezone_conversion/ut/convert_ut.cpp | 17 | ||||
-rw-r--r-- | yt/yt/client/object_client/helpers.cpp | 3 | ||||
-rw-r--r-- | yt/yt/core/concurrency/config.h | 6 | ||||
-rw-r--r-- | yt/yt/core/misc/config.h | 7 | ||||
-rw-r--r-- | yt/yt/core/ytree/serialization_traits.h | 34 | ||||
-rw-r--r-- | yt/yt/core/ytree/serialize-inl.h | 25 | ||||
-rw-r--r-- | yt/yt/core/ytree/serialize.h | 13 | ||||
-rw-r--r-- | yt/yt/core/ytree/unittests/yson_struct_ut.cpp | 325 | ||||
-rw-r--r-- | yt/yt/core/ytree/yson_struct-inl.h | 37 | ||||
-rw-r--r-- | yt/yt/core/ytree/yson_struct.h | 30 |
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 |