From 097a3da7d282565a42daa744de72b9afad2579ab Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Tue, 2 Jul 2024 11:02:17 +0300 Subject: [PATCH] UDT serialization of described enums --- include/boost/json/impl/serializer.hpp | 53 ++++++++++++++++++++++++++ test/serializer.cpp | 20 +++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/include/boost/json/impl/serializer.hpp b/include/boost/json/impl/serializer.hpp index 54ee37b8..bbe9bcf3 100644 --- a/include/boost/json/impl/serializer.hpp +++ b/include/boost/json/impl/serializer.hpp @@ -10,6 +10,7 @@ #ifndef BOOST_JSON_IMPL_SERIALIZER_HPP #define BOOST_JSON_IMPL_SERIALIZER_HPP +#include #include #include @@ -585,6 +586,58 @@ do_obj6: return w.suspend(writer::state::obj6, cur, pt); } +template +BOOST_FORCEINLINE +bool +write_impl(described_enum_conversion_tag, writer& w, stream& ss) +{ +#ifdef BOOST_DESCRIBE_CXX14 + using Integer = typename std::underlying_type::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(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(*pt); + w.p_ = &n; + return write_impl(w, ss); + } + } + else + { + writer::state st; + w.st_.peek(st); + if( st == writer::state::lit ) + return write_impl(w, ss); + else + return resume_string(w, ss); + } +#else // BOOST_DESCRIBE_CXX14 + (void)w; + (void)ss; + static_assert( + !std::is_same::value, + "described enums require C++14 support"); + return false; +#endif // BOOST_DESCRIBE_CXX14 +} + template bool write_impl(writer& w, stream& ss) diff --git a/test/serializer.cpp b/test/serializer.cpp index f84e2a8b..0f937109 100644 --- a/test/serializer.cpp +++ b/test/serializer.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -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::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