@@ -98,6 +98,22 @@ constexpr auto getFamiliesByRules()
98
98
return getFamiliesByRules<T>(tnt::tuple_iseq<T>{});
99
99
}
100
100
101
+ template <class BUF , class T >
102
+ constexpr auto detectFamily ();
103
+
104
+ template <class BUF , class T , size_t I = 0 >
105
+ constexpr auto detectFamilyVariant ()
106
+ {
107
+ static_assert (tnt::is_variant_v<T>);
108
+ if constexpr (I < std::variant_size_v<T>) {
109
+ constexpr auto curFamily =
110
+ detectFamily<BUF, std::variant_alternative_t <I, T>>();
111
+ return curFamily + detectFamilyVariant<BUF, T, I + 1 >();
112
+ } else {
113
+ return family_sequence<>{};
114
+ }
115
+ }
116
+
101
117
template <class BUF , class T >
102
118
constexpr auto detectFamily ()
103
119
{
@@ -117,6 +133,8 @@ constexpr auto detectFamily()
117
133
} else if constexpr (tnt::is_optional_v<U>) {
118
134
return family_sequence_populate<compact::MP_NIL>(
119
135
detectFamily<BUF, tnt::value_type_t <U>>());
136
+ } else if constexpr (tnt::is_variant_v<U>) {
137
+ return detectFamilyVariant<BUF, U>();
120
138
} else if constexpr (std::is_same_v<U, std::nullptr_t >) {
121
139
return family_sequence<compact::MP_NIL>{};
122
140
} else if constexpr (std::is_same_v<U, bool >) {
@@ -176,6 +194,7 @@ enum path_item_type {
176
194
PIT_DYN_KEY,
177
195
PIT_DYN_SKIP,
178
196
PIT_OPTIONAL,
197
+ PIT_VARIANT,
179
198
PIT_RAW,
180
199
};
181
200
@@ -239,8 +258,11 @@ struct Resolver {
239
258
static constexpr size_t SIZE = path_item_static_size(PI);
240
259
static constexpr size_t USR_ARG_COUNT = path_item_static_size(P0);
241
260
static_assert (path_item_type(P0) == PIT_STATIC_L0);
242
- static_assert ((is_path_item_static(PI) && POS < SIZE) ||
243
- (!is_path_item_static(PI) && POS + SIZE == 0 ));
261
+ /* Is set if the current path item requires static POS and SIZE. */
262
+ static constexpr bool requires_pos_and_size =
263
+ is_path_item_static (PI) || path_item_type(PI) == PIT_VARIANT;
264
+ static_assert ((requires_pos_and_size && POS < SIZE) ||
265
+ (!requires_pos_and_size && POS + SIZE == 0 ));
244
266
245
267
template <size_t ... J>
246
268
static constexpr size_t dyn_arg_pos (tnt::iseq<J...>)
@@ -298,6 +320,8 @@ struct Resolver {
298
320
auto &&opt = prev (t...);
299
321
assert (opt.has_value ());
300
322
return *opt;
323
+ } else if constexpr (TYPE == PIT_VARIANT) {
324
+ return tnt::get<POS>(prev (t...));
301
325
} else {
302
326
static_assert (tnt::always_false_v<T...>);
303
327
}
@@ -871,7 +895,7 @@ bool decode_next(BUF& buf, T... t)
871
895
return decode_impl<SKIP_PATH>(buf, t...);
872
896
} else if constexpr (static_done) {
873
897
return decode_next<POP_PATH>(buf, t...);
874
- } else if constexpr (LAST_TYPE == PIT_OPTIONAL) {
898
+ } else if constexpr (LAST_TYPE == PIT_OPTIONAL || LAST_TYPE == PIT_VARIANT ) {
875
899
return decode_next<POP_PATH>(buf, t...);
876
900
} else if constexpr (!is_path_item_dynamic (LAST)) {
877
901
return decode_impl<NEXT_PATH>(buf, t...);
@@ -1167,6 +1191,37 @@ bool jump_read_optional(BUF& buf, T... t)
1167
1191
}
1168
1192
}
1169
1193
1194
+ template <size_t I, compact::Family FAMILY, size_t SUBRULE,
1195
+ class PATH , class BUF , class ... T>
1196
+ bool jump_read_variant_impl (BUF& buf, T... t)
1197
+ {
1198
+ auto && variant = unwrap (path_resolve (PATH{}, t...));
1199
+ using variant_t = std::remove_reference_t <decltype (variant)>;
1200
+ constexpr size_t size = std::variant_size_v<variant_t >;
1201
+ static_assert (tnt::is_variant_v<variant_t >);
1202
+ static_assert (I < size);
1203
+ using curType = std::variant_alternative_t <I, variant_t >;
1204
+ constexpr auto curFamilies = detectFamily<BUF, curType>();
1205
+
1206
+ if constexpr (family_sequence_contains<FAMILY>(curFamilies)) {
1207
+ variant.template emplace <I>();
1208
+ using NEXT_PATH = path_push_t <PATH, PIT_VARIANT, size, I>;
1209
+ return decode_impl<NEXT_PATH>(buf, t...);
1210
+ } else {
1211
+ return jump_read_variant_impl<I + 1 , FAMILY, SUBRULE, PATH>(buf, t...);
1212
+ }
1213
+ }
1214
+
1215
+ template <compact::Family FAMILY, size_t SUBRULE,
1216
+ class PATH , class BUF , class ... T>
1217
+ bool jump_read_variant (BUF& buf, T... t)
1218
+ {
1219
+ auto && dst = unwrap (path_resolve (PATH{}, t...));
1220
+ using dst_t = std::remove_reference_t <decltype (dst)>;
1221
+ static_assert (tnt::is_variant_v<dst_t >);
1222
+ return jump_read_variant_impl<0 , FAMILY, SUBRULE, PATH>(buf, t...);
1223
+ }
1224
+
1170
1225
template <compact::Family FAMILY, size_t SUBRULE,
1171
1226
class PATH , class BUF , class ... T>
1172
1227
bool jump_common (BUF& buf, T... t)
@@ -1178,6 +1233,8 @@ bool jump_common(BUF& buf, T... t)
1178
1233
using dst_t = std::remove_reference_t <decltype (dst)>;
1179
1234
if constexpr (tnt::is_optional_v<dst_t >)
1180
1235
return jump_read_optional<FAMILY, SUBRULE, PATH>(buf, t...);
1236
+ else if constexpr (tnt::is_variant_v<dst_t >)
1237
+ return jump_read_variant<FAMILY, SUBRULE, PATH>(buf, t...);
1181
1238
else if constexpr (path_item_type (PATH::last ()) == PIT_DYN_ADD)
1182
1239
return jump_add<FAMILY, SUBRULE, PATH>(buf, t...);
1183
1240
else if constexpr (path_item_type (PATH::last ()) == PIT_DYN_KEY)
0 commit comments