Skip to content

Commit 57ba93a

Browse files
committed
Added Boost.Fusion support.
Fusion sequences can be serialized.
1 parent 1a6f826 commit 57ba93a

File tree

9 files changed

+177
-10
lines changed

9 files changed

+177
-10
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ IF (MSGPACK_ENABLE_CXX)
105105
include/msgpack.hpp
106106
include/msgpack/adaptor/adaptor_base.hpp
107107
include/msgpack/adaptor/bool.hpp
108+
include/msgpack/adaptor/boost/fusion.hpp
108109
include/msgpack/adaptor/boost/optional.hpp
109110
include/msgpack/adaptor/boost/string_ref.hpp
110111
include/msgpack/adaptor/char_ptr.hpp

include/msgpack/adaptor/adaptor_base.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,23 @@ namespace adaptor {
3333

3434
// Adaptor functors
3535

36-
template <typename T>
36+
template <typename T, typename Enabler = void>
3737
struct convert {
3838
msgpack::object const& operator()(msgpack::object const& o, T& v) const;
3939
};
4040

41-
template <typename T>
41+
template <typename T, typename Enabler = void>
4242
struct pack {
4343
template <typename Stream>
4444
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, T const& v) const;
4545
};
4646

47-
template <typename T>
47+
template <typename T, typename Enabler = void>
4848
struct object {
4949
void operator()(msgpack::object& o, T const& v) const;
5050
};
5151

52-
template <typename T>
52+
template <typename T, typename Enabler = void>
5353
struct object_with_zone {
5454
void operator()(msgpack::object::with_zone& o, T const& v) const;
5555
};
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//
2+
// MessagePack for C++ static resolution routine
3+
//
4+
// Copyright (C) 2015 KONDO Takatoshi
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
#ifndef MSGPACK_TYPE_BOOST_FUSION_HPP
19+
#define MSGPACK_TYPE_BOOST_FUSION_HPP
20+
21+
#include "msgpack/versioning.hpp"
22+
#include "msgpack/adaptor/adaptor_base.hpp"
23+
#include "msgpack/adaptor/check_container_size.hpp"
24+
25+
#include <boost/fusion/support/is_sequence.hpp>
26+
#include <boost/fusion/sequence/intrinsic/size.hpp>
27+
#include <boost/fusion/algorithm/iteration/for_each.hpp>
28+
29+
namespace msgpack {
30+
31+
/// @cond
32+
MSGPACK_API_VERSION_NAMESPACE(v1) {
33+
/// @endcond
34+
35+
namespace adaptor {
36+
37+
template <typename T>
38+
struct convert<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::value>::type > {
39+
msgpack::object const& operator()(msgpack::object const& o, T& v) const {
40+
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
41+
if(o.via.array.size != checked_get_container_size(boost::fusion::size(v))) {
42+
throw msgpack::type_error();
43+
}
44+
uint32_t index = 0;
45+
boost::fusion::for_each(v, convert_imp(o, index));
46+
return o;
47+
}
48+
private:
49+
struct convert_imp {
50+
convert_imp(msgpack::object const& obj, uint32_t& index):obj_(obj), index_(index) {}
51+
template <typename U>
52+
void operator()(U& v) const {
53+
msgpack::adaptor::convert<U>()(obj_.via.array.ptr[index_++], v);
54+
}
55+
private:
56+
msgpack::object const& obj_;
57+
uint32_t& index_;
58+
};
59+
};
60+
61+
template <typename T>
62+
struct pack<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::value>::type > {
63+
template <typename Stream>
64+
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const T& v) const {
65+
uint32_t size = checked_get_container_size(boost::fusion::size(v));
66+
o.pack_array(size);
67+
boost::fusion::for_each(v, pack_imp<Stream>(o));
68+
return o;
69+
}
70+
private:
71+
template <typename Stream>
72+
struct pack_imp {
73+
pack_imp(msgpack::packer<Stream>& stream):stream_(stream) {}
74+
template <typename U>
75+
void operator()(U const& v) const {
76+
stream_.pack(v);
77+
}
78+
private:
79+
msgpack::packer<Stream>& stream_;
80+
};
81+
};
82+
83+
template <typename T>
84+
struct object_with_zone<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::value>::type > {
85+
void operator()(msgpack::object::with_zone& o, const T& v) const {
86+
uint32_t size = checked_get_container_size(boost::fusion::size(v));
87+
o.type = msgpack::type::ARRAY;
88+
o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size));
89+
o.via.array.size = size;
90+
uint32_t count = 0;
91+
boost::fusion::for_each(v, with_zone_imp(o, count));
92+
}
93+
private:
94+
struct with_zone_imp {
95+
with_zone_imp(msgpack::object::with_zone const& obj, uint32_t& count):obj_(obj), count_(count) {}
96+
template <typename U>
97+
void operator()(U const& v) const {
98+
obj_.via.array.ptr[count_++] = msgpack::object(v, obj_.zone);
99+
}
100+
msgpack::object::with_zone const& obj_;
101+
uint32_t& count_;
102+
};
103+
};
104+
105+
} // namespace adaptor
106+
107+
/// @cond
108+
} // MSGPACK_API_VERSION_NAMESPACE(v1)
109+
/// @endcond
110+
111+
} // namespace msgpack
112+
113+
#endif // MSGPACK_TYPE_BOOST_FUSION_HPP

include/msgpack/object.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,26 +169,26 @@ struct packer_serializer {
169169
} // namespace detail
170170

171171
// Adaptor functors' member functions definitions.
172-
template <typename T>
172+
template <typename T, typename Enabler>
173173
inline
174174
msgpack::object const&
175-
msgpack::adaptor::convert<T>::operator()(msgpack::object const& o, T& v) const {
175+
msgpack::adaptor::convert<T, Enabler>::operator()(msgpack::object const& o, T& v) const {
176176
v.msgpack_unpack(o.convert());
177177
return o;
178178
}
179179

180-
template <typename T>
180+
template <typename T, typename Enabler>
181181
template <typename Stream>
182182
inline
183183
msgpack::packer<Stream>&
184-
msgpack::adaptor::pack<T>::operator()(msgpack::packer<Stream>& o, T const& v) const {
184+
msgpack::adaptor::pack<T, Enabler>::operator()(msgpack::packer<Stream>& o, T const& v) const {
185185
return detail::packer_serializer<Stream, T>::pack(o, v);
186186
}
187187

188-
template <typename T>
188+
template <typename T, typename Enabler>
189189
inline
190190
void
191-
msgpack::adaptor::object_with_zone<T>::operator()(msgpack::object::with_zone& o, T const& v) const {
191+
msgpack::adaptor::object_with_zone<T, Enabler>::operator()(msgpack::object::with_zone& o, T const& v) const {
192192
v.msgpack_object(static_cast<msgpack::object*>(&o), o.zone);
193193
}
194194

include/msgpack/type.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
#if defined(MSGPACK_USE_BOOST)
3838

39+
#include "adaptor/boost/fusion.hpp"
3940
#include "adaptor/boost/optional.hpp"
4041
#include "adaptor/boost/string_ref.hpp"
4142

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ nobase_include_HEADERS += \
5656
../include/msgpack.hpp \
5757
../include/msgpack/adaptor/adaptor_base.hpp \
5858
../include/msgpack/adaptor/bool.hpp \
59+
../include/msgpack/adaptor/boost/fusion.hpp \
5960
../include/msgpack/adaptor/boost/optional.hpp \
6061
../include/msgpack/adaptor/boost/string_ref.hpp \
6162
../include/msgpack/adaptor/char_ptr.hpp \

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ LIST (APPEND check_PROGRAMS
3434

3535
IF (MSGPACK_BOOST)
3636
LIST (APPEND check_PROGRAMS
37+
boost_fusion.cpp
3738
boost_optional.cpp
3839
boost_string_ref.cpp
3940
)

test/Makefile.am

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ check_PROGRAMS = \
2828
limit \
2929
json \
3030
iterator_cpp11 \
31+
boost_fusion \
3132
boost_optional \
3233
boost_string_ref
3334

@@ -84,6 +85,8 @@ json_SOURCES = json.cpp
8485

8586
iterator_cpp11_SOURCES = iterator_cpp11.cpp
8687

88+
boost_fusion_SOURCES = boost_fusion.cpp
89+
8790
boost_optional_SOURCES = boost_optional.cpp
8891

8992
boost_string_ref_SOURCES = boost_string_ref.cpp

test/boost_fusion.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <msgpack.hpp>
2+
#include <sstream>
3+
#include <iterator>
4+
#include <gtest/gtest.h>
5+
6+
#ifdef HAVE_CONFIG_H
7+
#include "config.h"
8+
#endif
9+
10+
#if defined(MSGPACK_USE_BOOST)
11+
12+
#include <boost/fusion/adapted/struct/define_struct.hpp>
13+
14+
BOOST_FUSION_DEFINE_STRUCT(
15+
BOOST_PP_EMPTY(),
16+
mystruct,
17+
(int, f1)
18+
(double, f2)
19+
)
20+
21+
TEST(MSGPACK_BOOST, fusion_pack_unpack_convert)
22+
{
23+
std::stringstream ss;
24+
mystruct val1;
25+
val1.f1 = 42;
26+
val1.f2 = 123.45;
27+
msgpack::pack(ss, val1);
28+
msgpack::unpacked ret;
29+
msgpack::unpack(ret, ss.str().data(), ss.str().size());
30+
mystruct val2 = ret.get().as<mystruct>();
31+
EXPECT_TRUE(val1.f1 == val2.f1);
32+
EXPECT_TRUE(val1.f2 == val2.f2);
33+
}
34+
35+
TEST(MSGPACK_BOOST, object_with_zone_convert)
36+
{
37+
mystruct val1;
38+
val1.f1 = 42;
39+
val1.f2 = 123.45;
40+
msgpack::zone z;
41+
msgpack::object obj(val1, z);
42+
mystruct val2 = obj.as<mystruct>();
43+
EXPECT_TRUE(val1.f1 == val2.f1);
44+
EXPECT_TRUE(val1.f2 == val2.f2);
45+
}
46+
47+
#endif // defined(MSGPACK_USE_BOOST)

0 commit comments

Comments
 (0)