Fix serialization of boost::variant
This commit is contained in:
parent
5f7c8b797b
commit
8296b50aec
|
@ -0,0 +1,96 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/MsgPack.h"
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace clmdep_msgpack {
|
||||
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
|
||||
namespace adaptor {
|
||||
|
||||
// ===========================================================================
|
||||
// -- Adaptors for boost::variant --------------------------------------------
|
||||
// ===========================================================================
|
||||
|
||||
template<typename... Ts>
|
||||
struct convert<boost::variant<Ts...>> {
|
||||
|
||||
const clmdep_msgpack::object &operator()(
|
||||
const clmdep_msgpack::object &o,
|
||||
boost::variant<Ts...> &v) const {
|
||||
if (o.type != clmdep_msgpack::type::ARRAY) {
|
||||
throw clmdep_msgpack::type_error();
|
||||
}
|
||||
if (o.via.array.size != 2) {
|
||||
throw clmdep_msgpack::type_error();
|
||||
}
|
||||
const auto index = o.via.array.ptr[0].as<int>();
|
||||
copy_to_variant(index, o, v, std::make_index_sequence<sizeof...(Ts)>());
|
||||
return o;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <size_t I>
|
||||
static void copy_to_variant_impl(
|
||||
const clmdep_msgpack::object &o,
|
||||
boost::variant<Ts...> &v) {
|
||||
/// @todo Workaround for finding the type.
|
||||
auto dummy = std::get<I>(std::tuple<Ts...>{});
|
||||
using T = decltype(dummy);
|
||||
v = o.via.array.ptr[1].as<T>();
|
||||
}
|
||||
|
||||
template <size_t... Is>
|
||||
static void copy_to_variant(
|
||||
const size_t index,
|
||||
const clmdep_msgpack::object &o,
|
||||
boost::variant<Ts...> &v,
|
||||
std::index_sequence<Is...>) {
|
||||
std::initializer_list<int> ({
|
||||
(index == Is ? copy_to_variant_impl<Is>(o, v), 0 : 0)...
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
struct pack<boost::variant<Ts...>> {
|
||||
template <typename Stream>
|
||||
packer<Stream> &operator()(
|
||||
clmdep_msgpack::packer<Stream> &o,
|
||||
const boost::variant<Ts...> &v) const {
|
||||
o.pack_array(2);
|
||||
o.pack(static_cast<int>(v.which()));
|
||||
boost::apply_visitor([&](const auto &value) { o.pack(value); }, v);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
struct object_with_zone<boost::variant<Ts...>> {
|
||||
void operator()(
|
||||
clmdep_msgpack::object::with_zone &o,
|
||||
const boost::variant<Ts...> &v) const {
|
||||
o.type = type::ARRAY;
|
||||
o.via.array.size = 2;
|
||||
o.via.array.ptr = static_cast<clmdep_msgpack::object*>(o.zone.allocate_align(
|
||||
sizeof(clmdep_msgpack::object) * o.via.array.size,
|
||||
MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)));
|
||||
o.via.array.ptr[0] = clmdep_msgpack::object(static_cast<int>(v.which()), o.zone);
|
||||
boost::apply_visitor([&](const auto &value) {
|
||||
o.via.array.ptr[1] = clmdep_msgpack::object(value, o.zone);
|
||||
}, v);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace adaptor
|
||||
} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
|
||||
} // namespace msgpack
|
|
@ -6,15 +6,14 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "carla/MsgPack.h"
|
||||
#include "carla/MsgPackAdaptors.h"
|
||||
#include "carla/geom/BoundingBox.h"
|
||||
#include "carla/geom/Location.h"
|
||||
#include "carla/geom/Rotation.h"
|
||||
#include "carla/rpc/Color.h"
|
||||
#include "carla/rpc/Variant.h"
|
||||
|
||||
// #include <rpc/msgpack/adaptor/boost/msgpack_variant.hpp>
|
||||
|
||||
// #include <boost/variant.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
@ -55,7 +54,7 @@ namespace rpc {
|
|||
MSGPACK_DEFINE_ARRAY(location, text, draw_shadow);
|
||||
};
|
||||
|
||||
Variant<Point, Line, Arrow, Box, String> primitive;
|
||||
boost::variant<Point, Line, Arrow, Box, String> primitive;
|
||||
|
||||
Color color = {255u, 0u, 0u};
|
||||
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/MsgPack.h"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
/// @todo Workaround for packing boost::variant; it uses tuple instead so it's
|
||||
/// quite inefficient memory-wise.
|
||||
template <typename... Ts>
|
||||
class Variant {
|
||||
private:
|
||||
|
||||
size_t _index = 0u;
|
||||
|
||||
std::tuple<Ts...> _tuple;
|
||||
|
||||
template <typename T, typename Tuple>
|
||||
struct IndexFromType;
|
||||
|
||||
template <typename T, typename... Types>
|
||||
struct IndexFromType<T, std::tuple<T, Types...>> {
|
||||
static constexpr size_t value = 0u;
|
||||
};
|
||||
|
||||
template <typename T, typename U, typename... Types>
|
||||
struct IndexFromType<T, std::tuple<U, Types...>> {
|
||||
static constexpr size_t value = 1u + IndexFromType<T, std::tuple<Types...>>::value;
|
||||
};
|
||||
|
||||
template <typename VisitorT, size_t... Is>
|
||||
void ApplyVisitorImpl(VisitorT &visitor, std::index_sequence<Is...>) const {
|
||||
std::initializer_list<int> ({ (_index == Is ? visitor(std::get<Is>(_tuple)), 0 : 0)... });
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Variant() = default;
|
||||
|
||||
template <typename ObjT>
|
||||
Variant(ObjT &&rhs) {
|
||||
(*this) = std::forward<ObjT>(rhs);
|
||||
}
|
||||
|
||||
template <typename ObjT>
|
||||
Variant &operator=(ObjT &&rhs) {
|
||||
constexpr auto index = IndexFromType<typename std::decay<ObjT>::type, decltype(_tuple)>::value;
|
||||
_index = index;
|
||||
std::get<index>(_tuple) = std::forward<ObjT>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename VisitorT>
|
||||
void ApplyVisitor(VisitorT visitor) const {
|
||||
return ApplyVisitorImpl(visitor, std::make_index_sequence<sizeof...(Ts)>());
|
||||
}
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(_index, _tuple);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "test.h"
|
||||
|
||||
#include <carla/MsgPackAdaptors.h>
|
||||
#include <carla/ThreadGroup.h>
|
||||
#include <carla/rpc/Actor.h>
|
||||
#include <carla/rpc/Client.h>
|
||||
|
@ -75,3 +76,24 @@ TEST(rpc, msgpack) {
|
|||
ASSERT_EQ(result.description.id, actor.description.id);
|
||||
ASSERT_EQ(result.bounding_box, actor.bounding_box);
|
||||
}
|
||||
|
||||
TEST(rpc, msgpack_variant) {
|
||||
using mp = carla::MsgPack;
|
||||
|
||||
boost::variant<bool, float, std::string> var;
|
||||
|
||||
var = true;
|
||||
auto result = mp::UnPack<decltype(var)>(mp::Pack(var));
|
||||
ASSERT_EQ(result.which(), 0);
|
||||
ASSERT_EQ(boost::get<bool>(result), true);
|
||||
|
||||
var = 42.0f;
|
||||
result = mp::UnPack<decltype(var)>(mp::Pack(var));
|
||||
ASSERT_EQ(result.which(), 1);
|
||||
ASSERT_EQ(boost::get<float>(result), 42.0f);
|
||||
|
||||
var = std::string("hola!");
|
||||
result = mp::UnPack<decltype(var)>(mp::Pack(var));
|
||||
ASSERT_EQ(result.which(), 2);
|
||||
ASSERT_EQ(boost::get<std::string>(result), "hola!");
|
||||
}
|
||||
|
|
|
@ -106,5 +106,5 @@ private:
|
|||
void FDebugShapeDrawer::Draw(const carla::rpc::DebugShape &Shape)
|
||||
{
|
||||
auto Visitor = FShapeVisitor(World, Shape.color, Shape.life_time, Shape.persistent_lines);
|
||||
Shape.primitive.ApplyVisitor(Visitor);
|
||||
boost::apply_visitor(Visitor, Shape.primitive);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue