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
|
#pragma once
|
||||||
|
|
||||||
|
#include "carla/MsgPack.h"
|
||||||
|
#include "carla/MsgPackAdaptors.h"
|
||||||
#include "carla/geom/BoundingBox.h"
|
#include "carla/geom/BoundingBox.h"
|
||||||
#include "carla/geom/Location.h"
|
#include "carla/geom/Location.h"
|
||||||
#include "carla/geom/Rotation.h"
|
#include "carla/geom/Rotation.h"
|
||||||
#include "carla/rpc/Color.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 carla {
|
||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
@ -55,7 +54,7 @@ namespace rpc {
|
||||||
MSGPACK_DEFINE_ARRAY(location, text, draw_shadow);
|
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};
|
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 "test.h"
|
||||||
|
|
||||||
|
#include <carla/MsgPackAdaptors.h>
|
||||||
#include <carla/ThreadGroup.h>
|
#include <carla/ThreadGroup.h>
|
||||||
#include <carla/rpc/Actor.h>
|
#include <carla/rpc/Actor.h>
|
||||||
#include <carla/rpc/Client.h>
|
#include <carla/rpc/Client.h>
|
||||||
|
@ -75,3 +76,24 @@ TEST(rpc, msgpack) {
|
||||||
ASSERT_EQ(result.description.id, actor.description.id);
|
ASSERT_EQ(result.description.id, actor.description.id);
|
||||||
ASSERT_EQ(result.bounding_box, actor.bounding_box);
|
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)
|
void FDebugShapeDrawer::Draw(const carla::rpc::DebugShape &Shape)
|
||||||
{
|
{
|
||||||
auto Visitor = FShapeVisitor(World, Shape.color, Shape.life_time, Shape.persistent_lines);
|
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