UDT serialization of described enums

This commit is contained in:
Dmitry Arkhipov 2024-07-02 11:02:17 +03:00
parent 42576b096a
commit 097a3da7d2
2 changed files with 71 additions and 2 deletions

View File

@ -10,6 +10,7 @@
#ifndef BOOST_JSON_IMPL_SERIALIZER_HPP
#define BOOST_JSON_IMPL_SERIALIZER_HPP
#include <boost/describe/enum_to_string.hpp>
#include <boost/json/conversion.hpp>
#include <cstddef>
@ -585,6 +586,58 @@ do_obj6:
return w.suspend(writer::state::obj6, cur, pt);
}
template<class T, bool StackEmpty>
BOOST_FORCEINLINE
bool
write_impl(described_enum_conversion_tag, writer& w, stream& ss)
{
#ifdef BOOST_DESCRIBE_CXX14
using Integer = typename std::underlying_type<T>::type;
#if defined(_MSC_VER)
# pragma warning( push )
# pragma warning( disable : 4127 )
#endif
if(StackEmpty || w.st_.empty())
#if defined(_MSC_VER)
# pragma warning( pop )
#endif
{
BOOST_ASSERT( w.p_ );
T const* pt = reinterpret_cast<T const*>(w.p_);
char const* const name = describe::enum_to_string(*pt, nullptr);
if( name )
{
string_view const sv = name;
w.cs0_ = { sv.data(), sv.size() };
return write_string(w, ss);
}
else
{
Integer n = static_cast<Integer>(*pt);
w.p_ = &n;
return write_impl<Integer, true>(w, ss);
}
}
else
{
writer::state st;
w.st_.peek(st);
if( st == writer::state::lit )
return write_impl<Integer, false>(w, ss);
else
return resume_string(w, ss);
}
#else // BOOST_DESCRIBE_CXX14
(void)w;
(void)ss;
static_assert(
!std::is_same<T, T>::value,
"described enums require C++14 support");
return false;
#endif // BOOST_DESCRIBE_CXX14
}
template<class T, bool StackEmpty>
bool
write_impl(writer& w, stream& ss)

View File

@ -11,6 +11,7 @@
#include <boost/json/serializer.hpp>
#include <boost/describe/class.hpp>
#include <boost/describe/enum.hpp>
#include <boost/json/detail/stack.hpp>
#include <boost/json/serialize.hpp>
#include <boost/json/null_resource.hpp>
@ -36,6 +37,15 @@ struct my_struct
};
BOOST_DESCRIBE_STRUCT(my_struct, (), (s, n, d));
enum class my_enum
{
option_one,
option_two,
option_three,
option_four,
};
BOOST_DESCRIBE_ENUM(my_enum, option_one, option_two, option_three);
} // namespace serializer_test_ns
BOOST_STATIC_ASSERT( std::is_nothrow_destructible<serializer>::value );
@ -821,12 +831,18 @@ public:
"a string", {12, true}),
R"(["a string",[12,true]])");
}
{
#ifdef BOOST_DESCRIBE_CXX14
{
serializer_test_ns::my_struct s{"some string", 1424, 12.4};
check_udt(s, R"({"s":"some string","n":1424,"d":1.24E1})");
#endif // BOOST_DESCRIBE_CXX14
}
{
check_udt(
serializer_test_ns::my_enum::option_three,
R"("option_three")");
check_udt( serializer_test_ns::my_enum(100), "100" );
}
#endif // BOOST_DESCRIBE_CXX14
}
void