mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-17 03:03:24 +02:00
Merge pull request #1075 from uyha/variant
feat: add support for `std::variant`
This commit is contained in:
1
.github/workflows/coverage.yml
vendored
1
.github/workflows/coverage.yml
vendored
@@ -56,6 +56,7 @@ jobs:
|
||||
-D MSGPACK_BUILD_TESTS=ON \
|
||||
-D CMAKE_BUILD_TYPE=Debug \
|
||||
-D MSGPACK_GEN_COVERAGE=ON \
|
||||
-D MSGPACK_USE_STD_VARIANT_ADAPTOR=ON \
|
||||
-D CMAKE_PREFIX_PATH="$HOME/zlib-prefix/64;$HOME/boost-prefix/64" \
|
||||
-B build \
|
||||
-S . || exit 1
|
||||
|
1
.github/workflows/gha.yml
vendored
1
.github/workflows/gha.yml
vendored
@@ -145,6 +145,7 @@ jobs:
|
||||
3)
|
||||
export CXX="g++-10"
|
||||
export MSGPACK_CXX_VERSION="MSGPACK_CXX17=ON"
|
||||
export MSGPACK_USE_STD_VARIANT_ADAPTOR="MSGPACK_USE_STD_VARIANT_ADAPTOR=ON"
|
||||
;;
|
||||
4)
|
||||
export CXX="clang++-10"
|
||||
|
@@ -23,16 +23,17 @@ OPTION (MSGPACK_CXX14 "Using c++14 compiler" OFF)
|
||||
OPTION (MSGPACK_CXX17 "Using c++17 compiler" OFF)
|
||||
OPTION (MSGPACK_CXX20 "Using c++20 compiler" OFF)
|
||||
|
||||
OPTION (MSGPACK_32BIT "32bit compile" OFF)
|
||||
OPTION (MSGPACK_USE_BOOST "Use Boost libraried" ON)
|
||||
OPTION (MSGPACK_USE_X3_PARSE "Use Boost X3 parse" OFF)
|
||||
OPTION (MSGPACK_BUILD_TESTS "Build tests" OFF)
|
||||
OPTION (MSGPACK_BUILD_DOCS "Build Doxygen documentation" ON)
|
||||
OPTION (MSGPACK_FUZZ_REGRESSION "Enable regression testing" OFF)
|
||||
OPTION (MSGPACK_BUILD_EXAMPLES "Build msgpack examples" OFF)
|
||||
OPTION (MSGPACK_GEN_COVERAGE "Generate coverage report" OFF)
|
||||
OPTION (MSGPACK_USE_STATIC_BOOST "Statically link with boost libraries" OFF)
|
||||
OPTION (MSGPACK_CHAR_SIGN "Char sign to use (signed or unsigned)")
|
||||
OPTION (MSGPACK_32BIT "32bit compile" OFF)
|
||||
OPTION (MSGPACK_USE_BOOST "Use Boost libraried" ON)
|
||||
OPTION (MSGPACK_USE_X3_PARSE "Use Boost X3 parse" OFF)
|
||||
OPTION (MSGPACK_BUILD_TESTS "Build tests" OFF)
|
||||
OPTION (MSGPACK_BUILD_DOCS "Build Doxygen documentation" ON)
|
||||
OPTION (MSGPACK_FUZZ_REGRESSION "Enable regression testing" OFF)
|
||||
OPTION (MSGPACK_BUILD_EXAMPLES "Build msgpack examples" OFF)
|
||||
OPTION (MSGPACK_GEN_COVERAGE "Generate coverage report" OFF)
|
||||
OPTION (MSGPACK_USE_STATIC_BOOST "Statically link with boost libraries" OFF)
|
||||
OPTION (MSGPACK_CHAR_SIGN "Char sign to use (signed or unsigned)")
|
||||
OPTION (MSGPACK_USE_STD_VARIANT_ADAPTOR "Enable the adaptor for std::variant" OFF)
|
||||
|
||||
SET (CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
@@ -92,6 +93,10 @@ ELSE ()
|
||||
TARGET_COMPILE_DEFINITIONS(msgpack-cxx INTERFACE MSGPACK_DEFAULT_API_VERSION=3)
|
||||
ENDIF ()
|
||||
|
||||
IF (MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
TARGET_COMPILE_DEFINITIONS(msgpack-cxx INTERFACE MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
ENDIF ()
|
||||
|
||||
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.1)
|
||||
INCLUDE (CheckCXXSourceCompiles)
|
||||
|
@@ -33,6 +33,7 @@ SET (msgpack-cxx_HEADERS
|
||||
include/msgpack/adaptor/cpp17/carray_byte.hpp
|
||||
include/msgpack/adaptor/cpp17/optional.hpp
|
||||
include/msgpack/adaptor/cpp17/string_view.hpp
|
||||
include/msgpack/adaptor/cpp17/variant.hpp
|
||||
include/msgpack/adaptor/cpp17/vector_byte.hpp
|
||||
include/msgpack/adaptor/cpp20/span.hpp
|
||||
include/msgpack/adaptor/define.hpp
|
||||
@@ -542,6 +543,7 @@ SET (msgpack-cxx_HEADERS
|
||||
include/msgpack/v1/adaptor/cpp17/carray_byte.hpp
|
||||
include/msgpack/v1/adaptor/cpp17/optional.hpp
|
||||
include/msgpack/v1/adaptor/cpp17/string_view.hpp
|
||||
include/msgpack/v1/adaptor/cpp17/variant.hpp
|
||||
include/msgpack/v1/adaptor/cpp17/vector_byte.hpp
|
||||
include/msgpack/v1/adaptor/cpp20/span.hpp
|
||||
include/msgpack/v1/adaptor/define.hpp
|
||||
|
@@ -21,6 +21,7 @@ cmake \
|
||||
-D MSGPACK_CHAR_SIGN=${CHAR_SIGN} \
|
||||
-D MSGPACK_DEFAULT_API_VERSION=${API_VERSION} \
|
||||
-D MSGPACK_USE_X3_PARSE=${X3_PARSE} \
|
||||
-D MSGPACK_USE_STD_VARIANT_ADAPTOR=${STD_VARIANT_ADAPTOR} \
|
||||
-D CMAKE_CXX_FLAGS="${CXXFLAGS} ${ARCH_FLAG}" \
|
||||
-D CMAKE_INSTALL_PREFIX=$prefix_dir \
|
||||
-B $build_dir \
|
||||
|
16
include/msgpack/adaptor/cpp17/variant.hpp
Normal file
16
include/msgpack/adaptor/cpp17/variant.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2023 Uy Ha
|
||||
//
|
||||
// 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_TYPE_CPP17_VARIANT_HPP
|
||||
#define MSGPACK_TYPE_CPP17_VARIANT_HPP
|
||||
|
||||
#include "msgpack/v1/adaptor/cpp17/variant.hpp"
|
||||
|
||||
#endif // MSGPACK_TYPE_CPP17_VARIANT_HPP
|
@@ -63,6 +63,10 @@
|
||||
#include "adaptor/cpp17/carray_byte.hpp"
|
||||
#include "adaptor/cpp17/vector_byte.hpp"
|
||||
|
||||
#if MSGPACK_HAS_INCLUDE(<variant>)
|
||||
#include "adaptor/cpp17/variant.hpp"
|
||||
#endif // MSGPACK_HAS_INCLUDE(<variant>)
|
||||
|
||||
#if MSGPACK_HAS_INCLUDE(<span>)
|
||||
#include "adaptor/cpp20/span.hpp"
|
||||
#endif // MSGPACK_HAS_INCLUDE(<span>)
|
||||
|
151
include/msgpack/v1/adaptor/cpp17/variant.hpp
Normal file
151
include/msgpack/v1/adaptor/cpp17/variant.hpp
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2023 Uy Ha
|
||||
//
|
||||
// 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_VARIANT_HPP
|
||||
#define MSGPACK_V1_TYPE_VARIANT_HPP
|
||||
|
||||
#if defined(MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
|
||||
#include "msgpack/cpp_version.hpp"
|
||||
|
||||
#if MSGPACK_CPP_VERSION >= 201703
|
||||
|
||||
#include "msgpack/adaptor/adaptor_base.hpp"
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/versioning.hpp"
|
||||
|
||||
#include <variant>
|
||||
|
||||
namespace msgpack {
|
||||
MSGPACK_API_VERSION_NAMESPACE(v1) {
|
||||
namespace adaptor {
|
||||
namespace detail {
|
||||
template <
|
||||
typename Variant,
|
||||
typename T,
|
||||
typename... Ts,
|
||||
std::size_t current_index,
|
||||
std::size_t... indices
|
||||
>
|
||||
Variant construct_variant(
|
||||
std::size_t index,
|
||||
msgpack::object& object,
|
||||
std::index_sequence<current_index, indices...>
|
||||
) {
|
||||
if constexpr(sizeof...(Ts) == 0) {
|
||||
return object.as<T>();
|
||||
}
|
||||
else {
|
||||
if (index == current_index) {
|
||||
return object.as<T>();
|
||||
}
|
||||
return construct_variant<Variant, Ts...>(
|
||||
index,
|
||||
object,
|
||||
std::index_sequence<indices...>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
struct object_variant_overload {
|
||||
object_variant_overload(msgpack::object& obj, msgpack::zone& zone)
|
||||
: obj{obj}
|
||||
, zone{zone} {}
|
||||
|
||||
template<typename T>
|
||||
void operator()(T const& value) {
|
||||
obj = msgpack::object(value, zone);
|
||||
}
|
||||
|
||||
msgpack::object& obj;
|
||||
msgpack::zone& zone;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename... Ts>
|
||||
struct as<std::variant<Ts...>, typename std::enable_if<(msgpack::has_as<Ts>::value && ...)>::type> {
|
||||
std::variant<Ts...> operator()(msgpack::object const& o) const {
|
||||
if ( o.type != msgpack::type::ARRAY
|
||||
|| o.via.array.size != 2
|
||||
|| o.via.array.ptr[0].type != msgpack::type::POSITIVE_INTEGER
|
||||
|| o.via.array.ptr[0].via.u64 >= sizeof...(Ts)) {
|
||||
throw msgpack::type_error{};
|
||||
}
|
||||
|
||||
return detail::construct_variant<std::variant<Ts...>, Ts...>(
|
||||
o.via.array.ptr[0].as<std::size_t>(),
|
||||
o.via.array.ptr[1],
|
||||
std::make_index_sequence<sizeof...(Ts)>()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
struct convert<std::variant<Ts...>> {
|
||||
msgpack::object const& operator()(msgpack::object const& o, std::variant<Ts...>& v) const {
|
||||
if ( o.type != msgpack::type::ARRAY
|
||||
|| o.via.array.size != 2
|
||||
|| o.via.array.ptr[0].type != msgpack::type::POSITIVE_INTEGER
|
||||
|| o.via.array.ptr[0].via.u64 >= sizeof...(Ts)) {
|
||||
throw msgpack::type_error{};
|
||||
}
|
||||
|
||||
v = detail::construct_variant<std::variant<Ts...>, Ts...>(
|
||||
o.via.array.ptr[0].as<std::size_t>(),
|
||||
o.via.array.ptr[1],
|
||||
std::make_index_sequence<sizeof...(Ts)>()
|
||||
);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
struct pack<std::variant<Ts...>>{
|
||||
template<typename Stream>
|
||||
msgpack::packer<Stream>& operator()(
|
||||
msgpack::packer<Stream>& o,
|
||||
std::variant<Ts...> const& v
|
||||
) const {
|
||||
o.pack_array(2);
|
||||
o.pack_uint64(v.index());
|
||||
std::visit([&o](auto const& value){o.pack(value);}, v);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename... Ts>
|
||||
struct object_with_zone<std::variant<Ts...>> {
|
||||
void operator()(
|
||||
msgpack::object::with_zone& o,
|
||||
std::variant<Ts...> const& v
|
||||
) const {
|
||||
msgpack::object *p =
|
||||
static_cast<msgpack::object *>(
|
||||
o.zone.allocate_align(
|
||||
sizeof(msgpack::object) * 2,
|
||||
MSGPACK_ZONE_ALIGNOF(msgpack::object)
|
||||
)
|
||||
);
|
||||
|
||||
o.type = msgpack::type::ARRAY;
|
||||
o.via.array.size = 2;
|
||||
o.via.array.ptr = p;
|
||||
o.via.array.ptr[0]= msgpack::object(v.index(), o.zone);
|
||||
std::visit(detail::object_variant_overload(o.via.array.ptr[1], o.zone), v);
|
||||
}
|
||||
};
|
||||
} // namespace adaptor
|
||||
}
|
||||
} // namespace msgpack
|
||||
|
||||
#endif // MSGPACK_CPP_VERSION >= 201703
|
||||
#endif // defined(MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
#endif // MSGPACK_V1_TYPE_VARIANT_HPP
|
@@ -461,4 +461,30 @@ BOOST_AUTO_TEST_CASE(carray_byte_object_with_zone)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(variant_pack_unpack_as) {
|
||||
std::stringstream ss;
|
||||
std::variant<bool, int, float, double> val1{1.0};
|
||||
msgpack::pack(ss, val1);
|
||||
std::string const& str = ss.str();
|
||||
msgpack::object_handle oh =
|
||||
msgpack::unpack(str.data(), str.size());
|
||||
std::variant<bool, int, float, double> val2 =
|
||||
oh.get().as<std::variant<bool, int, float, double> >();
|
||||
BOOST_CHECK(val1 == val2);
|
||||
BOOST_CHECK_THROW((oh.get().as<std::variant<bool>>()), msgpack::type_error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(variant_with_zone) {
|
||||
msgpack::zone z;
|
||||
std::variant<bool, int, float, double> val1{1.0};
|
||||
msgpack::object obj(val1, z);
|
||||
std::variant<bool, int, float, double> val2 = obj.as<std::variant<bool, int, float, double>>();
|
||||
BOOST_CHECK(val1 == val2);
|
||||
BOOST_CHECK_THROW((obj.as<std::variant<bool>>()), msgpack::type_error);
|
||||
}
|
||||
|
||||
#endif // defined(MSGPACK_USE_STD_VARIANT_ADAPTOR)
|
||||
|
||||
#endif // MSGPACK_CPP_VERSION >= 201703
|
||||
|
Reference in New Issue
Block a user