diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2025-06-02 20:33:26 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2025-06-02 20:54:26 +0300 |
commit | a88f04b45d4a0d7b7abe049ef422619ee1d6f930 (patch) | |
tree | 996c6ca22fa2f62c051ca501d338411df9a00edb | |
parent | c509944b9a40a900dc9906bf7436efa8517d55a5 (diff) | |
download | ydb-a88f04b45d4a0d7b7abe049ef422619ee1d6f930.tar.gz |
Intermediate changes
commit_hash:ec4f52d7356d9851e370b5086e73fc1c2299884f
-rw-r--r-- | yt/yt/core/ytree/polymorphic_yson_struct-inl.h | 45 | ||||
-rw-r--r-- | yt/yt/core/ytree/polymorphic_yson_struct.h | 45 | ||||
-rw-r--r-- | yt/yt/core/ytree/unittests/yson_struct_ut.cpp | 93 |
3 files changed, 170 insertions, 13 deletions
diff --git a/yt/yt/core/ytree/polymorphic_yson_struct-inl.h b/yt/yt/core/ytree/polymorphic_yson_struct-inl.h index b9ea6afaf45..ed0352c2438 100644 --- a/yt/yt/core/ytree/polymorphic_yson_struct-inl.h +++ b/yt/yt/core/ytree/polymorphic_yson_struct-inl.h @@ -18,10 +18,10 @@ TIntrusivePtr<TBase> TMappingLeaf<TEnum, Value, TBase, TDerived>::CreateInstance return New<TDerived>(); } -template <class TEnum, TEnum BaseValue, CYsonStructDerived TBase, TEnum... Values, class... TDerived> +template <class TEnum, TEnum... DefaultValue, TEnum BaseValue, CYsonStructDerived TBase, TEnum... Values, class... TDerived> requires (CHierarchy<TBase, TDerived...>) TIntrusivePtr<TBase> -TPolymorphicMapping<TEnum, TLeafTag<BaseValue, TBase>, TLeafTag<Values, TDerived>...>:: +TPolymorphicMapping<TEnum, TOptionalValue<TEnum, DefaultValue...>, TLeafTag<BaseValue, TBase>, TLeafTag<Values, TDerived>...>:: CreateInstance(TEnum value) { if (value == BaseValue) { @@ -84,10 +84,12 @@ void TPolymorphicYsonStruct<TMapping>::Load( auto key = map->FindChildValue<TKey>("type"); THROW_ERROR_EXCEPTION_UNLESS( - key.has_value(), - "Concrete type must be specified! Use \"type\": \"concrete_type\""); + key.has_value() || DefaultType_, + "Concrete type must be specified! Use \"type\": \"concrete_type\" or specify default type"); - auto type = *key; + auto type = key + ? *key + : *DefaultType_; if (!Storage_ || HeldType_ != type) { // NB: We will try to merge configs if types match. HeldType_ = type; @@ -207,7 +209,9 @@ void Deserialize(TPolymorphicYsonStruct<TMapping>& value, TSource source) //////////////////////////////////////////////////////////////////////////////// #undef DEFINE_POLYMORPHIC_YSON_STRUCT +#undef DEFINE_POLYMORPHIC_YSON_STRUCT_WITH_DEFAULT #undef DEFINE_POLYMORPHIC_YSON_STRUCT_FOR_ENUM +#undef DEFINE_POLYMORPHIC_YSON_STRUCT_FOR_ENUM_WITH_DEFAULT #define POLYMORPHIC_YSON_STRUCT_IMPL__GET_ENUM_SEQ_ELEM(item) \ PP_LEFT_PARENTHESIS PP_ELEMENT(item, 0) PP_RIGHT_PARENTHESIS @@ -231,11 +235,21 @@ void Deserialize(TPolymorphicYsonStruct<TMapping>& value, TSource source) PP_COMMA() ::NYT::NYTree::NDetail::TLeafTag<EType:: PP_ELEMENT(item, 0), PP_ELEMENT(item, 1)> #define POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_CLASS(Struct, seq) \ - using TMapping = ::NYT::NYTree::TPolymorphicEnumMapping<EType PP_FOR_EACH(POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_LEAF_FROM_ETYPE, seq)> + using TMapping = ::NYT::NYTree::TPolymorphicEnumMapping< \ + EType, \ + ::NYT::NYTree::NDetail::TOptionalValue<EType> \ + PP_FOR_EACH(POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_LEAF_FROM_ETYPE, seq) \ + > + +#define POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_CLASS_WITH_DEFAULT(Struct, default, seq) \ + using TMapping = ::NYT::NYTree::TPolymorphicEnumMapping< \ + EType, \ + ::NYT::NYTree::NDetail::TOptionalValue<EType, default> \ + PP_FOR_EACH(POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_LEAF_FROM_ETYPE, seq) \ + > #define DEFINE_POLYMORPHIC_YSON_STRUCT(name, seq) \ namespace NPolymorphicYsonStructFor##name { \ - \ POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_ENUM(seq); \ POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_CLASS(name, seq); \ } /*NPolymorphicYsonStructFor##name*/ \ @@ -243,6 +257,15 @@ using POLYMORPHIC_YSON_STRUCT_IMPL__ENUM_NAME(name) = NPolymorphicYsonStructFor# using T##name = ::NYT::NYTree::TPolymorphicYsonStruct<NPolymorphicYsonStructFor##name::TMapping>; \ static_assert(true) +#define DEFINE_POLYMORPHIC_YSON_STRUCT_WITH_DEFAULT(name, default, seq) \ +namespace NPolymorphicYsonStructFor##name { \ + POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_ENUM(seq); \ + POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_CLASS_WITH_DEFAULT(name, EType::default, seq); \ +} /*NPolymorphicYsonStructFor##name*/ \ +using POLYMORPHIC_YSON_STRUCT_IMPL__ENUM_NAME(name) = NPolymorphicYsonStructFor##name::EType; \ +using T##name = ::NYT::NYTree::TPolymorphicYsonStruct<NPolymorphicYsonStructFor##name::TMapping>; \ +static_assert(true) + #define DEFINE_POLYMORPHIC_YSON_STRUCT_FOR_ENUM(name, enum, seq) \ namespace NPolymorphicYsonStructFor##name { \ POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_ENUM_ALIAS(enum); \ @@ -251,6 +274,14 @@ namespace NPolymorphicYsonStructFor##name { \ using T##name = ::NYT::NYTree::TPolymorphicYsonStruct<NPolymorphicYsonStructFor##name::TMapping>; \ static_assert(true) +#define DEFINE_POLYMORPHIC_YSON_STRUCT_FOR_ENUM_WITH_DEFAULT(name, enum, default, seq) \ +namespace NPolymorphicYsonStructFor##name { \ + POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_ENUM_ALIAS(enum); \ + POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_CLASS_WITH_DEFAULT(name, EType::default, seq); \ +} /*NPolymorphicYsonStructFor##name*/ \ +using T##name = ::NYT::NYTree::TPolymorphicYsonStruct<NPolymorphicYsonStructFor##name::TMapping>; \ +static_assert(true) + //////////////////////////////////////////////////////////////////////////////// } // namespace NYT::NYTree diff --git a/yt/yt/core/ytree/polymorphic_yson_struct.h b/yt/yt/core/ytree/polymorphic_yson_struct.h index ee4732fa8e7..50c4b206380 100644 --- a/yt/yt/core/ytree/polymorphic_yson_struct.h +++ b/yt/yt/core/ytree/polymorphic_yson_struct.h @@ -59,12 +59,27 @@ struct TMappingLeaf friend TDerived EnumToDerivedMethod(TFactoryTag<Value>, TMappingLeaf*); }; -template <class TEnum, class... TLeafTags> +template <class T, T... Value> +struct TOptionalValue; + +template <class T> +struct TOptionalValue<T> +{ + static constexpr std::optional<T> OptionalValue; +}; + +template <class T, T Value> +struct TOptionalValue<T, Value> +{ + static constexpr std::optional<T> OptionalValue = Value; +}; + +template <class TEnum, class TDefaultEnumValue, class... TLeafTags> struct TPolymorphicMapping; -template <class TEnum, TEnum BaseValue, CYsonStructDerived TBase, TEnum... Values, class... TDerived> +template <class TEnum, TEnum... DefaultValue, TEnum BaseValue, CYsonStructDerived TBase, TEnum... Values, class... TDerived> requires (CHierarchy<TBase, TDerived...>) -struct TPolymorphicMapping<TEnum, TLeafTag<BaseValue, TBase>, TLeafTag<Values, TDerived>...> +struct TPolymorphicMapping<TEnum, TOptionalValue<TEnum, DefaultValue...>, TLeafTag<BaseValue, TBase>, TLeafTag<Values, TDerived>...> : public TMappingLeaf<TEnum, BaseValue, TBase, TBase> , public TMappingLeaf<TEnum, Values, TBase, TDerived>... { @@ -77,6 +92,8 @@ struct TPolymorphicMapping<TEnum, TLeafTag<BaseValue, TBase>, TLeafTag<Values, T using TKey = TEnum; using TBaseClass = TBase; + static constexpr auto DefaultEnumValue = TOptionalValue<TEnum, DefaultValue...>::OptionalValue; + static TIntrusivePtr<TBase> CreateInstance(TEnum value); }; @@ -84,7 +101,7 @@ struct TPolymorphicMapping<TEnum, TLeafTag<BaseValue, TBase>, TLeafTag<Values, T template <class T> constexpr bool IsMapping = requires (T t) { - [] <class TEnum, class... TLeafTags> (TPolymorphicMapping<TEnum, TLeafTags...>) { + [] <class TEnum, class TDefaultEnumValue, class... TLeafTags> (TPolymorphicMapping<TEnum, TDefaultEnumValue, TLeafTags...>) { } (t); }; @@ -97,8 +114,8 @@ constexpr bool IsMapping = requires (T t) { template <class TBase, class... TDerived> concept CHierarchy = NDetail::CHierarchy<TBase, TDerived...>; -template <class TEnum, class... TLeafTags> -using TPolymorphicEnumMapping = NDetail::TPolymorphicMapping<TEnum, TLeafTags...>; +template <class TEnum, class TDefaultEnumValue, class... TLeafTags> +using TPolymorphicEnumMapping = NDetail::TPolymorphicMapping<TEnum, TDefaultEnumValue, TLeafTags...>; template <class T> concept CPolymorphicEnumMapping = NDetail::IsMapping<T>; @@ -182,6 +199,8 @@ private: INodePtr SerializedStorage_; TKey HeldType_; + static constexpr auto DefaultType_ = TMapping::DefaultEnumValue; + void PrepareInstance(INodePtr& node); }; @@ -202,6 +221,13 @@ void Deserialize(TPolymorphicYsonStruct<TMapping>& value, TSource source); ((Derived1) (TDerivedStruct1)) ((Derived2) (TDerivedStruct2)) ); + or + DEFINE_POLYMORPHIC_YSON_STRUCT_WITH_DEFAULT(Struct, Derived1, + ((Base) (TBaseStruct)) + ((Derived1) (TDerivedStruct1)) + ((Derived2) (TDerivedStruct2)) + ); + .....TypeName.....ActualTypeName Macro generates two names: @@ -211,6 +237,7 @@ void Deserialize(TPolymorphicYsonStruct<TMapping>& value, TSource source); hierarchy members. They are keys in serialization. */ #define DEFINE_POLYMORPHIC_YSON_STRUCT(name, seq) +#define DEFINE_POLYMORPHIC_YSON_STRUCT_WITH_DEFAULT(name, default, seq) //! Usage: /* @@ -223,6 +250,11 @@ void Deserialize(TPolymorphicYsonStruct<TMapping>& value, TSource source); ((Pear) (TPearClass)) ((Apple) (TAppleClass)) ) + or + DEFINE_POLYMORPHIC_YSON_STRUCT_FOR_ENUM_WITH_DEFAULT(Struct, EMyEnum, Apple, + ((Pear) (TPearClass)) + ((Apple) (TAppleClass)) + ) // NB(arkady-e1ppa): enum names in the list must be unqualified! E.g. @@ -234,6 +266,7 @@ void Deserialize(TPolymorphicYsonStruct<TMapping>& value, TSource source); Will not compile */ #define DEFINE_POLYMORPHIC_YSON_STRUCT_FOR_ENUM(name, enum, seq) +#define DEFINE_POLYMORPHIC_YSON_STRUCT_FOR_ENUM_WITH_DEFAULT(name, enum, default, seq) //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/core/ytree/unittests/yson_struct_ut.cpp b/yt/yt/core/ytree/unittests/yson_struct_ut.cpp index aaed3fd853b..8e708cc2ed0 100644 --- a/yt/yt/core/ytree/unittests/yson_struct_ut.cpp +++ b/yt/yt/core/ytree/unittests/yson_struct_ut.cpp @@ -3459,6 +3459,99 @@ TEST(TYsonStructTest, TestPolymorphicYsonStructMergeIfPossible) EXPECT_EQ(drv1Ptr->Field1, 18); } +DEFINE_POLYMORPHIC_YSON_STRUCT_WITH_DEFAULT(MyPolyDefault, Drv1, + ((Base) (TPolyBase)) + ((Drv1) (TPolyDerived1)) + ((Drv2) (TPolyDerived2)) +); + +TEST(TYsonStructTest, TestPolymorphicYsonStructDefault) +{ + TMyPolyDefault poly; + + auto node = BuildYsonNodeFluently() + .BeginMap() + .Item("base_field").Value(11) + .Item("field1").Value(123) + .EndMap(); + + Deserialize(poly, node->AsMap()); + EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultType::Drv1); + + auto drv1Ptr = poly.TryGetConcrete<TPolyDerived1>(); + EXPECT_TRUE(drv1Ptr.operator bool()); + EXPECT_EQ(drv1Ptr->BaseField, 11); + EXPECT_EQ(drv1Ptr->Field1, 123); + + node = BuildYsonNodeFluently() + .BeginMap() + .Item("type").Value("drv2") + .Item("base_field").Value(14) + .Item("field2").Value(111) + .EndMap(); + + Deserialize(poly, node->AsMap()); + EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultType::Drv2); + + node = BuildYsonNodeFluently() + .BeginMap() + .Item("base_field").Value(11) + .Item("field1").Value(123) + .EndMap(); + + Deserialize(poly, node->AsMap()); + EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultType::Drv1); +} + +DEFINE_ENUM(EMyPolyDefaultEnum, + (Base) + (Drv1) + (Drv2) +); + +DEFINE_POLYMORPHIC_YSON_STRUCT_FOR_ENUM_WITH_DEFAULT(MyPolyDefaultEnum, EMyPolyDefaultEnum, Base, + ((Base) (TPolyBase)) + ((Drv1) (TPolyDerived1)) + ((Drv2) (TPolyDerived2)) +); + +TEST(TYsonStructTest, TestPolymorphicYsonStructDefaultEnum) +{ + TMyPolyDefaultEnum poly; + + auto node = BuildYsonNodeFluently() + .BeginMap() + .Item("base_field").Value(11) + .Item("field1").Value(123) + .EndMap(); + + Deserialize(poly, node->AsMap()); + EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultEnum::Base); + + auto basePtr = poly.TryGetConcrete<TPolyBase>(); + EXPECT_TRUE(basePtr.operator bool()); + EXPECT_EQ(basePtr->BaseField, 11); + + node = BuildYsonNodeFluently() + .BeginMap() + .Item("type").Value("drv1") + .Item("base_field").Value(14) + .Item("field1").Value(111) + .EndMap(); + + Deserialize(poly, node->AsMap()); + EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultEnum::Drv1); + + node = BuildYsonNodeFluently() + .BeginMap() + .Item("base_field").Value(11) + .Item("field1").Value(123) + .EndMap(); + + Deserialize(poly, node->AsMap()); + EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultEnum::Base); +} + //////////////////////////////////////////////////////////////////////////////// struct TPolyHolder |