CARLA
MsgPackAdaptors.h
Go to the documentation of this file.
1 // Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
2 // de Barcelona (UAB).
3 //
4 // This work is licensed under the terms of the MIT license.
5 // For a copy, see <https://opensource.org/licenses/MIT>.
6 
7 #pragma once
8 
9 #include "carla/Exception.h"
10 #include "carla/MsgPack.h"
11 
12 #include <boost/optional.hpp>
13 
14 #ifdef _MSC_VER
15 #pragma warning(push)
16 #pragma warning(disable:4583)
17 #pragma warning(disable:4582)
18 #include <boost/variant2/variant.hpp>
19 #pragma warning(pop)
20 #else
21 #include <boost/variant2/variant.hpp>
22 #endif
23 
24 #include <tuple>
25 
26 namespace clmdep_msgpack {
27 MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
28 namespace adaptor {
29 
30  // ===========================================================================
31  // -- Adaptors for boost::optional -------------------------------------------
32  // ===========================================================================
33 
34  template<typename T>
35  struct convert<boost::optional<T>> {
36  const clmdep_msgpack::object &operator()(
37  const clmdep_msgpack::object &o,
38  boost::optional<T> &v) const {
39  if (o.type != clmdep_msgpack::type::ARRAY) {
40  ::carla::throw_exception(clmdep_msgpack::type_error());
41  }
42  if (o.via.array.size == 1) {
43  v.reset();
44  } else if (o.via.array.size == 2) {
45  v.reset(o.via.array.ptr[1].as<T>());
46  } else {
47  ::carla::throw_exception(clmdep_msgpack::type_error());
48  }
49  return o;
50  }
51  };
52 
53  template<typename T>
54  struct pack<boost::optional<T>> {
55  template <typename Stream>
56  packer<Stream> &operator()(
57  clmdep_msgpack::packer<Stream> &o,
58  const boost::optional<T> &v) const {
59  if (v.has_value()) {
60  o.pack_array(2);
61  o.pack(true);
62  o.pack(*v);
63  } else {
64  o.pack_array(1);
65  o.pack(false);
66  }
67  return o;
68  }
69  };
70 
71  template<typename T>
72  struct object_with_zone<boost::optional<T>> {
73  void operator()(
74  clmdep_msgpack::object::with_zone &o,
75  const boost::optional<T> &v) const {
76  o.type = type::ARRAY;
77  if (v.has_value()) {
78  o.via.array.size = 2;
79  o.via.array.ptr = static_cast<clmdep_msgpack::object*>(o.zone.allocate_align(
80  sizeof(clmdep_msgpack::object) * o.via.array.size,
81  MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)));
82  o.via.array.ptr[0] = clmdep_msgpack::object(true, o.zone);
83  o.via.array.ptr[1] = clmdep_msgpack::object(*v, o.zone);
84  } else {
85  o.via.array.size = 1;
86  o.via.array.ptr = static_cast<clmdep_msgpack::object*>(o.zone.allocate_align(
87  sizeof(clmdep_msgpack::object) * o.via.array.size,
88  MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)));
89  o.via.array.ptr[0] = clmdep_msgpack::object(false, o.zone);
90  }
91  }
92  };
93 
94  // ===========================================================================
95  // -- Adaptors for boost::variant2::variant ----------------------------------
96  // ===========================================================================
97 
98  template<typename... Ts>
99  struct convert<boost::variant2::variant<Ts...>> {
100 
101  const clmdep_msgpack::object &operator()(
102  const clmdep_msgpack::object &o,
103  boost::variant2::variant<Ts...> &v) const {
104  if (o.type != clmdep_msgpack::type::ARRAY) {
105  ::carla::throw_exception(clmdep_msgpack::type_error());
106  }
107  if (o.via.array.size != 2) {
108  ::carla::throw_exception(clmdep_msgpack::type_error());
109  }
110  const auto index = o.via.array.ptr[0].as<uint64_t>();
111  copy_to_variant(index, o, v, std::make_index_sequence<sizeof...(Ts)>());
112  return o;
113  }
114 
115  private:
116 
117  template <uint64_t I>
118  static void copy_to_variant_impl(
119  const clmdep_msgpack::object &o,
120  boost::variant2::variant<Ts...> &v) {
121  /// @todo Workaround for finding the type.
122  auto dummy = std::get<I>(std::tuple<Ts...>{});
123  using T = decltype(dummy);
124  v = o.via.array.ptr[1].as<T>();
125  }
126 
127  template <uint64_t... Is>
128  static void copy_to_variant(
129  const uint64_t index,
130  const clmdep_msgpack::object &o,
131  boost::variant2::variant<Ts...> &v,
132  std::index_sequence<Is...>) {
133  std::initializer_list<int> ({
134  (index == Is ? copy_to_variant_impl<Is>(o, v), 0 : 0)...
135  });
136  }
137  };
138 
139  template<typename... Ts>
140  struct pack<boost::variant2::variant<Ts...>> {
141  template <typename Stream>
142  packer<Stream> &operator()(
143  clmdep_msgpack::packer<Stream> &o,
144  const boost::variant2::variant<Ts...> &v) const {
145  o.pack_array(2);
146  o.pack(static_cast<uint64_t>(v.index()));
147  boost::variant2::visit([&](const auto &value) { o.pack(value); }, v);
148  return o;
149  }
150  };
151 
152  template<typename... Ts>
153  struct object_with_zone<boost::variant2::variant<Ts...>> {
154  void operator()(
155  clmdep_msgpack::object::with_zone &o,
156  const boost::variant2::variant<Ts...> &v) const {
157  o.type = type::ARRAY;
158  o.via.array.size = 2;
159  o.via.array.ptr = static_cast<clmdep_msgpack::object*>(o.zone.allocate_align(
160  sizeof(clmdep_msgpack::object) * o.via.array.size,
161  MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)));
162  o.via.array.ptr[0] = clmdep_msgpack::object(static_cast<uint64_t>(v.index()), o.zone);
163  boost::variant2::visit([&](const auto &value) {
164  o.via.array.ptr[1] = clmdep_msgpack::object(value, o.zone);
165  }, v);
166  }
167  };
168 
169 } // namespace adaptor
170 } // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
171 } // namespace msgpack
void throw_exception(const std::exception &e)
Definition: Carla.cpp:135
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)