@@ -10,48 +10,44 @@ namespace NYT::NYTree {
10
10
11
11
namespace NDetail {
12
12
13
- template <class TEnum >
14
- requires TEnumTraits<TEnum>::IsEnum
15
- template <class TBase , class TDerived >
16
- TIntrusivePtr<TBase> TEnumTraitsExt<TEnum>::ConcreteFactory()
13
+ template <class TEnum , TEnum Value, class TBase , class TDerived >
14
+ TIntrusivePtr<TBase> TMappingLeaf<TEnum, Value, TBase, TDerived>::CreateInstance()
17
15
{
18
16
return New<TDerived>();
19
17
}
20
18
21
- template <class TEnum >
22
- requires TEnumTraits<TEnum>::IsEnum
23
- template <class TBase , class ... TDerived>
24
- TInstanceFactory<TEnum, TBase> TEnumTraitsExt<TEnum>::MakeFactory()
19
+ template <class TEnum , TEnum BaseValue, CYsonStructDerived TBase, TEnum... Values, class ... TDerived>
20
+ requires (CHierarchy<TBase, TDerived...>)
21
+ TIntrusivePtr<TBase>
22
+ TPolymorphicMapping<TEnum, TLeafTag<BaseValue, TBase>, TLeafTag<Values, TDerived>...>::
23
+ CreateInstance (TEnum value)
25
24
{
26
- static constexpr auto keys = TTraits::GetDomainValues ();
27
- using TTuple = std::tuple<TBase, TDerived...>;
25
+ if (value == BaseValue) {
26
+ return TLeaf<BaseValue, TBase>::CreateInstance ();
27
+ }
28
28
29
- TInstanceFactory<TEnum, TBase> mapping ;
29
+ TIntrusivePtr< TBase> ret ;
30
30
31
- [&] <size_t ... Idx> (std::index_sequence<Idx...>) {
32
- ([&] {
33
- mapping[keys[Idx]] = &TEnumTraitsExt<TEnum>::ConcreteFactory<TBase, std::tuple_element_t <Idx, TTuple>>;
34
- } (), ...);
35
- } (std::make_index_sequence<sizeof ...(TDerived) + 1 >());
31
+ ([&ret, value] {
32
+ if (value == Values) {
33
+ ret = TLeaf<Values, TDerived>::CreateInstance ();
34
+ return false ;
35
+ }
36
+ return true ;
37
+ } () && ...);
36
38
37
- return mapping;
38
- }
39
-
40
- // //////////////////////////////////////////////////////////////////////////////
41
-
42
- template <class TEnum , class TB , class ... TD>
43
- TIntrusivePtr<TB> TPolymorphicEnumMapping<TEnum, TB, TD...>::MakeInstance(TEnum e)
44
- {
45
- static auto factory =
46
- TEnumTraitsExt<TEnum>::template MakeFactory<TB, TD...>();
47
-
48
- return factory[e]();
39
+ return ret;
49
40
}
50
41
51
42
} // namespace NDetail
52
43
53
44
// //////////////////////////////////////////////////////////////////////////////
54
45
46
+ template <CPolymorphicEnumMapping TMapping>
47
+ TPolymorphicYsonStruct<TMapping>::TPolymorphicYsonStruct(TKey key)
48
+ : TPolymorphicYsonStruct(key, TMapping::CreateInstance(key))
49
+ { }
50
+
55
51
template <CPolymorphicEnumMapping TMapping>
56
52
TPolymorphicYsonStruct<TMapping>::TPolymorphicYsonStruct(TKey key, TIntrusivePtr<TBase> ptr) noexcept
57
53
: Storage_(std::move(ptr))
@@ -77,6 +73,11 @@ void TPolymorphicYsonStruct<TMapping>::Load(
77
73
// parse (unless we want to slice which we don't).
78
74
IMapNodePtr map = TTraits::AsNode (source)->AsMap ();
79
75
76
+ if (!map || map->GetChildCount () == 0 ) {
77
+ // Empty struct.
78
+ return ;
79
+ }
80
+
80
81
auto key = map->FindChildValue <TKey>(" type" );
81
82
THROW_ERROR_EXCEPTION_UNLESS (
82
83
key.has_value (),
@@ -86,7 +87,7 @@ void TPolymorphicYsonStruct<TMapping>::Load(
86
87
if (!Storage_ || HeldType_ != type) {
87
88
// NB: We will try to merge configs if types match.
88
89
HeldType_ = type;
89
- Storage_ = TMapping::MakeInstance (HeldType_);
90
+ Storage_ = TMapping::CreateInstance (HeldType_);
90
91
}
91
92
92
93
if (recursiveUnrecognizedStrategy) {
@@ -97,33 +98,62 @@ void TPolymorphicYsonStruct<TMapping>::Load(
97
98
// therefore we must delete it prior to |Load| call.
98
99
map->RemoveChild (" type" );
99
100
Storage_->Load (map, postprocess, setDefaults, path);
101
+
102
+ // NB(arkady-e1ppa): We must not actually remove contents of the node as a postcondition
103
+ // since it mutates serialized data which might be used for config validation.
104
+ map->AddChild (" type" , ConvertToNode (HeldType_));
100
105
}
101
106
102
107
template <CPolymorphicEnumMapping TMapping>
103
108
void TPolymorphicYsonStruct<TMapping>::Save(NYson::IYsonConsumer* consumer) const
104
109
{
105
110
consumer->OnBeginMap ();
106
111
107
- consumer->OnKeyedItem (" type" );
108
- consumer->OnStringScalar (FormatEnum (HeldType_));
112
+ if (Storage_) {
113
+ consumer->OnKeyedItem (" type" );
114
+ consumer->OnStringScalar (FormatEnum (HeldType_));
115
+
116
+ Storage_->SaveAsMapFragment (consumer);
117
+ }
109
118
110
- Storage_->SaveAsMapFragment (consumer);
111
119
consumer->OnEndMap ();
112
120
}
113
121
114
122
template <CPolymorphicEnumMapping TMapping>
115
- template <std::derived_from<typename TMapping::TBase > TConcrete>
123
+ template <std::derived_from<typename TMapping::TBaseClass > TConcrete>
116
124
TIntrusivePtr<TConcrete> TPolymorphicYsonStruct<TMapping>::TryGetConcrete() const
117
125
{
118
126
return DynamicPointerCast<TConcrete>(Storage_);
119
127
}
120
128
129
+ template <CPolymorphicEnumMapping TMapping>
130
+ template <typename TMapping::TKey Value>
131
+ TIntrusivePtr<typename TMapping::template TDerivedToEnum<Value>> TPolymorphicYsonStruct<TMapping>::TryGetConcrete() const
132
+ {
133
+ if (Value != HeldType_) {
134
+ return {};
135
+ }
136
+ return TryGetConcrete<typename TMapping::template TDerivedToEnum<Value>>();
137
+ }
138
+
121
139
template <CPolymorphicEnumMapping TMapping>
122
140
typename TPolymorphicYsonStruct<TMapping>::TKey TPolymorphicYsonStruct<TMapping>::GetCurrentType() const
123
141
{
124
142
return HeldType_;
125
143
}
126
144
145
+ template <CPolymorphicEnumMapping TMapping>
146
+ typename TPolymorphicYsonStruct<TMapping>::TBase* TPolymorphicYsonStruct<TMapping>::operator ->()
147
+ {
148
+ return Storage_.Get ();
149
+ }
150
+
151
+ template <CPolymorphicEnumMapping TMapping>
152
+ const typename TPolymorphicYsonStruct<TMapping>::TBase* TPolymorphicYsonStruct<TMapping>::operator ->() const
153
+ {
154
+ return Storage_.Get ();
155
+ }
156
+
127
157
// //////////////////////////////////////////////////////////////////////////////
128
158
129
159
template <CPolymorphicEnumMapping TMapping>
@@ -141,6 +171,7 @@ void Deserialize(TPolymorphicYsonStruct<TMapping>& value, TSource source)
141
171
// //////////////////////////////////////////////////////////////////////////////
142
172
143
173
#undef DEFINE_POLYMORPHIC_YSON_STRUCT
174
+ #undef DEFINE_POLYMORPHIC_YSON_STRUCT_FOR_ENUM
144
175
145
176
#define POLYMORPHIC_YSON_STRUCT_IMPL__GET_ENUM_SEQ_ELEM (item ) \
146
177
PP_LEFT_PARENTHESIS PP_ELEMENT (item, 0 ) PP_RIGHT_PARENTHESIS
@@ -151,23 +182,37 @@ void Deserialize(TPolymorphicYsonStruct<TMapping>& value, TSource source)
151
182
#define POLYMORPHIC_YSON_STRUCT_IMPL__ENUM_NAME (Struct ) \
152
183
E##Struct##Type
153
184
154
- #define POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_ENUM (Struct, seq ) \
185
+ #define POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_ENUM (seq ) \
155
186
DEFINE_ENUM (EType, POLYMORPHIC_YSON_STRUCT_IMPL__GET_ENUM_SEQ(seq))
156
187
188
+ #define POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_ENUM_ALIAS (EnumName ) \
189
+ using EType = EnumName;
190
+
157
191
#define POLYMORPHIC_YSON_STRUCT_IMPL__GET_CLASS_ELEM (item ) \
158
192
PP_COMMA () PP_ELEMENT(item, 1 )
159
193
194
+ #define POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_LEAF_FROM_ETYPE (item ) \
195
+ PP_COMMA () ::NYT::NYTree::NDetail::TLeafTag<EType:: PP_ELEMENT(item, 0 ), PP_ELEMENT(item, 1 )>
196
+
160
197
#define POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_CLASS (Struct, seq ) \
161
- using TMapping = TPolymorphicEnumMapping<EType PP_FOR_EACH (POLYMORPHIC_YSON_STRUCT_IMPL__GET_CLASS_ELEM , seq)>
198
+ using TMapping = ::NYT::NYTree:: TPolymorphicEnumMapping<EType PP_FOR_EACH (POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_LEAF_FROM_ETYPE , seq)>
162
199
163
200
#define DEFINE_POLYMORPHIC_YSON_STRUCT (name, seq ) \
164
201
namespace NPolymorphicYsonStructFor ##name { \
165
202
\
166
- POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_ENUM (name, seq); \
203
+ POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_ENUM (seq); \
167
204
POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_CLASS (name, seq); \
168
205
} /* NPolymorphicYsonStructFor##name*/ \
169
206
using POLYMORPHIC_YSON_STRUCT_IMPL__ENUM_NAME (name) = NPolymorphicYsonStructFor##name::EType; \
170
- using T##name = TPolymorphicYsonStruct<NPolymorphicYsonStructFor##name::TMapping>; \
207
+ using T##name = ::NYT::NYTree::TPolymorphicYsonStruct<NPolymorphicYsonStructFor##name::TMapping>; \
208
+ static_assert (true )
209
+
210
+ #define DEFINE_POLYMORPHIC_YSON_STRUCT_FOR_ENUM (name, enum, seq ) \
211
+ namespace NPolymorphicYsonStructFor ##name { \
212
+ POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_ENUM_ALIAS (enum ); \
213
+ POLYMORPHIC_YSON_STRUCT_IMPL__MAKE_MAPPING_CLASS (name, seq); \
214
+ } /* NPolymorphicYsonStructFor##name*/ \
215
+ using T##name = ::NYT::NYTree::TPolymorphicYsonStruct<NPolymorphicYsonStructFor##name::TMapping>; \
171
216
static_assert (true )
172
217
173
218
// //////////////////////////////////////////////////////////////////////////////
0 commit comments