diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b91fb7db..3e92db3d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -166,6 +166,7 @@ IF (MSGPACK_ENABLE_CXX) include/msgpack/adaptor/adaptor_base.hpp include/msgpack/adaptor/bool.hpp include/msgpack/adaptor/boost/fusion.hpp + include/msgpack/adaptor/boost/msgpack_variant.hpp include/msgpack/adaptor/boost/optional.hpp include/msgpack/adaptor/boost/string_ref.hpp include/msgpack/adaptor/char_ptr.hpp diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 5fa8a3f64..e447d1a25 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,3 +1,4 @@ ADD_SUBDIRECTORY (c) ADD_SUBDIRECTORY (cpp03) ADD_SUBDIRECTORY (cpp11) +ADD_SUBDIRECTORY (boost) diff --git a/example/boost/CMakeLists.txt b/example/boost/CMakeLists.txt new file mode 100644 index 000000000..57a31acc5 --- /dev/null +++ b/example/boost/CMakeLists.txt @@ -0,0 +1,24 @@ +IF (MSGPACK_BOOST) + LIST (APPEND exec_PROGRAMS + msgpack_variant_capitalize.cpp + msgpack_variant_mapbased.cpp + ) +ENDIF () + +FOREACH (source_file ${exec_PROGRAMS}) + GET_FILENAME_COMPONENT (source_file_we ${source_file} NAME_WE) + ADD_EXECUTABLE ( + ${source_file_we} + ${source_file} + ) + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -Wno-mismatched-tags -g -O3") + ENDIF () + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + STRING(REGEX REPLACE "/W[0-4]" "/W3 /WX" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + ELSE () + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX") + ENDIF () + ENDIF () +ENDFOREACH () diff --git a/example/boost/msgpack_variant_capitalize.cpp b/example/boost/msgpack_variant_capitalize.cpp new file mode 100644 index 000000000..317e7ac09 --- /dev/null +++ b/example/boost/msgpack_variant_capitalize.cpp @@ -0,0 +1,102 @@ +// MessagePack for C++ example +// +// Copyright (C) 2015 KONDO Takatoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include +#include +#include +#include +#include + +#include + +struct user { + std::string name; + int age; + std::string address; + MSGPACK_DEFINE(name, age, address); +}; + +struct proc:boost::static_visitor { + void operator()(std::string& v) const { + std::cout << " match std::string& v" << std::endl; + std::cout << " v: " << v << std::endl; + std::cout << " capitalize" << std::endl; + for (std::string::iterator it = v.begin(), end = v.end(); + it != end; + ++it) { + *it = std::toupper(*it); + } + } + void operator()(std::vector& v) const { + std::cout << "match vector (msgpack::type::ARRAY)" << std::endl; + std::vector::iterator it = v.begin(); + std::vector::const_iterator end = v.end(); + for (; it != end; ++it) { + boost::apply_visitor(*this, *it); + } + } + template + void operator()(T const&) const { + std::cout << " match others" << std::endl; + } +}; + +void print(std::string const& buf) { + for (std::string::const_iterator it = buf.begin(), end = buf.end(); + it != end; + ++it) { + std::cout + << std::setw(2) + << std::hex + << std::setfill('0') + << (static_cast(*it) & 0xff) + << ' '; + } + std::cout << std::dec << std::endl; +} + + +int main() { + std::stringstream ss1; + user u; + u.name = "Takatoshi Kondo"; + u.age = 42; + u.address = "Tokyo, JAPAN"; + + std::cout << "Packing object." << std::endl; + msgpack::pack(ss1, u); + print(ss1.str()); + + msgpack::unpacked unp1 = msgpack::unpack(ss1.str().data(), ss1.str().size()); + msgpack::object const& obj1 = unp1.get(); + std::cout << "Unpacked msgpack object." << std::endl; + std::cout << obj1 << std::endl; + + msgpack::type::variant v = obj1.as(); + std::cout << "Applying proc..." << std::endl; + boost::apply_visitor(proc(), v); + + std::stringstream ss2; + std::cout << "Packing modified object." << std::endl; + msgpack::pack(ss2, v); + print(ss2.str()); + + msgpack::unpacked unp2 = msgpack::unpack(ss2.str().data(), ss2.str().size()); + msgpack::object const& obj2 = unp2.get(); + std::cout << "Modified msgpack object." << std::endl; + std::cout << obj2 << std::endl; +} diff --git a/example/boost/msgpack_variant_mapbased.cpp b/example/boost/msgpack_variant_mapbased.cpp new file mode 100644 index 000000000..a4d4ddce0 --- /dev/null +++ b/example/boost/msgpack_variant_mapbased.cpp @@ -0,0 +1,100 @@ +// MessagePack for C++ example +// +// Copyright (C) 2015 KONDO Takatoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include +#include +#include + +#include + +struct user { + std::string name; + int age; + std::string address; + MSGPACK_DEFINE_MAP(name, age, address); +}; + +struct proc:boost::static_visitor { + // msgpack::type::MAP is converted to std::multimap, not std::map. + void operator()(std::multimap& v) const { + std::cout << "match map" << std::endl; + std::multimap::iterator it = v.begin(); + std::multimap::iterator end = v.end(); + while(it != end) { + boost::string_ref const& key = it->first.as_boost_string_ref(); + if (key == "name") { + boost::string_ref const& value = it->second.as_boost_string_ref(); + if (value == "Takatoshi Kondo") { + // You can add values to msgpack::type::variant_ref. + v.insert( + std::multimap::value_type( + "role", + "msgpack-c committer" + ) + ); + } + ++it; + } + else if (key == "age") { + // You can remove key-value pair from msgpack::type::variant_ref + +#if defined(MSGPACK_USE_CPP03) + v.erase(it++); +#else // defined(MSGPACK_USE_CPP03) +# if MSGPACK_LIB_STD_CXX + it = v.erase(std::multimap::const_iterator(it)); +# else // MSGPACK_LIB_STD_CXX + it = v.erase(it); +# endif // MSGPACK_LIB_STD_CXX +#endif // defined(MSGPACK_USE_CPP03) + } + else if (key == "address") { + // When you want to append string + // "Tokyo" -> "Tokyo, JAPAN" + // Use msgpack::type::variant instead of msgpack::type::variant_ref + // or do as follows: + boost::string_ref const& value = it->second.as_boost_string_ref(); + it->second = std::string(&value.front(), value.size()) + ", JAPAN"; + ++it; + } + } + } + template + void operator()(T const&) const { + std::cout << " match others" << std::endl; + } +}; + +int main() { + std::stringstream ss; + user u; + u.name = "Takatoshi Kondo"; + u.age = 42; + u.address = "Tokyo"; + msgpack::pack(ss, u); + + msgpack::unpacked unp = msgpack::unpack(ss.str().data(), ss.str().size()); + msgpack::object const& obj = unp.get(); + std::cout << "Unpacked msgpack object." << std::endl; + std::cout << obj << std::endl; + msgpack::type::variant_ref v = obj.as(); + std::cout << "Applying proc..." << std::endl; + boost::apply_visitor(proc(), v); + msgpack::zone z; + std::cout << "Applied msgpack object." << std::endl; + std::cout << msgpack::object(v, z) << std::endl; +} diff --git a/include/msgpack/adaptor/boost/msgpack_variant.hpp b/include/msgpack/adaptor/boost/msgpack_variant.hpp new file mode 100644 index 000000000..4bbeebd21 --- /dev/null +++ b/include/msgpack/adaptor/boost/msgpack_variant.hpp @@ -0,0 +1,438 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2015 KONDO Takatoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_BOOST_MSGPACK_VARIANT_HPP +#define MSGPACK_TYPE_BOOST_MSGPACK_VARIANT_HPP + +#if defined(MSGPACK_USE_BOOST) + +#include "msgpack/versioning.hpp" +#include "msgpack/adaptor/adaptor_base.hpp" +#include "msgpack/adaptor/check_container_size.hpp" +#include "msgpack/adaptor/boost/string_ref.hpp" + +#include "msgpack/adaptor/nil.hpp" +#include "msgpack/adaptor/bool.hpp" +#include "msgpack/adaptor/int.hpp" +#include "msgpack/adaptor/float.hpp" +#include "msgpack/adaptor/string.hpp" +#include "msgpack/adaptor/vector_char.hpp" +#include "msgpack/adaptor/raw.hpp" +#include "msgpack/adaptor/ext.hpp" +#include "msgpack/adaptor/vector.hpp" +#include "msgpack/adaptor/map.hpp" + +#include +#include + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +namespace type { + + +template +struct basic_variant : + boost::variant< + nil, // NIL + bool, // BOOL + int64_t, // NEGATIVE_INTEGER + uint64_t, // POSITIVE_INTEGER + double, // FLOAT + std::string, // STR +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + boost::string_ref, // STR +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + std::vector, // BIN + msgpack::type::raw_ref, // BIN + ext, // EXT + ext_ref, // EXT + boost::recursive_wrapper > >, // ARRAY + boost::recursive_wrapper, basic_variant > >, // MAP + boost::recursive_wrapper, basic_variant > >// MAP + >, + private boost::totally_ordered > { + typedef boost::variant< + nil, // NIL + bool, // BOOL + int64_t, // NEGATIVE_INTEGER + uint64_t, // POSITIVE_INTEGER + double, // FLOAT + std::string, // STR +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + boost::string_ref, // STR +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + std::vector, // BIN + msgpack::type::raw_ref, // BIN + ext, // EXT + ext_ref, // EXT + boost::recursive_wrapper > >, // ARRAY + boost::recursive_wrapper, basic_variant > >, // MAP + boost::recursive_wrapper, basic_variant > >// MAP + > base; + basic_variant() {} + template + basic_variant(T const& t):base(t) {} + basic_variant(char const* p):base(std::string(p)) {} + basic_variant(char v) { + int_init(v); + } + basic_variant(signed char v) { + int_init(v); + } + basic_variant(unsigned char v):base(uint64_t(v)) {} + basic_variant(signed int v) { + int_init(v); + } + basic_variant(unsigned int v):base(uint64_t(v)) {} + basic_variant(signed long v) { + int_init(v); + } + basic_variant(unsigned long v):base(uint64_t(v)) {} + basic_variant(signed long long v) { + int_init(v); + } + basic_variant(unsigned long long v):base(uint64_t(v)) {} + + bool is_nil() const { + return boost::get(this); + } + bool is_bool() const { + return boost::get(this); + } + bool is_int64_t() const { + return boost::get(this); + } + bool is_uint64_t() const { + return boost::get(this); + } + bool is_double() const { + return boost::get(this); + } + bool is_string() const { + return boost::get(this); + } +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + bool is_boost_string_ref() const { + return boost::get(this); + } +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + bool is_vector_char() const { + return boost::get >(this); + } + bool is_vector_char() { + return boost::get >(this); + } + bool is_raw_ref() const { + return boost::get(this); + } + bool is_ext() const { + return boost::get(this); + } + bool is_ext_ref() const { + return boost::get(this); + } + bool is_vector() const { + return boost::get > >(this); + } + bool is_map() const { + return boost::get, basic_variant > >(this); + } + bool is_multimap() const { + return boost::get, basic_variant > >(this); + } + + bool as_bool() const { + return boost::get(*this); + } + int64_t as_int64_t() const { + return boost::get(*this); + } + int64_t& as_int64_t() { + return boost::get(*this); + } + uint64_t as_uint64_t() const { + return boost::get(*this); + } + uint64_t& as_uint64_t() { + return boost::get(*this); + } + double as_double() const { + return boost::get(*this); + } + double& as_double() { + return boost::get(*this); + } + std::string const& as_string() const { + return boost::get(*this); + } + std::string& as_string() { + return boost::get(*this); + } +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + boost::string_ref const& as_boost_string_ref() const { + return boost::get(*this); + } + boost::string_ref& as_boost_string_ref() { + return boost::get(*this); + } +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + std::vector const& as_vector_char() const { + return boost::get >(*this); + } + std::vector& as_vector_char() { + return boost::get >(*this); + } + raw_ref const& as_raw_ref() const { + return boost::get(*this); + } + ext const& as_ext() const { + return boost::get(*this); + } + ext& as_ext() { + return boost::get(*this); + } + ext_ref const& as_ext_ref() const { + return boost::get(*this); + } + std::vector > const& as_vector() const { + return boost::get > >(*this); + } + std::vector >& as_vector() { + return boost::get > >(*this); + } + std::map, basic_variant > const& as_map() const { + return boost::get, basic_variant > >(*this); + } + std::map, basic_variant >& as_map() { + return boost::get, basic_variant > >(*this); + } + std::multimap, basic_variant > const& as_multimap() const { + return boost::get, basic_variant > >(*this); + } + std::multimap, basic_variant >& as_multimap() { + return boost::get, basic_variant > >(*this); + } +private: + template + void int_init(T v) { + if (v < 0) { + static_cast(*this) = int64_t(v); + } + else { + static_cast(*this) = uint64_t(v); + } + } +}; + +template +inline bool operator<(basic_variant const& lhs, basic_variant const& rhs) { + return + static_cast::base const&>(lhs) < + static_cast::base const&>(rhs); +} + +template +inline bool operator==(basic_variant const& lhs, basic_variant const& rhs) { + return + static_cast::base const&>(lhs) == + static_cast::base const&>(rhs); +} + +typedef basic_variant, ext> variant; +typedef basic_variant< +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + boost::string_ref, +#else // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + std::string, +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + raw_ref, ext_ref> variant_ref; + +} // namespace type + +namespace adaptor { + +#if !defined (MSGPACK_USE_CPP03) + +template +struct as > { + msgpack::type::basic_variant operator()(msgpack::object const& o) const { + switch(o.type) { + case type::NIL: + return o.as(); + case type::BOOLEAN: + return o.as(); + case type::POSITIVE_INTEGER: + return o.as(); + case type::NEGATIVE_INTEGER: + return o.as(); + case type::FLOAT: + return o.as(); + case type::STR: + return o.as(); + case type::BIN: + return o.as(); + case type::EXT: + return o.as(); + case type::ARRAY: + return o.as > >(); + case type::MAP: + return o.as, msgpack::type::basic_variant > >(); + default: + break; + } + return msgpack::type::basic_variant(); + } +}; + +#endif // !defined (MSGPACK_USE_CPP03) + + +template +struct convert > { + msgpack::object const& operator()( + msgpack::object const& o, + msgpack::type::basic_variant& v) const { + switch(o.type) { + case type::NIL: + v = o.as(); + break; + case type::BOOLEAN: + v = o.as(); + break; + case type::POSITIVE_INTEGER: + v = o.as(); + break; + case type::NEGATIVE_INTEGER: + v = o.as(); + break; + case type::FLOAT: + v = o.as(); + break; + case type::STR: + v = o.as(); + break; + case type::BIN: + v = o.as(); + break; + case type::EXT: + v = o.as(); + break; + case type::ARRAY: + v = o.as > >(); + break; + case type::MAP: + v = o.as, msgpack::type::basic_variant > >(); + break; + default: + break; + } + return o; + } +}; + +namespace detail { + +template +struct pack_imp : boost::static_visitor { + template + void operator()(T const& value) const { + pack()(o_, value); + } + pack_imp(packer& o):o_(o) {} + packer& o_; +}; + +} // namespace detail + +template +struct pack > { + template + msgpack::packer& operator()(msgpack::packer& o, const msgpack::type::basic_variant& v) const { + boost::apply_visitor(detail::pack_imp(o), v); + return o; + } +}; + +namespace detail { + +struct object_imp : boost::static_visitor { + void operator()(msgpack::type::nil const& v) const { + object()(o_, v); + } + void operator()(bool const& v) const { + object()(o_, v); + } + void operator()(uint64_t const& v) const { + object()(o_, v); + } + void operator()(int64_t const& v) const { + object()(o_, v); + } + void operator()(double const& v) const { + object()(o_, v); + } + template + void operator()(T const&) const { + throw msgpack::type_error(); + } + object_imp(msgpack::object& o):o_(o) {} + msgpack::object& o_; +}; + +} // namespace detail + +template +struct object > { + void operator()(msgpack::object& o, const msgpack::type::basic_variant& v) const { + boost::apply_visitor(detail::object_imp(o), v); + } +}; + +namespace detail { + +struct object_with_zone_imp : boost::static_visitor { + template + void operator()(T const& v) const { + object_with_zone()(o_, v); + } + object_with_zone_imp(msgpack::object::with_zone& o):o_(o) {} + msgpack::object::with_zone& o_; +}; + +} // namespace detail + +template +struct object_with_zone > { + void operator()(msgpack::object::with_zone& o, const msgpack::type::basic_variant& v) const { + boost::apply_visitor(detail::object_with_zone_imp(o), v); + } +}; + +} // namespace adaptor + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_USE_BOOST +#endif // MSGPACK_TYPE_BOOST_MSGPACK_VARIANT_HPP diff --git a/include/msgpack/adaptor/nil.hpp b/include/msgpack/adaptor/nil.hpp index 2f99f1ad6..607f767a5 100644 --- a/include/msgpack/adaptor/nil.hpp +++ b/include/msgpack/adaptor/nil.hpp @@ -31,6 +31,14 @@ namespace type { struct nil { }; +inline bool operator<(nil const& lhs, nil const& rhs) { + return &lhs < &rhs; +} + +inline bool operator==(nil const& lhs, nil const& rhs) { + return &lhs == &rhs; +} + } // namespace type namespace adaptor { diff --git a/include/msgpack/type.hpp b/include/msgpack/type.hpp index 4619fe0f1..7143741e9 100644 --- a/include/msgpack/type.hpp +++ b/include/msgpack/type.hpp @@ -41,6 +41,7 @@ #if defined(MSGPACK_USE_BOOST) #include "adaptor/boost/fusion.hpp" +#include "adaptor/boost/msgpack_variant.hpp" #include "adaptor/boost/optional.hpp" #include "adaptor/boost/string_ref.hpp" diff --git a/src/Makefile.am b/src/Makefile.am index b15c31a07..8eaad74e3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -175,6 +175,7 @@ nobase_include_HEADERS += \ ../include/msgpack/adaptor/adaptor_base.hpp \ ../include/msgpack/adaptor/bool.hpp \ ../include/msgpack/adaptor/boost/fusion.hpp \ + ../include/msgpack/adaptor/boost/msgpack_variant.hpp \ ../include/msgpack/adaptor/boost/optional.hpp \ ../include/msgpack/adaptor/boost/string_ref.hpp \ ../include/msgpack/adaptor/char_ptr.hpp \ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f0888588d..a0b8e28b4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -37,6 +37,7 @@ LIST (APPEND check_PROGRAMS IF (MSGPACK_BOOST) LIST (APPEND check_PROGRAMS boost_fusion.cpp + boost_variant.cpp boost_optional.cpp boost_string_ref.cpp ) diff --git a/test/Makefile.am b/test/Makefile.am index 165a5e28a..37f9de634 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -30,6 +30,7 @@ check_PROGRAMS = \ check_PROGRAMS += \ boost_fusion \ + boost_variant \ boost_optional \ boost_string_ref @@ -77,6 +78,7 @@ shared_ptr_cpp11_SOURCES = shared_ptr_cpp11.cpp unique_ptr_cpp11_SOURCES = unique_ptr_cpp11.cpp boost_fusion_SOURCES = boost_fusion.cpp +boost_variant_SOURCES = boost_variant.cpp boost_optional_SOURCES = boost_optional.cpp boost_string_ref_SOURCES = boost_string_ref.cpp diff --git a/test/boost_variant.cpp b/test/boost_variant.cpp new file mode 100644 index 000000000..abc574ce3 --- /dev/null +++ b/test/boost_variant.cpp @@ -0,0 +1,810 @@ +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(MSGPACK_USE_BOOST) + +const double kEPS = 1e-10; + +// nil + +TEST(MSGPACK_BOOST, pack_convert_variant_nil) +{ + std::stringstream ss; + msgpack::type::variant val1 = msgpack::type::nil(); + EXPECT_TRUE(val1.is_nil()); + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_nil()); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_variant_nil) +{ + msgpack::type::variant val1 = msgpack::type::nil(); + EXPECT_TRUE(val1.is_nil()); + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_nil()); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_nil) +{ + msgpack::zone z; + msgpack::type::variant val1 = msgpack::type::nil(); + EXPECT_TRUE(val1.is_nil()); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_nil()); + EXPECT_NO_THROW(boost::get(val2)); +} + +// nil (default constructor) + +TEST(MSGPACK_BOOST, pack_convert_variant_nil_default) +{ + std::stringstream ss; + msgpack::type::variant val1; + EXPECT_TRUE(val1.is_nil()); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_nil()); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_variant_nil_default) +{ + msgpack::type::variant val1; + EXPECT_TRUE(val1.is_nil()); + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_nil()); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_nil_default) +{ + msgpack::zone z; + msgpack::type::variant val1; + EXPECT_TRUE(val1.is_nil()); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_nil()); + EXPECT_NO_THROW(boost::get(val2)); +} + +// bool + +TEST(MSGPACK_BOOST, pack_convert_variant_bool) +{ + std::stringstream ss; + msgpack::type::variant val1 = true; + EXPECT_TRUE(val1.is_bool()); + EXPECT_TRUE(val1.as_bool()); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_bool()); + EXPECT_TRUE(val2.as_bool()); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); + // Tests for totally ordered + EXPECT_FALSE(val1 != val2); + EXPECT_FALSE(val1 < val2); + EXPECT_FALSE(val1 > val2); + EXPECT_TRUE(val1 <= val2); + EXPECT_TRUE(val1 >= val2); +} + +TEST(MSGPACK_BOOST, object_variant_bool) +{ + msgpack::type::variant val1 = true; + EXPECT_TRUE(val1.is_bool()); + EXPECT_TRUE(val1.as_bool()); + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_bool()); + EXPECT_TRUE(val2.as_bool()); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_bool) +{ + msgpack::zone z; + msgpack::type::variant val1 = true; + EXPECT_TRUE(val1.is_bool()); + EXPECT_TRUE(val1.as_bool()); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_bool()); + EXPECT_TRUE(val2.as_bool()); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// positive integer + +TEST(MSGPACK_BOOST, pack_convert_variant_positive_integer) +{ + std::stringstream ss; + msgpack::type::variant val1 = 123; + EXPECT_TRUE(val1.is_uint64_t()); + EXPECT_EQ(val1.as_uint64_t(), 123); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_uint64_t()); + EXPECT_EQ(val2.as_uint64_t(), 123); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_variant_positive_integer) +{ + msgpack::type::variant val1 = 123; + EXPECT_TRUE(val1.is_uint64_t()); + EXPECT_EQ(val1.as_uint64_t(), 123); + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_uint64_t()); + EXPECT_EQ(val2.as_uint64_t(), 123); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_positive_integer) +{ + msgpack::zone z; + msgpack::type::variant val1 = 123; + EXPECT_TRUE(val1.is_uint64_t()); + EXPECT_EQ(val1.as_uint64_t(), 123); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_uint64_t()); + EXPECT_EQ(val2.as_uint64_t(), 123); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// negative integer + +TEST(MSGPACK_BOOST, pack_convert_variant_negative_integer) +{ + std::stringstream ss; + msgpack::type::variant val1 = -123; + EXPECT_TRUE(val1.is_int64_t()); + EXPECT_EQ(val1.as_int64_t(), -123); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_int64_t()); + EXPECT_EQ(val2.as_int64_t(), -123); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_variant_negative_integer) +{ + msgpack::type::variant val1 = -123; + EXPECT_TRUE(val1.is_int64_t()); + EXPECT_EQ(val1.as_int64_t(), -123); + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_int64_t()); + EXPECT_EQ(val2.as_int64_t(), -123); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_negative_integer) +{ + msgpack::zone z; + msgpack::type::variant val1 = -123; + EXPECT_TRUE(val1.is_int64_t()); + EXPECT_EQ(val1.as_int64_t(), -123); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_int64_t()); + EXPECT_EQ(val2.as_int64_t(), -123); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// float + +TEST(MSGPACK_BOOST, pack_convert_variant_float) +{ + std::stringstream ss; + msgpack::type::variant val1 = 12.34; + EXPECT_TRUE(val1.is_double()); + EXPECT_TRUE(fabs(12.34 - val1.as_double()) <= kEPS); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_double()); + EXPECT_TRUE(fabs(12.34 - val2.as_double()) <= kEPS); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(fabs(val2.as_double() - val2.as_double()) <= kEPS); +} + +TEST(MSGPACK_BOOST, object_variant_float) +{ + msgpack::type::variant val1 = 12.34; + EXPECT_TRUE(val1.is_double()); + EXPECT_TRUE(fabs(12.34 - val1.as_double()) <= kEPS); + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_double()); + EXPECT_TRUE(fabs(12.34 - val2.as_double()) <= kEPS); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(fabs(val2.as_double() - val2.as_double()) <= kEPS); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_float) +{ + msgpack::zone z; + msgpack::type::variant val1 = 12.34; + EXPECT_TRUE(val1.is_double()); + EXPECT_TRUE(fabs(12.34 - val1.as_double()) <= kEPS); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_double()); + EXPECT_TRUE(fabs(12.34 - val2.as_double()) <= kEPS); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(fabs(val2.as_double() - val2.as_double()) <= kEPS); +} + +// str + +TEST(MSGPACK_BOOST, pack_convert_variant_str) +{ + std::stringstream ss; + msgpack::type::variant val1 = "ABC"; + EXPECT_TRUE(val1.is_string()); + EXPECT_EQ(val1.as_string(), "ABC"); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_string()); + EXPECT_EQ(val2.as_string(), "ABC"); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + + +TEST(MSGPACK_BOOST, object_with_zone_variant_str) +{ + msgpack::zone z; + msgpack::type::variant val1 = "ABC"; + EXPECT_TRUE(val1.is_string()); + EXPECT_EQ(val1.as_string(), "ABC"); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_string()); + EXPECT_EQ(val2.as_string(), "ABC"); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + +TEST(MSGPACK_BOOST, object_with_zone_variant_str_ref) +{ + // You can use boost::string_ref with msgpack::type::variant. + msgpack::zone z; + std::string s = "ABC"; + boost::string_ref sr(s); + msgpack::type::variant val1(sr); + EXPECT_TRUE(val1.is_boost_string_ref()); + EXPECT_EQ(val1.as_boost_string_ref(), "ABC"); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + // Coverted as std::string. + EXPECT_TRUE(val2.is_string()); + EXPECT_EQ(val2.as_string(), "ABC"); + EXPECT_NO_THROW(boost::get(val2)); + // boost::string_ref and std::string are different. + EXPECT_FALSE(val1 == val2); +} + +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + +// bin + +TEST(MSGPACK_BOOST, pack_convert_variant_bin) +{ + std::stringstream ss; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::variant val1 = v; + EXPECT_TRUE(val1.is_vector_char()); + EXPECT_EQ(val1.as_vector_char(), v); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_vector_char()); + EXPECT_EQ(val2.as_vector_char(), v); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + + + +TEST(MSGPACK_BOOST, object_with_zone_variant_bin) +{ + msgpack::zone z; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::variant val1 = v; + EXPECT_TRUE(val1.is_vector_char()); + EXPECT_EQ(val1.as_vector_char(), v); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_vector_char()); + EXPECT_EQ(val2.as_vector_char(), v); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + +TEST(MSGPACK_BOOST, object_with_zone_variant_raw_ref) +{ + // You can use boost::string_ref with msgpack::type::variant. + msgpack::zone z; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::raw_ref rr(&v.front(), v.size()); + msgpack::type::variant val1 = rr; + EXPECT_TRUE(val1.is_raw_ref()); + EXPECT_EQ(val1.as_raw_ref(), msgpack::type::raw_ref(&v.front(), v.size())); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + // Coverted as std::vector. + EXPECT_TRUE(val2.is_vector_char()); + EXPECT_EQ(val2.as_vector_char(), v); + EXPECT_NO_THROW(boost::get >(val2)); + // msgpack::type::raw_ref and std::vector are different. + EXPECT_FALSE(val1 == val2); +} + +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + +// ext + +TEST(MSGPACK_BOOST, pack_convert_variant_ext) +{ + std::stringstream ss; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::ext e(42, v.data(), v.size()); + msgpack::type::variant val1(e); + EXPECT_TRUE(val1.is_ext()); + EXPECT_EQ(val1.as_ext(), e); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_ext()); + EXPECT_EQ(val2.as_ext(), e); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + + + +TEST(MSGPACK_BOOST, object_with_zone_variant_ext) +{ + msgpack::zone z; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::ext e(42, v.data(), v.size()); + msgpack::type::variant val1(e); + EXPECT_TRUE(val1.is_ext()); + EXPECT_EQ(val1.as_ext(), e); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_ext()); + EXPECT_EQ(val2.as_ext(), e); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ext_ref) +{ + // You can use msgpack::type::ext_ref with msgpack::type::variant. + msgpack::zone z; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::ext_ref e(v.data(), v.size()); + msgpack::type::variant val1(e); + EXPECT_TRUE(val1.is_ext_ref()); + EXPECT_EQ(val1.as_ext_ref(), e); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + // Coverted as msgpack::type::ext. + EXPECT_TRUE(val2.is_ext()); + EXPECT_EQ(val2.as_ext(), e); + EXPECT_NO_THROW(boost::get(val2)); + // msgpack::type::ext_ref and msgpack::type::ext are different. + EXPECT_FALSE(val1 == val2); +} + +// array + +TEST(MSGPACK_BOOST, pack_convert_variant_array) +{ + std::stringstream ss; + std::vector v; + v.push_back(msgpack::type::variant(1)); + v.push_back(msgpack::type::variant(-1)); + v.push_back(msgpack::type::variant("ABC")); + msgpack::type::variant val1 = v; + EXPECT_TRUE(val1.is_vector()); + EXPECT_EQ(val1.as_vector(), v); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_vector()); + EXPECT_EQ(val2.as_vector(), v); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_array) +{ + msgpack::zone z; + std::vector v; + v.push_back(msgpack::type::variant(1)); + v.push_back(msgpack::type::variant(-1)); + v.push_back(msgpack::type::variant("ABC")); + msgpack::type::variant val1 = v; + EXPECT_TRUE(val1.is_vector()); + EXPECT_EQ(val1.as_vector(), v); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_vector()); + EXPECT_EQ(val2.as_vector(), v); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + +// multimap + +TEST(MSGPACK_BOOST, pack_convert_variant_map) +{ + std::stringstream ss; + typedef std::multimap multimap_t; + multimap_t v; + v.insert(multimap_t::value_type(msgpack::type::variant(1), msgpack::type::variant(-1))); + v.insert(multimap_t::value_type(msgpack::type::variant("ABC"), msgpack::type::variant("DEF"))); + msgpack::type::variant val1 = v; + EXPECT_TRUE(val1.is_multimap()); + EXPECT_EQ(val1.as_multimap(), v); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_TRUE(val2.is_multimap()); + EXPECT_EQ(val2.as_multimap(), v); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_map) +{ + msgpack::zone z; + typedef std::multimap multimap_t; + multimap_t v; + v.insert(multimap_t::value_type(msgpack::type::variant(1), msgpack::type::variant(-1))); + v.insert(multimap_t::value_type(msgpack::type::variant("ABC"), msgpack::type::variant("DEF"))); + msgpack::type::variant val1 = v; + EXPECT_TRUE(val1.is_multimap()); + EXPECT_EQ(val1.as_multimap(), v); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_TRUE(val2.is_multimap()); + EXPECT_EQ(val2.as_multimap(), v); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// variant_ref + +// str + +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_str) +{ + std::stringstream ss; + std::string s("ABC"); + boost::string_ref sr(s); + msgpack::type::variant_ref val1 = sr; + EXPECT_TRUE(val1.is_boost_string_ref()); + EXPECT_EQ(val1.as_boost_string_ref(), sr); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_TRUE(val2.is_boost_string_ref()); + EXPECT_EQ(val2.as_boost_string_ref(), sr); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + + + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_str) +{ + msgpack::zone z; + std::string s("ABC"); + boost::string_ref sr(s); + msgpack::type::variant_ref val1 = sr; + EXPECT_TRUE(val1.is_boost_string_ref()); + EXPECT_EQ(val1.as_boost_string_ref(), sr); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_TRUE(val2.is_boost_string_ref()); + EXPECT_EQ(val2.as_boost_string_ref(), sr); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + +// bin + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_bin) +{ + std::stringstream ss; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::raw_ref rr(v.data(), v.size()); + msgpack::type::variant_ref val1 = rr; + EXPECT_TRUE(val1.is_raw_ref()); + EXPECT_EQ(val1.as_raw_ref(), rr); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_TRUE(val2.is_raw_ref()); + EXPECT_EQ(val2.as_raw_ref(), rr); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + + + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_bin) +{ + msgpack::zone z; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::raw_ref rr(v.data(), v.size()); + msgpack::type::variant_ref val1 = rr; + EXPECT_TRUE(val1.is_raw_ref()); + EXPECT_EQ(val1.as_raw_ref(), rr); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_TRUE(val2.is_raw_ref()); + EXPECT_EQ(val2.as_raw_ref(), rr); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// ext + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_ext) +{ + std::stringstream ss; + std::vector v; + v.push_back(static_cast(42)); + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::ext_ref er(v.data(), v.size()); + msgpack::type::variant_ref val1(er); + EXPECT_TRUE(val1.is_ext_ref()); + EXPECT_EQ(val1.as_ext_ref(), er); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val2.is_ext_ref()); + EXPECT_EQ(val2.as_ext_ref(), er); + EXPECT_TRUE(val1 == val2); +} + + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_ext) +{ + msgpack::zone z; + std::vector v; + v.push_back(static_cast(42)); + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::ext_ref er(v.data(), v.size()); + msgpack::type::variant_ref val1(er); + EXPECT_TRUE(val1.is_ext_ref()); + EXPECT_EQ(val1.as_ext_ref(), er); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_TRUE(val2.is_ext_ref()); + EXPECT_EQ(val2.as_ext_ref(), er); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// array + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_array) +{ + std::stringstream ss; + std::vector v; + v.push_back(msgpack::type::variant_ref(1)); + v.push_back(msgpack::type::variant_ref(-1)); + std::string s("ABC"); +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + v.push_back(msgpack::type::variant_ref(boost::string_ref(s))); +#else // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + v.push_back(msgpack::type::variant_ref(s)); +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + msgpack::type::variant_ref val1 = v; + EXPECT_TRUE(val1.is_vector()); + EXPECT_EQ(val1.as_vector(), v); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_TRUE(val2.is_vector()); + EXPECT_EQ(val2.as_vector(), v); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_array) +{ + msgpack::zone z; + std::vector v; + v.push_back(msgpack::type::variant_ref(1)); + v.push_back(msgpack::type::variant_ref(-1)); + std::string s("ABC"); +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + v.push_back(msgpack::type::variant_ref(boost::string_ref(s))); +#else // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + v.push_back(msgpack::type::variant_ref(s)); +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + msgpack::type::variant_ref val1 = v; + EXPECT_TRUE(val1.is_vector()); + EXPECT_EQ(val1.as_vector(), v); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_TRUE(val2.is_vector()); + EXPECT_EQ(val2.as_vector(), v); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + +// multimap + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_map) +{ + std::stringstream ss; + typedef std::multimap multimap_t; + multimap_t v; + v.insert(multimap_t::value_type(msgpack::type::variant_ref(1), msgpack::type::variant_ref(-1))); + std::string s1("ABC"); + std::string s2("DEF"); +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + v.insert(multimap_t::value_type(msgpack::type::variant_ref(boost::string_ref(s1)), msgpack::type::variant_ref(boost::string_ref(s2)))); +#else // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + v.insert(multimap_t::value_type(msgpack::type::variant_ref(s1), msgpack::type::variant_ref(s2))); +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + msgpack::type::variant_ref val1 = v; + EXPECT_TRUE(val1.is_multimap()); + EXPECT_EQ(val1.as_multimap(), v); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_TRUE(val2.is_multimap()); + EXPECT_EQ(val2.as_multimap(), v); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_map) +{ + msgpack::zone z; + typedef std::multimap multimap_t; + multimap_t v; + v.insert(multimap_t::value_type(msgpack::type::variant_ref(1), msgpack::type::variant_ref(-1))); + std::string s1("ABC"); + std::string s2("DEF"); +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + v.insert(multimap_t::value_type(msgpack::type::variant_ref(boost::string_ref(s1)), msgpack::type::variant_ref(boost::string_ref(s2)))); +#else // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + v.insert(multimap_t::value_type(msgpack::type::variant_ref(s1), msgpack::type::variant_ref(s2))); +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + msgpack::type::variant_ref val1 = v; + EXPECT_TRUE(val1.is_multimap()); + EXPECT_EQ(val1.as_multimap(), v); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_TRUE(val2.is_multimap()); + EXPECT_EQ(val2.as_multimap(), v); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + + +#endif // defined(MSGPACK_USE_BOOST)