// // 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 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 ) { if constexpr(sizeof...(Ts) == 0) { return Variant{std::in_place_index, object.as()}; } else { if (index == current_index) { return Variant{std::in_place_index, object.as()}; } return construct_variant( index, object, std::index_sequence() ); } } struct object_variant_overload { object_variant_overload(msgpack::object& obj, msgpack::zone& zone) : obj{obj} , zone{zone} {} template void operator()(T const& value) { obj = msgpack::object(value, zone); } msgpack::object& obj; msgpack::zone& zone; }; } // namespace detail template struct as, typename std::enable_if<(msgpack::has_as::value && ...)>::type> { std::variant 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, Ts...>( o.via.array.ptr[0].as(), o.via.array.ptr[1], std::make_index_sequence() ); } }; template struct convert> { msgpack::object const& operator()(msgpack::object const& o, std::variant& 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, Ts...>( o.via.array.ptr[0].as(), o.via.array.ptr[1], std::make_index_sequence() ); return o; } }; template struct pack>{ template msgpack::packer& operator()( msgpack::packer& o, std::variant 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 struct object_with_zone> { void operator()( msgpack::object::with_zone& o, std::variant const& v ) const { msgpack::object *p = static_cast( 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