@@ -98,6 +98,22 @@ constexpr auto getFamiliesByRules()
9898 return getFamiliesByRules<T>(tnt::tuple_iseq<T>{});
9999}
100100
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+
101117template <class BUF , class T >
102118constexpr auto detectFamily ()
103119{
@@ -117,6 +133,8 @@ constexpr auto detectFamily()
117133 } else if constexpr (tnt::is_optional_v<U>) {
118134 return family_sequence_populate<compact::MP_NIL>(
119135 detectFamily<BUF, tnt::value_type_t <U>>());
136+ } else if constexpr (tnt::is_variant_v<U>) {
137+ return detectFamilyVariant<BUF, U>();
120138 } else if constexpr (std::is_same_v<U, std::nullptr_t >) {
121139 return family_sequence<compact::MP_NIL>{};
122140 } else if constexpr (std::is_same_v<U, bool >) {
@@ -176,6 +194,7 @@ enum path_item_type {
176194 PIT_DYN_KEY,
177195 PIT_DYN_SKIP,
178196 PIT_OPTIONAL,
197+ PIT_VARIANT,
179198 PIT_RAW,
180199};
181200
@@ -239,8 +258,11 @@ struct Resolver {
239258 static constexpr size_t SIZE = path_item_static_size(PI);
240259 static constexpr size_t USR_ARG_COUNT = path_item_static_size(P0);
241260 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 ));
244266
245267 template <size_t ... J>
246268 static constexpr size_t dyn_arg_pos (tnt::iseq<J...>)
@@ -298,6 +320,8 @@ struct Resolver {
298320 auto &&opt = prev (t...);
299321 assert (opt.has_value ());
300322 return *opt;
323+ } else if constexpr (TYPE == PIT_VARIANT) {
324+ return tnt::get<POS>(prev (t...));
301325 } else {
302326 static_assert (tnt::always_false_v<T...>);
303327 }
@@ -871,7 +895,7 @@ bool decode_next(BUF& buf, T... t)
871895 return decode_impl<SKIP_PATH>(buf, t...);
872896 } else if constexpr (static_done) {
873897 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 ) {
875899 return decode_next<POP_PATH>(buf, t...);
876900 } else if constexpr (!is_path_item_dynamic (LAST)) {
877901 return decode_impl<NEXT_PATH>(buf, t...);
@@ -1167,6 +1191,37 @@ bool jump_read_optional(BUF& buf, T... t)
11671191 }
11681192}
11691193
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+
11701225template <compact::Family FAMILY, size_t SUBRULE,
11711226 class PATH , class BUF , class ... T>
11721227bool jump_common (BUF& buf, T... t)
@@ -1178,6 +1233,8 @@ bool jump_common(BUF& buf, T... t)
11781233 using dst_t = std::remove_reference_t <decltype (dst)>;
11791234 if constexpr (tnt::is_optional_v<dst_t >)
11801235 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...);
11811238 else if constexpr (path_item_type (PATH::last ()) == PIT_DYN_ADD)
11821239 return jump_add<FAMILY, SUBRULE, PATH>(buf, t...);
11831240 else if constexpr (path_item_type (PATH::last ()) == PIT_DYN_KEY)
0 commit comments