// // MessagePack for C++ static resolution routine // // Copyright (C) 2015-2016 KONDO Takatoshi // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef MSGPACK_V1_TYPE_BOOST_FUSION_HPP #define MSGPACK_V1_TYPE_BOOST_FUSION_HPP #include "msgpack/versioning.hpp" #include "msgpack/adaptor/adaptor_base.hpp" #include "msgpack/adaptor/check_container_size.hpp" #include "msgpack/meta.hpp" #if !defined (MSGPACK_USE_CPP03) #include "msgpack/adaptor/cpp11/tuple.hpp" #endif // #if !defined (MSGPACK_USE_CPP03) #include #include #include #include #include #include namespace msgpack { /// @cond MSGPACK_API_VERSION_NAMESPACE(v1) { /// @endcond namespace adaptor { #if !defined (MSGPACK_USE_CPP03) template struct as< T, typename msgpack::enable_if< boost::fusion::traits::is_sequence::value && boost::mpl::fold< T, boost::mpl::bool_, boost::mpl::if_ < boost::mpl::or_< boost::mpl::_1, msgpack::has_as >, boost::mpl::bool_, boost::mpl::bool_ > >::type::value >::type > { T operator()(msgpack::object const& o) const { if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.via.array.size != checked_get_container_size(boost::mpl::size::value)) { throw msgpack::type_error(); } using tuple_t = decltype(to_tuple(std::declval(), gen_seq::value>())); return to_t( o.as(), msgpack::gen_seq::value>()); } template static std::tuple< typename std::remove_reference< typename boost::fusion::result_of::at_c::type >::type...> to_tuple(U const& u, seq) { return std::make_tuple(boost::fusion::at_c(u)...); } template static T to_t(U const& u, seq) { return T(std::get(u)...); } }; #endif // !defined (MSGPACK_USE_CPP03) template struct convert::value>::type > { msgpack::object const& operator()(msgpack::object const& o, T& v) const { if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.via.array.size != checked_get_container_size(boost::fusion::size(v))) { throw msgpack::type_error(); } uint32_t index = 0; boost::fusion::for_each(v, convert_imp(o, index)); return o; } private: struct convert_imp { convert_imp(msgpack::object const& obj, uint32_t& index):obj_(obj), index_(index) {} template void operator()(U& v) const { msgpack::adaptor::convert()(obj_.via.array.ptr[index_++], v); } private: msgpack::object const& obj_; uint32_t& index_; }; }; template struct pack::value>::type > { template msgpack::packer& operator()(msgpack::packer& o, const T& v) const { uint32_t size = checked_get_container_size(boost::fusion::size(v)); o.pack_array(size); boost::fusion::for_each(v, pack_imp(o)); return o; } private: template struct pack_imp { pack_imp(msgpack::packer& stream):stream_(stream) {} template void operator()(U const& v) const { stream_.pack(v); } private: msgpack::packer& stream_; }; }; template struct object_with_zone::value>::type > { void operator()(msgpack::object::with_zone& o, const T& v) const { uint32_t size = checked_get_container_size(boost::fusion::size(v)); o.type = msgpack::type::ARRAY; o.via.array.ptr = static_cast(o.zone.allocate_align(sizeof(msgpack::object)*size)); o.via.array.size = size; uint32_t count = 0; boost::fusion::for_each(v, with_zone_imp(o, count)); } private: struct with_zone_imp { with_zone_imp(msgpack::object::with_zone const& obj, uint32_t& count):obj_(obj), count_(count) {} template void operator()(U const& v) const { obj_.via.array.ptr[count_++] = msgpack::object(v, obj_.zone); } msgpack::object::with_zone const& obj_; uint32_t& count_; }; }; } // namespace adaptor /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v1) /// @endcond } // namespace msgpack #endif // MSGPACK_V1_TYPE_BOOST_FUSION_HPP