mirror of
https://github.com/boostorg/leaf.git
synced 2026-01-19 04:22:08 +00:00
minor refactor
This commit is contained in:
281
doc/leaf.adoc
281
doc/leaf.adoc
@@ -1740,40 +1740,12 @@ LEAF provides a serialization API that enables exporting error information into
|
||||
* <<diagnostic_details>>
|
||||
* <<result>>
|
||||
|
||||
==== Custom Writers
|
||||
LEAF serialization is defined in terms of `write` and `write_nested` function calls, found via ADL:
|
||||
|
||||
To support different serialization formats, users can define custom writer types that derive from `leaf::serialization::writer`. Writers should provide `write` and `write_nested` friend functions:
|
||||
* `write(w, x)` serializes `x` directly to writer `w`.
|
||||
* `write_nested(w, x, name)` serializes `x` to writer `w` as a named field.
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
|
||||
class my_writer: public leaf::serialization::writer
|
||||
{
|
||||
public:
|
||||
|
||||
my_writer() noexcept:
|
||||
writer(this)
|
||||
{
|
||||
}
|
||||
|
||||
template <class E>
|
||||
friend void write_nested(my_writer & w, E const & e, char const * name)
|
||||
{
|
||||
.... // Serialize e as a named field
|
||||
}
|
||||
|
||||
template <class E>
|
||||
friend void write(my_writer & w, E const & e)
|
||||
{
|
||||
.... // Serialize e
|
||||
}
|
||||
};
|
||||
----
|
||||
|
||||
The `write` function serializes an error object directly to the writer. The `write_nested` function serializes an error object as a named field, typically calling `write` internally. LEAF finds these friend functions via ADL using the writer type.
|
||||
|
||||
LEAF provides suitable `write` overloads for the following types:
|
||||
LEAF provides generic `write` overloads for the following types:
|
||||
|
||||
* `error_id`
|
||||
* `e_source_location`
|
||||
@@ -1784,9 +1756,36 @@ LEAF provides suitable `write` overloads for the following types:
|
||||
* `std::exception_ptr`
|
||||
* any type with a `.value` member for which a suitable `write` can be found via ADL
|
||||
|
||||
Custom writers must also handle types that do not provide ADL `write` overloads, including built-in types like `int` and `std::string` as needed. See <<json_writer>> for an example.
|
||||
[[custom-writers]]
|
||||
==== Custom Writers
|
||||
|
||||
To enable serialization of error objects to custom writer types, define a `serialize` function template in the `boost::leaf::serialization` namespace:
|
||||
To support exporting to a specific format, users define a writer class with associated `write` and `write_nested` function templates specific to that writer:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
struct my_writer
|
||||
{
|
||||
std::ostream & os;
|
||||
|
||||
template <class T>
|
||||
friend void write(my_writer & w, T const & x)
|
||||
{
|
||||
// write x to w
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend void write_nested(my_writer & w, T const & x, char const * name)
|
||||
{
|
||||
// write x to w as a named field
|
||||
}
|
||||
};
|
||||
----
|
||||
|
||||
The `write` function outputs a value. The `write_nested` function typically creates a nested scope (e.g. a JSON object or XML element) and then makes an unqualified call to `write` to output the value. This will call any compatible overload found via ADL.
|
||||
|
||||
TIP: The `write` function may need to use SFINAE to avoid ambiguities with the generic `write` overloads provided by LEAF. Custom writers must also handle types that do not provide ADL `write` overloads, including built-in types like `int` and `std::string`.
|
||||
|
||||
To enable serialization to a custom writer type, define a `serialize` function template in the `boost::leaf::serialization` namespace:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
@@ -1794,54 +1793,70 @@ namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization {
|
||||
|
||||
template <class E>
|
||||
void serialize(writer & w, E const & e, char const * name)
|
||||
{
|
||||
if( my_writer * mw = w.get<my_writer>() )
|
||||
write_nested(*mw, e, name);
|
||||
}
|
||||
template <class Handle, class E>
|
||||
void serialize(Handle & h, E const & e, char const * name)
|
||||
{
|
||||
h.dispatch([&](my_writer & mw) {
|
||||
write_nested(mw, e, name);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `serialize` function receives a polymorphic `writer &` reference, the object being serialized, and its name. Use the `get<Derived>()` member function to check for a specific writer type. If the cast succeeds (returns non-null), call `write_nested` to serialize the error object with its type name. To support multiple output formats, this user-defined `serialize` function should check for each writer type accordingly.
|
||||
The `serialize` function template takes a handle reference `h` (of unspecified type) that holds a writer, the error object to be serialized, and its type name. Call `h.dispatch` with a single-argument function F to detect the writer type based on F's argument type; F is called only if the handle contains a writer of that type.
|
||||
|
||||
==== JSON Serialization
|
||||
|
||||
LEAF provides `json_writer`, a writer class template for JSON serialization. The `json_writer` class provides `write` and `write_nested` friend functions that work with:
|
||||
|
||||
* LEAF types that provide their own `write` overloads (e.g. `error_id`, `e_source_location`, `e_errno`, `std::error_code`, `std::error_condition`, `std::exception`, `std::exception_ptr`)
|
||||
* Types for which `to_json` overloads can be found via ADL
|
||||
|
||||
This interface is compatible with https://github.com/nlohmann/json[nlohmann/json]:
|
||||
To support multiple output formats, pass multiple functions to `h.dispatch`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
#include <boost/leaf/diagnostics.hpp>
|
||||
#include <boost/leaf/serialization/json_writer.hpp>
|
||||
h.dispatch(
|
||||
[&](nlohmann_writer & nw) { write_nested(nw, e, name); },
|
||||
[&](xml_writer & xw) { write_nested(xw, e, name); }
|
||||
);
|
||||
----
|
||||
|
||||
==== JSON Serialization
|
||||
|
||||
LEAF provides `nlohmann_writer`, a class template for JSON serialization. The `nlohmann_writer` class defines `write` and `write_nested` friend functions (see <<tutorial-serialization>>) that work with:
|
||||
|
||||
* Types for which `to_json` overloads can be found via ADL
|
||||
* Types for which a `write` overload can be found via ADL (e.g. LEAF types)
|
||||
|
||||
This interface is compatible with https://github.com/nlohmann/json[nlohmann/json], we just need to define the required `serialize` function template (see <<custom-writers>>):
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
|
||||
using nlohmann_writer = leaf::serialization::json_writer<nlohmann::json>;
|
||||
using nlohmann_writer = leaf::serialization::nlohmann_writer<nlohmann::json>;
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization {
|
||||
|
||||
template <class E>
|
||||
void serialize(writer & w, E const & e, char const * name)
|
||||
{
|
||||
if( nlohmann_writer * nw = w.get<nlohmann_writer>() )
|
||||
write_nested(*nw, e, name);
|
||||
}
|
||||
template <class Handle, class E>
|
||||
void serialize(Handle & h, E const & e, char const * name)
|
||||
{
|
||||
h.dispatch([&](nlohmann_writer & nw) {
|
||||
write_nested(nw, e, name);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
With this in place, we can easily (for example) serialize <<diagnostic_details>> to JSON:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
struct e_api_response
|
||||
{
|
||||
int status;
|
||||
@@ -2852,82 +2867,36 @@ Reference: <<to_variant>>
|
||||
|
||||
=== Serialization
|
||||
|
||||
[[writer.hpp]]
|
||||
==== `writer.hpp`
|
||||
[[nlohmann_writer.hpp]]
|
||||
==== `nlohmann_writer.hpp`
|
||||
|
||||
====
|
||||
.#include <boost/leaf/serialization/writer.hpp>
|
||||
.#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
class writer
|
||||
{
|
||||
protected:
|
||||
|
||||
template <class Derived>
|
||||
explicit writer( Derived * ) noexcept;
|
||||
|
||||
~writer() noexcept;
|
||||
|
||||
public:
|
||||
|
||||
template <class Derived>
|
||||
Derived * get() noexcept;
|
||||
};
|
||||
|
||||
// Enabled for types with a .value member for which
|
||||
// a suitable write can be found via ADL.
|
||||
template <class W, class E>
|
||||
void write( W &, E const & );
|
||||
|
||||
} // namespace serialization
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
[.text-right]
|
||||
Reference: <<writer>> | <<serialize>>
|
||||
====
|
||||
|
||||
[[json_writer.hpp]]
|
||||
==== `json_writer.hpp`
|
||||
|
||||
====
|
||||
.#include <boost/leaf/serialization/json_writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
template <class Json>
|
||||
class json_writer: public writer
|
||||
struct nlohmann_writer
|
||||
{
|
||||
public:
|
||||
Json & j_;
|
||||
|
||||
explicit json_writer( Json & ) noexcept;
|
||||
template <class T>
|
||||
friend auto write( nlohmann_writer &, T const & x )
|
||||
-> decltype(to_json(std::declval<Json &>(), x));
|
||||
|
||||
template <class E>
|
||||
friend void write_nested( json_writer &, E const &, char const * name );
|
||||
|
||||
// Enabled for types for which a suitable to_json overload
|
||||
// can be found via ADL.
|
||||
template <class E>
|
||||
friend void write( json_writer &, E const & );
|
||||
template <class T>
|
||||
friend void write_nested( nlohmann_writer &, T const &, char const * name );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
[.text-right]
|
||||
Reference: <<json_writer>>
|
||||
Reference: <<nlohmann_writer>>
|
||||
====
|
||||
|
||||
[[functions]]
|
||||
@@ -3227,21 +3196,20 @@ TIP: See <<tutorial-on_error>> from the Tutorial.
|
||||
[[serialize]]
|
||||
=== `serialize`
|
||||
|
||||
.#include <boost/leaf/serialization/writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class E>
|
||||
void serialize( writer &, E const &, char const * name );
|
||||
template <class Handle, class E>
|
||||
void serialize( Handle &, E const &, char const * name );
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `serialize` function template is a user-defined customization point. If defined, it is called by the serialization system to serialize error objects to a writer. See <<tutorial-serialization>>.
|
||||
The `serialize` function template is a user-defined customization point. If provided, it is called by the serialization system to output error objects; see <<custom-writers>>.
|
||||
|
||||
'''
|
||||
|
||||
@@ -4474,10 +4442,10 @@ The `write_to` member function is used with the serialization system; see <<tuto
|
||||
|
||||
'''
|
||||
|
||||
[[json_writer]]
|
||||
=== `json_writer`
|
||||
[[nlohmann_writer]]
|
||||
=== `nlohmann_writer`
|
||||
|
||||
.#include <boost/leaf/serialization/json_writer.hpp>
|
||||
.#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
@@ -4485,32 +4453,25 @@ namespace boost { namespace leaf {
|
||||
namespace serialization
|
||||
{
|
||||
template <class Json>
|
||||
class json_writer: public writer
|
||||
struct nlohmann_writer
|
||||
{
|
||||
public:
|
||||
|
||||
explicit json_writer( Json & ) noexcept;
|
||||
|
||||
template <class E>
|
||||
friend void write_nested( json_writer &, E const &, char const * name );
|
||||
Json & j_;
|
||||
|
||||
// Enabled for types for which a suitable to_json overload
|
||||
// can be found via ADL.
|
||||
template <class E>
|
||||
friend void write( json_writer &, E const & );
|
||||
// can be found via ADL, but a suitable write overload cannot.
|
||||
template <class T>
|
||||
friend auto write( nlohmann_writer &, T const & x )
|
||||
-> decltype(to_json(std::declval<Json &>(), x));
|
||||
|
||||
template <class T>
|
||||
friend void write_nested( nlohmann_writer &, T const &, char const * name );
|
||||
};
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `json_writer` class template is used to serialize error objects to a JSON object. The `Json` template parameter is the type of the JSON object, for example https://github.com/nlohmann/json[nlohmann/json].
|
||||
|
||||
The constructor takes a reference to a JSON object, which will be populated with serialized error data.
|
||||
|
||||
The `write_nested` friend function creates a named field in the JSON object and calls `write` to serialize the error object into it.
|
||||
|
||||
The `write` friend function serializes an error object by calling `to_json(json, e)`, found via ADL. LEAF types provide their own `write` overloads instead of `to_json`. See <<tutorial-serialization>>.
|
||||
The `nlohmann_writer` class template serializes error objects to JSON format using unqualified calls to `to_json`. This is compatible with https://github.com/nlohmann/json[nlohmann/json]; See <<tutorial-serialization>>.
|
||||
|
||||
'''
|
||||
|
||||
@@ -5013,48 +4974,6 @@ namespace boost { namespace leaf {
|
||||
} }
|
||||
----
|
||||
|
||||
'''
|
||||
|
||||
[[writer]]
|
||||
=== `writer`
|
||||
|
||||
.#include <boost/leaf/serialization/writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
class writer
|
||||
{
|
||||
protected:
|
||||
|
||||
template <class Derived>
|
||||
explicit writer( Derived * ) noexcept;
|
||||
|
||||
~writer() noexcept;
|
||||
|
||||
public:
|
||||
|
||||
template <class Derived>
|
||||
Derived * get() noexcept;
|
||||
};
|
||||
|
||||
// Enabled for types with a .value member for which
|
||||
// a suitable write overload can be found via ADL.
|
||||
template <class W, class E>
|
||||
void write( W &, E const & );
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `writer` class is the base class for custom serialization writers. The constructor takes a pointer to the derived class, which is used by the `get` member function to recognize writer types at runtime.
|
||||
|
||||
The `get` member function returns a pointer to the derived class if the type matches, or `nullptr` otherwise. This allows the <<serialize>> function to dispatch to the correct writer type.
|
||||
|
||||
Derived writer types typically provide `write` and `write_nested` friend functions for serializing error objects. The `write` function serializes an error object directly, while `write_nested` serializes it as a named field. See <<tutorial-serialization>>.
|
||||
|
||||
[[predicates]]
|
||||
== Reference: Predicates
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace detail
|
||||
tuple_for_each<I-1,Tup>::unload(tup, err_id);
|
||||
}
|
||||
|
||||
static void write_to(serialization::writer & w, void const * tup, error_id id)
|
||||
static void write_to(writer & w, void const * tup, error_id id)
|
||||
{
|
||||
BOOST_LEAF_ASSERT(tup != nullptr);
|
||||
tuple_for_each<I-1,Tup>::write_to(w, tup, id);
|
||||
@@ -218,11 +218,11 @@ namespace detail
|
||||
BOOST_LEAF_CONSTEXPR static void activate( Tup & ) noexcept { }
|
||||
BOOST_LEAF_CONSTEXPR static void deactivate( Tup & ) noexcept { }
|
||||
BOOST_LEAF_CONSTEXPR static void unload( Tup &, int ) noexcept { }
|
||||
BOOST_LEAF_CONSTEXPR static void write_to(serialization::writer &, void const *, error_id) { }
|
||||
BOOST_LEAF_CONSTEXPR static void write_to(writer &, void const *, error_id) { }
|
||||
};
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR void serialize_tuple_contents(serialization::writer & w, void const * tup, error_id id)
|
||||
void serialize_tuple_contents(writer & w, void const * tup, error_id id)
|
||||
{
|
||||
tuple_for_each<std::tuple_size<Tup>::value, Tup>::write_to(w, tup, id);
|
||||
}
|
||||
@@ -368,7 +368,7 @@ public:
|
||||
return is_active_;
|
||||
}
|
||||
|
||||
void write_to( serialization::writer & w ) const
|
||||
void write_to( detail::diagnostics_writer & w ) const
|
||||
{
|
||||
detail::serialize_tuple_contents<Tup>(w, &tup_, error_id());
|
||||
}
|
||||
|
||||
@@ -11,6 +11,5 @@
|
||||
#include <boost/leaf/on_error.hpp>
|
||||
#include <boost/leaf/pred.hpp>
|
||||
#include <boost/leaf/result.hpp>
|
||||
#include <boost/leaf/serialization/json_writer.hpp>
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
#include <boost/leaf/to_variant.hpp>
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
class error_id;
|
||||
namespace serialization { class writer; }
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class writer;
|
||||
|
||||
class capture_list
|
||||
{
|
||||
@@ -29,7 +29,7 @@ namespace detail
|
||||
friend class capture_list;
|
||||
|
||||
virtual void unload( int err_id ) = 0;
|
||||
virtual void write_to(serialization::writer &, error_id const &) const = 0;
|
||||
virtual void write_to(writer &, error_id const &) const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace detail
|
||||
} );
|
||||
}
|
||||
|
||||
void write_to(serialization::writer & w, error_id const & id) const
|
||||
void write_to(writer & w, error_id const & id) const
|
||||
{
|
||||
if( first_ )
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
#include <boost/leaf/detail/writer.hpp>
|
||||
#include <boost/leaf/detail/exception_base.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
@@ -52,7 +52,7 @@ namespace detail
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
class diagnostics_writer: public serialization::writer
|
||||
class diagnostics_writer: public writer
|
||||
{
|
||||
diagnostics_writer(diagnostics_writer const &) = delete;
|
||||
diagnostics_writer & operator=(diagnostics_writer const &) = delete;
|
||||
@@ -161,10 +161,10 @@ namespace detail
|
||||
delimiter_ = delimiter;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
void write(E const & e)
|
||||
template <class T>
|
||||
void write(T const & x)
|
||||
{
|
||||
diagnostic<E>::print(os_, prefix_, delimiter_, e);
|
||||
diagnostic<T>::print(os_, prefix_, delimiter_, x);
|
||||
}
|
||||
}; // class diagnostics_writer
|
||||
|
||||
|
||||
@@ -7,96 +7,51 @@
|
||||
|
||||
#include <boost/leaf/detail/demangle.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
# include <string>
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
# include <string_view>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct type_name
|
||||
{
|
||||
char const * name_not_zero_terminated_at_length;
|
||||
std::size_t length;
|
||||
std::size_t hash;
|
||||
|
||||
friend bool operator==(type_name const & a, type_name const & b) noexcept
|
||||
struct type_name
|
||||
{
|
||||
BOOST_LEAF_ASSERT((a.hash == b.hash) == (a.length == b.length && std::memcmp(a.name_not_zero_terminated_at_length, b.name_not_zero_terminated_at_length, a.length) == 0));
|
||||
return a.hash == b.hash;
|
||||
}
|
||||
char const * name_not_zero_terminated_at_length;
|
||||
std::size_t length;
|
||||
std::size_t hash;
|
||||
|
||||
friend bool operator!=(type_name const & a, type_name const & b) noexcept
|
||||
friend bool operator==(type_name const & a, type_name const & b) noexcept
|
||||
{
|
||||
BOOST_LEAF_ASSERT((a.hash == b.hash) == (a.length == b.length && std::memcmp(a.name_not_zero_terminated_at_length, b.name_not_zero_terminated_at_length, a.length) == 0));
|
||||
return a.hash == b.hash;
|
||||
}
|
||||
|
||||
friend bool operator!=(type_name const & a, type_name const & b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<(std::basic_ostream<CharT, Traits> & os, type_name const & x)
|
||||
{
|
||||
return os.write(x.name_not_zero_terminated_at_length, x.length);
|
||||
}
|
||||
|
||||
template <std::size_t S>
|
||||
friend char * to_zstr(char (&zstr)[S], type_name const & x) noexcept
|
||||
{
|
||||
std::size_t n = x.length < S - 1 ? x.length : S - 1;
|
||||
std::memcpy(zstr, x.name_not_zero_terminated_at_length, n);
|
||||
zstr[n] = 0;
|
||||
return zstr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
type_name get_type_name()
|
||||
{
|
||||
return !(a == b);
|
||||
n::r parsed = n::p<T>();
|
||||
return { parsed.name_not_zero_terminated_at_length, parsed.length, parsed.hash };
|
||||
}
|
||||
|
||||
friend bool operator<(type_name const & a, type_name const & b) noexcept
|
||||
{
|
||||
if( int cmp = std::memcmp(a.name_not_zero_terminated_at_length, b.name_not_zero_terminated_at_length, a.length < b.length ? a.length : b.length) )
|
||||
return cmp < 0;
|
||||
return a.length < b.length;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<(std::basic_ostream<CharT, Traits> & os, type_name const & x)
|
||||
{
|
||||
return os.write(x.name_not_zero_terminated_at_length, x.length);
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
friend std::string_view to_string_view(type_name const & x) noexcept
|
||||
{
|
||||
return std::string_view(x.name_not_zero_terminated_at_length, x.length);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
friend std::string to_string(type_name const & x)
|
||||
{
|
||||
return std::string(x.name_not_zero_terminated_at_length, x.length);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <std::size_t S>
|
||||
friend char * to_zstr(char (&zstr)[S], type_name const & x) noexcept
|
||||
{
|
||||
std::size_t n = x.length < S - 1 ? x.length : S - 1;
|
||||
std::memcpy(zstr, x.name_not_zero_terminated_at_length, n);
|
||||
zstr[n] = 0;
|
||||
return zstr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
type_name get_type_name()
|
||||
{
|
||||
n::r parsed = n::p<T>();
|
||||
return { parsed.name_not_zero_terminated_at_length, parsed.length, parsed.hash };
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<boost::leaf::detail::type_name>
|
||||
{
|
||||
std::size_t operator()(boost::leaf::detail::type_name const & x) const noexcept
|
||||
{
|
||||
return x.hash;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_DETAIL_TYPE_NAME_HPP_INCLUDED
|
||||
|
||||
92
include/boost/leaf/detail/writer.hpp
Normal file
92
include/boost/leaf/detail/writer.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef BOOST_LEAF_DETAIL_WRITER_HPP_INCLUDED
|
||||
#define BOOST_LEAF_DETAIL_WRITER_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// 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)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/detail/type_name.hpp>
|
||||
#include <boost/leaf/detail/function_traits.hpp>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
struct writer_adl {};
|
||||
|
||||
template <class Writer, class E>
|
||||
auto write(Writer & w, E const & e) -> decltype(write(w, e.value))
|
||||
{
|
||||
write(w, e.value);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class writer:
|
||||
serialization::writer_adl
|
||||
{
|
||||
writer(writer const &) = delete;
|
||||
writer & operator=(writer const &) = delete;
|
||||
|
||||
type_name const type_;
|
||||
void * const w_;
|
||||
|
||||
bool dispatch_()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class F1, class... Fn>
|
||||
bool dispatch_(F1 && f1, Fn && ... fn)
|
||||
{
|
||||
using writer_type = typename std::decay<fn_arg_type<F1, 0>>::type;
|
||||
if (writer_type * w = get<writer_type>())
|
||||
{
|
||||
std::forward<F1>(f1)(*w);
|
||||
return true;
|
||||
}
|
||||
return dispatch_(std::forward<Fn>(fn)...);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
template <class Writer>
|
||||
explicit writer(Writer * w) noexcept:
|
||||
type_(get_type_name<Writer>()),
|
||||
w_(w)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template <class Writer>
|
||||
Writer * get() noexcept
|
||||
{
|
||||
return type_ == get_type_name<Writer>() ? static_cast<Writer *>(w_) : nullptr;
|
||||
}
|
||||
|
||||
template <class... Fn>
|
||||
bool dispatch(Fn && ... fn)
|
||||
{
|
||||
using writer_types = leaf_detail_mp11::mp_list<typename std::decay<fn_arg_type<Fn, 0>>::type...>;
|
||||
static_assert(std::is_same<writer_types, leaf_detail_mp11::mp_unique<writer_types>>::value, "Duplicate writer types in dispatch");
|
||||
return dispatch_(std::forward<Fn>(fn)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Writer>
|
||||
struct writer_adaptor:
|
||||
writer
|
||||
{
|
||||
explicit writer_adaptor(Writer & w) noexcept:
|
||||
writer(&w)
|
||||
{
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_DETAIL_WRITER_HPP_INCLUDED
|
||||
@@ -6,7 +6,6 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/context.hpp>
|
||||
#include <boost/leaf/handle_errors.hpp>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
@@ -14,7 +13,7 @@ namespace boost { namespace leaf {
|
||||
class diagnostic_info: public error_info
|
||||
{
|
||||
void const * tup_;
|
||||
void (*serialize_tuple_contents_)(serialization::writer &, void const *, error_id);
|
||||
void (*serialize_tuple_contents_)(detail::writer &, void const *, error_id);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -31,6 +30,7 @@ protected:
|
||||
template <class Writer>
|
||||
void write_to_(Writer & w) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
serialize_tuple_contents_(w, tup_, error());
|
||||
}
|
||||
|
||||
@@ -39,8 +39,9 @@ public:
|
||||
template <class Writer>
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
error_info::write_to(w);
|
||||
write_to_(w);
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
error_info::write_to_(wa);
|
||||
write_to_(wa);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
@@ -100,6 +101,7 @@ protected:
|
||||
template <class Writer>
|
||||
void write_to_(Writer & w) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
if( da_ )
|
||||
da_->write_to(w, error());
|
||||
}
|
||||
@@ -109,8 +111,10 @@ public:
|
||||
template <class Writer>
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
diagnostic_info::write_to(w);
|
||||
write_to_(w);
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
error_info::write_to_(wa);
|
||||
diagnostic_info::write_to_(wa);
|
||||
write_to_(wa);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
@@ -170,7 +174,9 @@ public:
|
||||
template <class Writer>
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
diagnostic_info::write_to(w);
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
error_info::write_to_(wa);
|
||||
diagnostic_info::write_to_(wa);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
|
||||
@@ -119,29 +119,29 @@ struct show_in_diagnostics<e_source_location>: std::false_type
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
template <class W, class E>
|
||||
typename std::enable_if<std::is_base_of<writer, W>::value>::type
|
||||
serialize(W &, E const &, char const *)
|
||||
template <class Writer, class T, class... Unused>
|
||||
typename std::enable_if<std::is_base_of<detail::writer, Writer>::value>::type
|
||||
serialize(Writer &, T const &, char const *, Unused && ...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class E>
|
||||
void serialize_(diagnostics_writer & w, E const & e)
|
||||
template <class T>
|
||||
void serialize_(diagnostics_writer & w, T const & x)
|
||||
{
|
||||
w.write(e);
|
||||
w.write(x);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
void serialize_(serialization::writer & w, E const & e)
|
||||
template <class T>
|
||||
void serialize_(writer & w, T const & x)
|
||||
{
|
||||
using namespace serialization;
|
||||
char zstr[1024];
|
||||
serialize(w, e, to_zstr(zstr, get_type_name<E>()));
|
||||
if( detail::diagnostics_writer * dw = w.get<detail::diagnostics_writer>() )
|
||||
dw->write(e);
|
||||
serialize(w, x, to_zstr(zstr, get_type_name<T>()));
|
||||
if( diagnostics_writer * dw = w.get<diagnostics_writer>() )
|
||||
dw->write(x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +204,7 @@ namespace detail
|
||||
template <class Writer,class ErrorID>
|
||||
void write_to(Writer & w, ErrorID id) const
|
||||
{
|
||||
static_assert(std::is_base_of<writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
if( int k = this->key() )
|
||||
{
|
||||
if( id && id.value() != k )
|
||||
@@ -270,7 +271,7 @@ namespace detail
|
||||
{
|
||||
impl::unload(err_id);
|
||||
}
|
||||
void write_to(serialization::writer & w, error_id const & id) const override
|
||||
void write_to(writer & w, error_id const & id) const override
|
||||
{
|
||||
impl::write_to(w, id);
|
||||
}
|
||||
@@ -305,7 +306,7 @@ namespace detail
|
||||
{
|
||||
std::rethrow_exception(ex_);
|
||||
}
|
||||
void write_to(serialization::writer &, error_id const &) const override
|
||||
void write_to(writer &, error_id const &) const override
|
||||
{
|
||||
}
|
||||
std::exception_ptr const ex_;
|
||||
@@ -481,7 +482,7 @@ namespace detail
|
||||
}
|
||||
|
||||
template <class ErrorID>
|
||||
void write_to(serialization::writer &, ErrorID) const
|
||||
void write_to(writer &, ErrorID) const
|
||||
{
|
||||
}
|
||||
}; // slot specialization for dynamic_allocator
|
||||
|
||||
@@ -45,6 +45,17 @@ protected:
|
||||
|
||||
error_info( error_info const & ) noexcept = default;
|
||||
|
||||
template <class Writer>
|
||||
void write_to_(Writer & w) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
detail::serialize_(w, err_id_);
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
if( ex_ )
|
||||
detail::serialize_(w, *ex_);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
BOOST_LEAF_CONSTEXPR error_info(error_id id, std::exception * ex, e_source_location const * loc) noexcept:
|
||||
@@ -79,11 +90,8 @@ public:
|
||||
template <class Writer>
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
detail::serialize_(w, err_id_);
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
if( ex_ )
|
||||
detail::serialize_(w, *ex_);
|
||||
#endif
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
write_to_(wa);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
|
||||
@@ -299,6 +299,7 @@ protected:
|
||||
template <class Writer>
|
||||
error_id write_error_to(Writer & w) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
result_discriminant const what = what_;
|
||||
BOOST_LEAF_ASSERT(what.kind() != result_discriminant::val);
|
||||
error_id const err_id = what.get_error_id();
|
||||
@@ -309,6 +310,7 @@ protected:
|
||||
template <class Writer>
|
||||
void write_capture_to(Writer & w, error_id err_id) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
if( what_.kind() == result_discriminant::err_id_capture_list )
|
||||
{
|
||||
#if BOOST_LEAF_CFG_CAPTURE
|
||||
@@ -322,6 +324,7 @@ protected:
|
||||
template <class Writer>
|
||||
void print_error( Writer & w ) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
error_id err_id = write_error_to(w);
|
||||
w.set_prefix(", captured -> ");
|
||||
w.set_delimiter(", ");
|
||||
@@ -576,10 +579,11 @@ public:
|
||||
template <class Writer>
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
if( what_.kind() == result_discriminant::val )
|
||||
detail::serialize_(w, value());
|
||||
detail::serialize_(wa, value());
|
||||
else
|
||||
write_capture_to(w, write_error_to(w));
|
||||
write_capture_to(wa, write_error_to(wa));
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
@@ -695,7 +699,10 @@ public:
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
if( !*this )
|
||||
write_error_to(w);
|
||||
{
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
write_error_to(wa);
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#ifndef BOOST_LEAF_SERIALIZATION_JSON_WRITER_HPP_INCLUDED
|
||||
#define BOOST_LEAF_SERIALIZATION_JSON_WRITER_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// 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)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class Json, class E, class = void>
|
||||
struct has_to_json : std::false_type {};
|
||||
|
||||
template <class Json, class E>
|
||||
struct has_to_json<Json, E, decltype(to_json(std::declval<Json &>(), std::declval<E const &>()), void())> : std::true_type {};
|
||||
|
||||
template <class Json>
|
||||
class json_writer: public writer
|
||||
{
|
||||
Json & j_;
|
||||
|
||||
public:
|
||||
|
||||
explicit json_writer(Json & j) noexcept:
|
||||
writer(this),
|
||||
j_(j)
|
||||
{
|
||||
}
|
||||
|
||||
template <class E>
|
||||
friend void write_nested(json_writer & w, E const & e, char const * name)
|
||||
{
|
||||
json_writer nested(w.j_[name]);
|
||||
write(nested, e);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
friend typename std::enable_if<has_to_json<Json, E>::value>::type write(json_writer & w, E const & e)
|
||||
{
|
||||
to_json(w.j_, e);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_SERIALIZATION_JSON_WRITER_HPP_INCLUDED
|
||||
37
include/boost/leaf/serialization/nlohmann_writer.hpp
Normal file
37
include/boost/leaf/serialization/nlohmann_writer.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef BOOST_LEAF_SERIALIZATION_NLOHMANN_WRITER_HPP_INCLUDED
|
||||
#define BOOST_LEAF_SERIALIZATION_NLOHMANN_WRITER_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// 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)
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class Json>
|
||||
struct nlohmann_writer
|
||||
{
|
||||
Json & j_;
|
||||
|
||||
template <class T>
|
||||
friend auto write(nlohmann_writer & w, T const & x) -> decltype(to_json(std::declval<Json &>(), x))
|
||||
{
|
||||
to_json(w.j_, x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend void write_nested(nlohmann_writer & w, T const & x, char const * name)
|
||||
{
|
||||
nlohmann_writer nested{w.j_[name]};
|
||||
write(nested, x);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_SERIALIZATION_NLOHMANN_WRITER_HPP_INCLUDED
|
||||
@@ -1,72 +0,0 @@
|
||||
#ifndef BOOST_LEAF_SERIALIZATION_WRITER_HPP_INCLUDED
|
||||
#define BOOST_LEAF_SERIALIZATION_WRITER_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// 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)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/detail/type_name.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
class writer
|
||||
{
|
||||
detail::type_name const type_;
|
||||
|
||||
protected:
|
||||
|
||||
template <class Derived>
|
||||
explicit writer(Derived * d) noexcept:
|
||||
type_(detail::get_type_name<Derived>())
|
||||
{
|
||||
BOOST_LEAF_ASSERT(d == this), (void) d;
|
||||
}
|
||||
|
||||
~writer() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template <class Derived>
|
||||
Derived * get() noexcept
|
||||
{
|
||||
return type_ == detail::get_type_name<typename std::decay<Derived>::type>() ? static_cast<Derived *>(this) : nullptr;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class T, class E = void>
|
||||
struct has_member_value: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct has_member_value<T, decltype((void)std::declval<T const &>().value)>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class W, class E>
|
||||
typename std::enable_if<has_member_value<E>::value>::type
|
||||
write(W & w, E const & e)
|
||||
{
|
||||
write(w, e.value);
|
||||
}
|
||||
}
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_SERIALIZATION_WRITER_HPP_INCLUDED
|
||||
@@ -224,8 +224,7 @@ if option_enable_unit_tests
|
||||
'_hpp_on_error_test',
|
||||
'_hpp_pred_test',
|
||||
'_hpp_result_test',
|
||||
'_hpp_serialization_json_writer_test',
|
||||
'_hpp_serialization_writer_test',
|
||||
'_hpp_serialization_nlohmann_writer_test',
|
||||
'_hpp_to_variant_test',
|
||||
]
|
||||
foreach t : header_tests
|
||||
|
||||
@@ -44,8 +44,7 @@ compile _hpp_leaf_test.cpp ;
|
||||
compile _hpp_on_error_test.cpp ;
|
||||
compile _hpp_pred_test.cpp ;
|
||||
compile _hpp_result_test.cpp ;
|
||||
compile _hpp_serialization_json_writer_test.cpp ;
|
||||
compile _hpp_serialization_writer_test.cpp ;
|
||||
compile _hpp_serialization_nlohmann_writer_test.cpp ;
|
||||
compile _hpp_to_variant_test.cpp ;
|
||||
|
||||
run boost_exception_test.cpp ;
|
||||
@@ -160,11 +159,11 @@ compile-fail _compile-fail-error_obj_ptr.cpp ;
|
||||
compile-fail _compile-fail-exception_1.cpp ;
|
||||
compile-fail _compile-fail-exception_2.cpp ;
|
||||
compile-fail _compile-fail-new_error.cpp ;
|
||||
compile-fail _compile-fail-nlohmann.cpp ;
|
||||
compile-fail _compile-fail-result_1.cpp ;
|
||||
compile-fail _compile-fail-result_2.cpp ;
|
||||
compile-fail _compile-fail-result_3.cpp ;
|
||||
compile-fail _compile-fail-result_4.cpp ;
|
||||
compile-fail _compile-fail-to_json.cpp ;
|
||||
|
||||
exe try_capture_all_exceptions : ../example/try_capture_all_exceptions.cpp : <threading>single:<build>no <exception-handling>off:<build>no <variant>leaf_debug_capture0:<build>no <variant>leaf_release_capture0:<build>no ;
|
||||
exe try_capture_all_result : ../example/try_capture_all_result.cpp : <threading>single:<build>no <variant>leaf_debug_capture0:<build>no <variant>leaf_release_capture0:<build>no <variant>leaf_debug_embedded:<build>no <variant>leaf_release_embedded:<build>no ;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/leaf/serialization/json_writer.hpp>
|
||||
#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
struct no_to_json {};
|
||||
@@ -13,5 +13,6 @@ struct e_no_to_json
|
||||
};
|
||||
|
||||
nlohmann::json j;
|
||||
boost::leaf::serialization::nlohmann_writer<nlohmann::json> w{j};
|
||||
e_no_to_json e;
|
||||
auto x = (boost::leaf::serialization::to_json(j, e), 0);
|
||||
auto x = (write(w, e), 0);
|
||||
@@ -1,7 +0,0 @@
|
||||
// Copyright 2018-2025 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// 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)
|
||||
|
||||
#include <boost/leaf/serialization/json_writer.hpp>
|
||||
#include <boost/leaf/serialization/json_writer.hpp>
|
||||
int main() { return 0; }
|
||||
@@ -2,6 +2,6 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
int main() { return 0; }
|
||||
@@ -10,7 +10,7 @@
|
||||
# include <boost/leaf/diagnostics.hpp>
|
||||
# include <boost/leaf/common.hpp>
|
||||
# include <boost/leaf/on_error.hpp>
|
||||
# include <boost/leaf/serialization/json_writer.hpp>
|
||||
# include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
#endif
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
@@ -27,17 +27,19 @@
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
|
||||
using nlohmann_writer = leaf::serialization::json_writer<nlohmann::ordered_json>;
|
||||
using output_writer = leaf::serialization::nlohmann_writer<nlohmann::ordered_json>;
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization {
|
||||
|
||||
template <class E>
|
||||
void serialize(writer & w, E const & e, char const * name)
|
||||
template <class Handle, class E>
|
||||
void serialize(Handle & h, E const & e, char const * name)
|
||||
{
|
||||
if( nlohmann_writer * nw = w.get<nlohmann_writer>() )
|
||||
write_nested(*nw, e, name);
|
||||
h.dispatch(
|
||||
[&](nlohmann_writer<nlohmann::json> & w) { write_nested(w, e, name); },
|
||||
[&](nlohmann_writer<nlohmann::ordered_json> & w) { write_nested(w, e, name); }
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -222,7 +224,7 @@ int main()
|
||||
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
di.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -240,7 +242,7 @@ int main()
|
||||
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
dd.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -259,7 +261,7 @@ int main()
|
||||
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
di.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -278,7 +280,7 @@ int main()
|
||||
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
dd.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -297,7 +299,7 @@ int main()
|
||||
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
di.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -315,7 +317,7 @@ int main()
|
||||
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
dd.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -332,7 +334,7 @@ int main()
|
||||
},
|
||||
[&j](leaf::diagnostic_details const & dd, my_exception_ptr *)
|
||||
{
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
dd.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -354,7 +356,7 @@ int main()
|
||||
},
|
||||
[&j](leaf::diagnostic_details const & dd, my_exception_ptr *)
|
||||
{
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
dd.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -372,7 +374,7 @@ int main()
|
||||
nlohmann::ordered_json j;
|
||||
leaf::result<int> r = 42;
|
||||
BOOST_TEST(r);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
r.write_to(w);
|
||||
std::cout << __LINE__ << " result<int> success JSON output:\n" << std::setw(2) << j << std::endl;
|
||||
BOOST_TEST_EQ(j["int"].get<int>(), 42);
|
||||
@@ -382,7 +384,7 @@ int main()
|
||||
nlohmann::ordered_json j;
|
||||
leaf::result<int> r = leaf::new_error();
|
||||
BOOST_TEST(!r);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
r.write_to(w);
|
||||
std::cout << __LINE__ << " result<int> error JSON output:\n" << std::setw(2) << j << std::endl;
|
||||
BOOST_TEST(j["boost::leaf::error_id"].get<int>() > 0);
|
||||
@@ -397,7 +399,7 @@ int main()
|
||||
return leaf::new_error(my_error<1>{1, "error one"}, my_error<2>{2, "error two"});
|
||||
} );
|
||||
BOOST_TEST(!r);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
r.write_to(w);
|
||||
std::cout << __LINE__ << " result<int> captured error JSON output:\n" << std::setw(2) << j << std::endl;
|
||||
BOOST_TEST(j["boost::leaf::error_id"].get<int>() > 0);
|
||||
|
||||
@@ -10,11 +10,6 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <unordered_set>
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
# include <string_view>
|
||||
#endif
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
namespace detail = boost::leaf::detail;
|
||||
@@ -84,38 +79,5 @@ int main()
|
||||
BOOST_TEST(get_type_name<int>() != get_type_name<float>());
|
||||
BOOST_TEST(get_type_name<class_>() != get_type_name<struct_>());
|
||||
|
||||
BOOST_TEST(get_type_name<class_>() < get_type_name<struct_>()); // "class_" < "struct_"
|
||||
BOOST_TEST(!(get_type_name<struct_>() < get_type_name<class_>()));
|
||||
BOOST_TEST(!(get_type_name<int>() < get_type_name<int>())); // not less than itself
|
||||
BOOST_TEST(get_type_name<int>() < get_type_name<long>()); // "int" < "long"
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
{
|
||||
auto sv = to_string_view(get_type_name<int>());
|
||||
BOOST_TEST(sv == "int");
|
||||
}
|
||||
{
|
||||
auto sv = to_string_view(get_type_name<class_>());
|
||||
BOOST_TEST(sv == "class_");
|
||||
}
|
||||
{
|
||||
auto sv = to_string_view(get_type_name<leaf_test::struct_>());
|
||||
BOOST_TEST(sv == "leaf_test::struct_");
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOST_TEST(std::hash<detail::type_name>()(get_type_name<int>()) == get_type_name<int>().hash);
|
||||
BOOST_TEST(std::hash<detail::type_name>()(get_type_name<int>()) == std::hash<detail::type_name>()(get_type_name<int>()));
|
||||
{
|
||||
std::unordered_set<detail::type_name> s;
|
||||
s.insert(get_type_name<int>());
|
||||
s.insert(get_type_name<float>());
|
||||
s.insert(get_type_name<int>()); // duplicate
|
||||
BOOST_TEST(s.size() == 2);
|
||||
BOOST_TEST(s.count(get_type_name<int>()) == 1);
|
||||
BOOST_TEST(s.count(get_type_name<float>()) == 1);
|
||||
BOOST_TEST(s.count(get_type_name<double>()) == 0);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user