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 #include <boost/variant.hpp>
14 
15 #include <tuple>
16 
17 namespace clmdep_msgpack {
18 MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
19 namespace adaptor {
20 
21  // ===========================================================================
22  // -- Adaptors for boost::optional -------------------------------------------
23  // ===========================================================================
24 
25  template<typename T>
26  struct convert<boost::optional<T>> {
27  const clmdep_msgpack::object &operator()(
28  const clmdep_msgpack::object &o,
29  boost::optional<T> &v) const {
30  if (o.type != clmdep_msgpack::type::ARRAY) {
31  ::carla::throw_exception(clmdep_msgpack::type_error());
32  }
33  if (o.via.array.size == 1) {
34  v.reset();
35  } else if (o.via.array.size == 2) {
36  v.reset(o.via.array.ptr[1].as<T>());
37  } else {
38  ::carla::throw_exception(clmdep_msgpack::type_error());
39  }
40  return o;
41  }
42  };
43 
44  template<typename T>
45  struct pack<boost::optional<T>> {
46  template <typename Stream>
47  packer<Stream> &operator()(
48  clmdep_msgpack::packer<Stream> &o,
49  const boost::optional<T> &v) const {
50  if (v.has_value()) {
51  o.pack_array(2);
52  o.pack(true);
53  o.pack(*v);
54  } else {
55  o.pack_array(1);
56  o.pack(false);
57  }
58  return o;
59  }
60  };
61 
62  template<typename T>
63  struct object_with_zone<boost::optional<T>> {
64  void operator()(
65  clmdep_msgpack::object::with_zone &o,
66  const boost::optional<T> &v) const {
67  o.type = type::ARRAY;
68  if (v.has_value()) {
69  o.via.array.size = 2;
70  o.via.array.ptr = static_cast<clmdep_msgpack::object*>(o.zone.allocate_align(
71  sizeof(clmdep_msgpack::object) * o.via.array.size,
72  MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)));
73  o.via.array.ptr[0] = clmdep_msgpack::object(true, o.zone);
74  o.via.array.ptr[1] = clmdep_msgpack::object(*v, o.zone);
75  } else {
76  o.via.array.size = 1;
77  o.via.array.ptr = static_cast<clmdep_msgpack::object*>(o.zone.allocate_align(
78  sizeof(clmdep_msgpack::object) * o.via.array.size,
79  MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)));
80  o.via.array.ptr[0] = clmdep_msgpack::object(false, o.zone);
81  }
82  }
83  };
84 
85  // ===========================================================================
86  // -- Adaptors for boost::variant --------------------------------------------
87  // ===========================================================================
88 
89  template<typename... Ts>
90  struct convert<boost::variant<Ts...>> {
91 
92  const clmdep_msgpack::object &operator()(
93  const clmdep_msgpack::object &o,
94  boost::variant<Ts...> &v) const {
95  if (o.type != clmdep_msgpack::type::ARRAY) {
96  ::carla::throw_exception(clmdep_msgpack::type_error());
97  }
98  if (o.via.array.size != 2) {
99  ::carla::throw_exception(clmdep_msgpack::type_error());
100  }
101  const auto index = o.via.array.ptr[0].as<uint64_t>();
102  copy_to_variant(index, o, v, std::make_index_sequence<sizeof...(Ts)>());
103  return o;
104  }
105 
106  private:
107 
108  template <uint64_t I>
109  static void copy_to_variant_impl(
110  const clmdep_msgpack::object &o,
111  boost::variant<Ts...> &v) {
112  /// @todo Workaround for finding the type.
113  auto dummy = std::get<I>(std::tuple<Ts...>{});
114  using T = decltype(dummy);
115  v = o.via.array.ptr[1].as<T>();
116  }
117 
118  template <uint64_t... Is>
119  static void copy_to_variant(
120  const uint64_t index,
121  const clmdep_msgpack::object &o,
122  boost::variant<Ts...> &v,
123  std::index_sequence<Is...>) {
124  std::initializer_list<int> ({
125  (index == Is ? copy_to_variant_impl<Is>(o, v), 0 : 0)...
126  });
127  }
128  };
129 
130  template<typename... Ts>
131  struct pack<boost::variant<Ts...>> {
132  template <typename Stream>
133  packer<Stream> &operator()(
134  clmdep_msgpack::packer<Stream> &o,
135  const boost::variant<Ts...> &v) const {
136  o.pack_array(2);
137  o.pack(static_cast<uint64_t>(v.which()));
138  boost::apply_visitor([&](const auto &value) { o.pack(value); }, v);
139  return o;
140  }
141  };
142 
143  template<typename... Ts>
144  struct object_with_zone<boost::variant<Ts...>> {
145  void operator()(
146  clmdep_msgpack::object::with_zone &o,
147  const boost::variant<Ts...> &v) const {
148  o.type = type::ARRAY;
149  o.via.array.size = 2;
150  o.via.array.ptr = static_cast<clmdep_msgpack::object*>(o.zone.allocate_align(
151  sizeof(clmdep_msgpack::object) * o.via.array.size,
152  MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)));
153  o.via.array.ptr[0] = clmdep_msgpack::object(static_cast<uint64_t>(v.which()), o.zone);
154  boost::apply_visitor([&](const auto &value) {
155  o.via.array.ptr[1] = clmdep_msgpack::object(value, o.zone);
156  }, v);
157  }
158  };
159 
160 } // namespace adaptor
161 } // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
162 } // namespace msgpack
void throw_exception(const std::exception &e)
Definition: Carla.cpp:101
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)