Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #ifndef IROHA_VARIANT_DESERIALIZER_HPP
7 : #define IROHA_VARIANT_DESERIALIZER_HPP
8 :
9 : #include <boost/serialization/variant.hpp>
10 :
11 : #define NORETURN [[noreturn]]
12 :
13 : namespace shared_model {
14 : namespace detail {
15 : /**
16 : * Helper for variant deserialization
17 : * Iterate through type list to use type specified by type index in list
18 : * @tparam S list of types
19 : */
20 : template <class S>
21 : struct variant_impl {
22 : /**
23 : * Dummy deserializer for empty list
24 : */
25 : struct load_null {
26 : /**
27 : * Dummy deserializer
28 : * @tparam V variant type for deserialization
29 : * @tparam Archive container type
30 : */
31 : template <class V, class Archive>
32 : NORETURN static V invoke(Archive &&, int) {
33 0 : BOOST_ASSERT_MSG(false, "Required type not found");
34 : std::abort();
35 0 : }
36 : };
37 :
38 : /**
39 : * Deserializer implementation
40 : */
41 : struct load_impl {
42 : /**
43 : * Deserialize container in variant using type in list by specified
44 : * index
45 : * If type selector is 0, head type is required type, and it is used
46 : * Otherwise call helper without front element in type list
47 : * @tparam V variant type for deserialization
48 : * @tparam Archive container type
49 : * @param ar container to be deserialized
50 : * @param which type index in list
51 : * @param v result variant
52 : */
53 : template <class V, class Archive>
54 : static V invoke(Archive &&ar, int which) {
55 74105 : if (which == 0) {
56 : using head_type = typename boost::mpl::front<S>::type;
57 16191 : return head_type(std::forward<Archive>(ar));
58 : } else {
59 : using type = typename boost::mpl::pop_front<S>::type;
60 70431 : return variant_impl<type>::template load<V>(
61 70431 : std::forward<Archive>(ar), which - 1);
62 : }
63 74011 : }
64 : };
65 :
66 : /**
67 : * Deserialize container in variant using type in list by specified index
68 : * Choose dummy or concrete deserializer depending on type list size
69 : * @tparam V variant type for deserialization
70 : * @tparam Archive container type
71 : * @param ar container to be deserialized
72 : * @param which type index in list
73 : * @param v result variant
74 : */
75 : template <class V, class Archive>
76 : static V load(Archive &&ar, int which) {
77 : using typex =
78 : typename boost::mpl::eval_if<boost::mpl::empty<S>,
79 : boost::mpl::identity<load_null>,
80 : boost::mpl::identity<load_impl>>::type;
81 74092 : return typex::template invoke<V>(std::forward<Archive>(ar), which);
82 : }
83 : };
84 : } // namespace detail
85 : } // namespace shared_model
86 :
87 : #endif // IROHA_VARIANT_DESERIALIZER_HPP
|