aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2025-06-02 20:33:26 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2025-06-02 20:54:26 +0300
commita88f04b45d4a0d7b7abe049ef422619ee1d6f930 (patch)
tree996c6ca22fa2f62c051ca501d338411df9a00edb
parentc509944b9a40a900dc9906bf7436efa8517d55a5 (diff)
downloadydb-a88f04b45d4a0d7b7abe049ef422619ee1d6f930.tar.gz
Intermediate changes
commit_hash:ec4f52d7356d9851e370b5086e73fc1c2299884f
-rw-r--r--yt/yt/core/ytree/polymorphic_yson_struct-inl.h45
-rw-r--r--yt/yt/core/ytree/polymorphic_yson_struct.h45
-rw-r--r--yt/yt/core/ytree/unittests/yson_struct_ut.cpp93
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