Skip to content

Commit 327f3d1

Browse files
committed
implement as and pack for std::variant
1 parent ac062e2 commit 327f3d1

File tree

4 files changed

+164
-0
lines changed

4 files changed

+164
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// MessagePack for C++ static resolution routine
3+
//
4+
// Copyright (C) 2023 Uy Ha
5+
//
6+
// Distributed under the Boost Software License, Version 1.0.
7+
// (See accompanying file LICENSE_1_0.txt or copy at
8+
// http://www.boost.org/LICENSE_1_0.txt)
9+
//
10+
11+
#ifndef MSGPACK_TYPE_CPP17_VARIANT_HPP
12+
#define MSGPACK_TYPE_CPP17_VARIANT_HPP
13+
14+
#include "msgpack/v1/adaptor/cpp17/variant.hpp"
15+
16+
#endif // MSGPACK_TYPE_CPP17_VARIANT_HPP

include/msgpack/type.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@
6363
#include "adaptor/cpp17/carray_byte.hpp"
6464
#include "adaptor/cpp17/vector_byte.hpp"
6565

66+
#if MSGPACK_HAS_INCLUDE(<variant>)
67+
#include "adaptor/cpp17/variant.hpp"
68+
#endif // MSGPACK_HAS_INCLUDE(<variant>)
69+
6670
#if MSGPACK_HAS_INCLUDE(<span>)
6771
#include "adaptor/cpp20/span.hpp"
6872
#endif // MSGPACK_HAS_INCLUDE(<span>)
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//
2+
// MessagePack for C++ static resolution routine
3+
//
4+
// Copyright (C) 2023 Uy Ha
5+
//
6+
// Distributed under the Boost Software License, Version 1.0.
7+
// (See accompanying file LICENSE_1_0.txt or copy at
8+
// http://www.boost.org/LICENSE_1_0.txt)
9+
//
10+
11+
#ifndef MSGPACK_V1_TYPE_VARIANT_HPP
12+
#define MSGPACK_V1_TYPE_VARIANT_HPP
13+
14+
#define MSGPACK_USE_STD_VARIANT_ADAPTOR
15+
16+
#if defined(MSGPACK_USE_STD_VARIANT_ADAPTOR)
17+
18+
#include "msgpack/cpp_version.hpp"
19+
20+
#if MSGPACK_CPP_VERSION >= 201703
21+
22+
#include "msgpack/adaptor/adaptor_base.hpp"
23+
#include "msgpack/object.hpp"
24+
#include "msgpack/versioning.hpp"
25+
26+
#include <variant>
27+
28+
namespace msgpack {
29+
MSGPACK_API_VERSION_NAMESPACE(v1) {
30+
namespace adaptor {
31+
namespace detail {
32+
template <typename Variant, typename T, typename... Ts, std::size_t current_index, std::size_t... indices>
33+
Variant construct_variant(std::size_t index,
34+
msgpack::object &object,
35+
std::index_sequence<current_index, indices...>) {
36+
if constexpr(sizeof...(Ts) == 0) {
37+
return object.as<T>();
38+
} else {
39+
if (index == current_index) {
40+
return object.as<T>();
41+
}
42+
return construct_variant<Variant, Ts...>(index, object, std::index_sequence<indices...>());
43+
}
44+
}
45+
46+
} // namespace detail
47+
48+
template <typename... Ts>
49+
struct as<std::variant<Ts...>, std::enable_if_t<(msgpack::has_as<Ts>::value && ...)>> {
50+
std::variant<Ts...> operator()(msgpack::object const &o) const {
51+
if (o.type != msgpack::type::ARRAY) {
52+
throw msgpack::type_error{};
53+
}
54+
if (o.via.array.size != 2) {
55+
throw msgpack::type_error{};
56+
}
57+
if (o.via.array.ptr[0].type != msgpack::type::POSITIVE_INTEGER) {
58+
throw msgpack::type_error{};
59+
}
60+
return detail::construct_variant<std::variant<Ts...>, Ts...>(
61+
o.via.array.ptr[0].as<std::size_t>(),
62+
o.via.array.ptr[1],
63+
std::make_index_sequence<sizeof...(Ts)>()
64+
);
65+
}
66+
};
67+
68+
template<typename... Ts>
69+
struct convert<std::variant<Ts...>> {
70+
msgpack::object const &operator()(msgpack::object const &o, std::variant<Ts...> &v) const {
71+
if (o.type != msgpack::type::ARRAY) {
72+
throw msgpack::type_error{};
73+
}
74+
if (o.via.array.size != 2) {
75+
throw msgpack::type_error{};
76+
}
77+
if (o.via.array.ptr[0].type != msgpack::type::POSITIVE_INTEGER) {
78+
throw msgpack::type_error{};
79+
}
80+
v = detail::construct_variant<std::variant<Ts...>, Ts...>(
81+
o.via.array.ptr[0].as<std::size_t>(),
82+
o.via.array.ptr[1],
83+
std::make_index_sequence<sizeof...(Ts)>()
84+
);
85+
return o;
86+
}
87+
};
88+
89+
template <typename... Ts>
90+
struct pack<std::variant<Ts...>>{
91+
template<typename Stream>
92+
msgpack::packer<Stream>& operator()(msgpack::packer<Stream> &o, std::variant<Ts...> const &v) const {
93+
o.pack_array(2);
94+
o.pack_uint64(v.index());
95+
std::visit([&o](auto const &real_value){o.pack(real_value);}, v);
96+
return o;
97+
}
98+
};
99+
100+
// template <typename... Ts>
101+
// struct object<std::variant<Ts...>> {
102+
// void operator()(msgpack::object &o, std::variant<Ts...> const &v) const {
103+
// o.type = msgpack::type::ARRAY;
104+
// o.via.array.size = 2;
105+
// msgpack::adaptor::object<std::size_t>(o.via.array.ptr[0], v.index());
106+
// std::visit([&o](auto const &value) {
107+
// msgpack::adaptor::object(o.via.array.ptr[1], value);
108+
// }, v);
109+
// }
110+
// };
111+
//
112+
// template<typename... Ts>
113+
// struct object_with_zone<std::variant<Ts...>> {
114+
// void operator()(msgpack::object::with_zone &o, std::variant<Ts...> const &v) const {
115+
// o.type = msgpack::type::ARRAY;
116+
//
117+
// msgpack::object *p = static_cast<msgpack::object *>(o.zone.allocate_align(sizeof(msgpack::object) * 2, MSGPACK_ZONE_ALIGNOF(msgpack::object)));
118+
//
119+
// o.via.array.size = 2;
120+
// o.via.array.ptr = p;
121+
// msgpack::adaptor::object_with_zone<std::size_t>()(o.via.array.ptr[0], v.index(), o.zone);
122+
// std::visit([&o](auto const &real_value){
123+
// o.via.array.ptr[1] = msgpack::adaptor::object()(real_value, o.zone);
124+
// }, v);
125+
// }
126+
// };
127+
} // namespace adaptor
128+
}
129+
} // namespace msgpack
130+
131+
#endif // MSGPACK_CPP_VERSION >= 201703
132+
#endif // defined(MSGPACK_USE_STD_VARIANT_ADAPTOR)
133+
#endif // MSGPACK_V1_TYPE_VARIANT_HPP

test/msgpack_cpp17.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,15 @@ BOOST_AUTO_TEST_CASE(carray_byte_object_with_zone)
461461
}
462462
}
463463

464+
BOOST_AUTO_TEST_CASE(variant_as) {
465+
std::stringstream ss;
466+
std::variant<bool, int, float, double> val1{1.0};
467+
msgpack::pack(ss, val1);
468+
std::string const& str = ss.str();
469+
msgpack::object_handle oh =
470+
msgpack::unpack(str.data(), str.size());
471+
std::variant<bool, int, float, double> val2 = oh.get().as<std::variant<bool, int, float, double> >();
472+
BOOST_CHECK(val1 == val2);
473+
}
474+
464475
#endif // MSGPACK_CPP_VERSION >= 201703

0 commit comments

Comments
 (0)