2
0
mirror of https://github.com/boostorg/leaf.git synced 2026-01-19 04:22:08 +00:00

renamed write / write_nested to output / output_at

This commit is contained in:
Emil Dotchevski
2026-01-13 15:34:49 -05:00
parent d09a551b38
commit 2b09481f23
25 changed files with 498 additions and 479 deletions

View File

@@ -1733,19 +1733,19 @@ TIP: The automatically generated diagnostic messages are developer-friendly, but
[[tutorial-serialization]]
=== Serialization
LEAF provides a serialization API that enables exporting error information into different formats, such as JSON. This is useful for structured logging, remote debugging, or integrating with monitoring systems. To serialize error information, use the `write_to` member function available on the following types:
LEAF provides a serialization API that enables exporting error information into different formats, such as JSON. This is useful for structured logging, remote debugging, or integrating with monitoring systems. To serialize error information, use the `output_to` member function available on the following types:
* <<error_info>>
* <<diagnostic_info>>
* <<diagnostic_details>>
* <<result>>
LEAF serialization is defined in terms of `write` and `write_nested` function calls, found via ADL:
LEAF serialization is defined in terms of `output` and `output_at` function calls, found via ADL:
* `write(w, x)` serializes `x` directly to writer `w`.
* `write_nested(w, x, name)` serializes `x` to writer `w` as a named field.
* `output(e, x)` serializes `x` directly to encoder `e` as a value.
* `output_at(e, x, name)` serializes `x` to encoder `e` as a named field.
LEAF provides generic `write` overloads for the following types:
LEAF provides generic `output` overloads for the following types:
* `error_id`
* `e_source_location`
@@ -1754,38 +1754,36 @@ LEAF provides generic `write` overloads for the following types:
* `std::error_condition`
* `std::exception`
* `std::exception_ptr`
* any type with a `.value` member for which a suitable `write` can be found via ADL
* any type with a `.value` member for which a suitable `output` can be found via ADL
[[custom-writers]]
==== Custom Writers
[[custom-encoders]]
==== Custom Encoders
To support exporting to a specific format, users define a writer class with associated `write` and `write_nested` function templates specific to that writer:
To support exporting to a specific format, users define an encoder class with associated `output` and `output_at` function templates specific to that encoder:
[source,c++]
----
struct my_writer
struct my_encoder
{
std::ostream & os;
template <class T>
friend void write(my_writer & w, T const & x)
friend void output(my_encoder & e, T const & x)
{
// write x to w
// output value x to e
}
template <class T>
friend void write_nested(my_writer & w, T const & x, char const * name)
friend void output_at(my_encoder & e, T const & x, char const * name)
{
// write x to w as a named field
// output x to e 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.
The `output_at` function typically creates a nested scope (e.g. a JSON object or XML element) and then makes an unqualified call to `output` 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`.
TIP: The `output` function may need to be defined using SFINAE to avoid ambiguities with the generic `output` overloads provided by LEAF. Custom encoders must also handle types that do not provide ADL `output` 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:
To enable serialization to a custom encoder type, define a `serialize` function template in the `boost::leaf::serialization` namespace:
[source,c++]
----
@@ -1793,11 +1791,11 @@ namespace boost { namespace leaf {
namespace serialization {
template <class Handle, class E>
void serialize(Handle & h, E const & e, char const * name)
template <class Handle, class T>
void serialize(Handle & h, T const & x, char const * name)
{
h.dispatch([&](my_writer & mw) {
write_nested(mw, e, name);
h.dispatch([&](my_encoder & e) {
output_at(e, x, name);
});
}
@@ -1806,45 +1804,45 @@ namespace serialization {
} }
----
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.
The `serialize` function template takes a handle reference `h` (of unspecified type) that holds an encoder, the error object to be serialized, and its type name. Call `h.dispatch` with a single-argument function F to detect the encoder type based on F's argument type; F is called only if the handle contains an encoder of that type.
To support multiple output formats, pass multiple functions to `h.dispatch`:
[source,c++]
----
h.dispatch(
[&](json_writer_nlohmann & w) { write_nested(w, e, name); },
[&](xml_writer & xw) { write_nested(xw, e, name); }
[&](json_encoder_nlohmann & e) { output_at(e, x, name); },
[&](xml_encoder & xe) { output_at(xe, x, name); }
);
----
==== JSON Serialization
LEAF provides writers for JSON serialization with two popular JSON libraries:
LEAF provides encoders for JSON serialization with two popular JSON libraries:
* <<json_writer_nlohmann>> for https://github.com/nlohmann/json[nlohmann/json]
* <<json_writer_boost>> for https://www.boost.org/doc/libs/release/libs/json/[Boost.JSON]
* <<json_encoder_nlohmann>> for https://github.com/nlohmann/json[nlohmann/json]
* <<json_encoder_boost>> for https://www.boost.org/doc/libs/release/libs/json/[Boost.JSON]
Below is an example using `json_writer_nlohmann`. We just need to define the required `serialize` function template (see <<custom-writers>>):
Below is an example using `json_encoder_nlohmann`. We just need to define the required `serialize` function template (see <<custom-encoders>>):
[source,c++]
----
#include <boost/leaf/serialization/json_writer_nlohmann.hpp>
#include <boost/leaf/serialization/json_encoder_nlohmann.hpp>
#include "nlohmann/json.hpp"
namespace leaf = boost::leaf;
using json_writer_nlohmann = leaf::serialization::json_writer_nlohmann<nlohmann::json>;
using json_encoder_nlohmann = leaf::serialization::json_encoder_nlohmann<nlohmann::json>;
namespace boost { namespace leaf {
namespace serialization {
template <class Handle, class E>
void serialize(Handle & h, E const & e, char const * name)
template <class Handle, class T>
void serialize(Handle & h, T const & x, char const * name)
{
h.dispatch([&](json_writer_nlohmann & w) {
write_nested(w, e, name);
h.dispatch([&](json_encoder_nlohmann & e) {
output_at(e, x, name);
});
}
@@ -1853,7 +1851,7 @@ namespace serialization {
} }
----
With this in place, we can easily (for example) serialize <<diagnostic_details>> to JSON:
With this in place, we can easily (for example) output <<diagnostic_details>> to JSON:
[source,c++]
----
@@ -1886,8 +1884,8 @@ leaf::try_handle_all(
[](leaf::diagnostic_details const & dd)
{
nlohmann::json j;
json_writer_nlohmann w(j);
dd.write_to(w);
json_encoder_nlohmann e(j);
dd.output_to(e);
std::cout << j.dump(2) << std::endl;
}
);
@@ -1908,6 +1906,8 @@ leaf::try_handle_all(
[.text-right]
<<diagnostic_details>> | <<diagnostic_info>> | <<error_info>>
NOTE: In the example above, `e_api_response` uses an unqualified call to `to_json` for serialization. This is to demonstrate that `json_encoder_nlohmann` handles third party type with suitable `to_json` overloads automatically. If instead we defined a function `output` compatible with the LEAF serialization API, it would make `e_api_response` compatible with any LEAF encoder.
'''
[[tutorial-std_error_code]]
@@ -2525,8 +2525,8 @@ namespace boost { namespace leaf {
void unload();
template <class Writer>
void write_to( Writer & w ) const;
template <class Encoder>
void output_to( Encoder & e ) const;
template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> &, result const & );
@@ -2574,8 +2574,8 @@ namespace boost { namespace leaf {
void unload();
template <class Writer>
void write_to( Writer & w ) const;
template <class Encoder>
void output_to( Encoder & e ) const;
template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> &, result const &);
@@ -2867,28 +2867,28 @@ Reference: <<to_variant>>
=== Serialization
[[json_writer_boost.hpp]]
==== `json_writer_boost.hpp`
[[json_encoder_boost.hpp]]
==== `json_encoder_boost.hpp`
====
.#include <boost/leaf/serialization/json_writer_boost.hpp>
.#include <boost/leaf/serialization/json_encoder_boost.hpp>
[source,c++]
----
namespace boost { namespace leaf {
namespace serialization
{
struct json_writer_boost
struct json_encoder_boost
{
boost::json::value & v_;
// Enabled if x is assignable to boost::json::value, or
// if tag_invoke is defined for boost::json::value_from_tag.
template <class T>
friend void write( json_writer_boost &, T const & x );
friend void output( json_encoder_boost &, T const & x );
template <class T>
friend void write_nested( json_writer_boost &, T const &, char const * name );
friend void output_at( json_encoder_boost &, T const &, char const * name );
};
}
@@ -2896,14 +2896,14 @@ namespace serialization
----
[.text-right]
Reference: <<json_writer_boost>>
Reference: <<json_encoder_boost>>
====
[[json_writer_nlohmann.hpp]]
==== `json_writer_nlohmann.hpp`
[[json_encoder_nlohmann.hpp]]
==== `json_encoder_nlohmann.hpp`
====
.#include <boost/leaf/serialization/json_writer_nlohmann.hpp>
.#include <boost/leaf/serialization/json_encoder_nlohmann.hpp>
[source,c++]
----
namespace boost { namespace leaf {
@@ -2911,16 +2911,16 @@ namespace boost { namespace leaf {
namespace serialization
{
template <class Json>
struct json_writer_nlohmann
struct json_encoder_nlohmann
{
Json & j_;
// Enabled if to_json is defined for Json and T.
// Enabled if to_json is available for Json and T.
template <class T>
friend void write( json_writer_nlohmann &, T const & x );
friend void output( json_encoder_nlohmann &, T const & x );
template <class T>
friend void write_nested( json_writer_nlohmann &, T const &, char const * name );
friend void output_at( json_encoder_nlohmann &, T const &, char const * name );
};
}
@@ -2928,7 +2928,7 @@ namespace serialization
----
[.text-right]
Reference: <<json_writer_nlohmann>>
Reference: <<json_encoder_nlohmann>>
====
[[functions]]
@@ -3935,8 +3935,8 @@ namespace boost { namespace leaf {
public:
template <class Writer>
void write_to( Writer & w ) const;
template <class Encoder>
void output_to( Encoder & e ) const;
template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> &, diagnostic_details const & );
@@ -3951,7 +3951,7 @@ The message printed by `operator<<` includes the message printed by `error_info`
The additional information includes the types and the values of all such error objects (but see <<show_in_diagnostics>>).
The `write_to` member function is used with the serialization system; see <<tutorial-serialization>>.
The `output_to` member function is used with the serialization system; see <<tutorial-serialization>>.
[NOTE]
--
@@ -3979,8 +3979,8 @@ namespace boost { namespace leaf {
public:
template <class Writer>
void write_to( Writer & w ) const;
template <class Encoder>
void output_to( Encoder & e ) const;
template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> &, diagnostic_info const & );
@@ -3995,7 +3995,7 @@ The message printed by `operator<<` includes the message printed by `error_info`
The additional information is limited to the type name of the first such error object, as well as their total count.
The `write_to` member function is used with the serialization system; see <<tutorial-serialization>>.
The `output_to` member function is used with the serialization system; see <<tutorial-serialization>>.
[NOTE]
--
@@ -4448,8 +4448,8 @@ namespace boost { namespace leaf {
bool exception_caught() const noexcept;
std::exception const * exception() const noexcept;
template <class Writer>
void write_to( Writer & w ) const;
template <class Encoder>
void output_to( Encoder & e ) const;
template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> &, error_info const & );
@@ -4470,38 +4470,38 @@ WARNING: It is illegal to call the `exception` member function unless `exception
The `operator<<` overload prints diagnostic information about each error object currently stored in the <<context>> local to the <<try_handle_some>>, <<try_handle_all>> or <<try_catch>> scope that invoked the handler, but only if it is associated with the <<error_id>> returned by `error()`.
The `write_to` member function is used with the serialization system; see <<tutorial-serialization>>.
The `output_to` member function is used with the serialization system; see <<tutorial-serialization>>.
'''
[[json_writer_boost]]
=== `json_writer_boost`
[[json_encoder_boost]]
=== `json_encoder_boost`
.#include <boost/leaf/serialization/json_writer_boost.hpp>
.#include <boost/leaf/serialization/json_encoder_boost.hpp>
[source,c++]
----
namespace boost { namespace leaf {
namespace serialization
{
struct json_writer_boost
struct json_encoder_boost
{
boost::json::value & v_;
// Enabled if x is assignable to boost::json::value, or
// if tag_invoke is defined for boost::json::value_from_tag.
template <class T>
friend void write( json_writer_boost &, T const & x );
friend void output( json_encoder_boost &, T const & x );
template <class T>
friend void write_nested( json_writer_boost &, T const &, char const * name );
friend void output_at( json_encoder_boost &, T const &, char const * name );
};
}
} }
----
The `json_writer_boost` type serializes error objects to JSON format using https://www.boost.org/doc/libs/release/libs/json/[Boost.JSON]. The `write` function is enabled for:
The `json_encoder_boost` type serializes error objects to JSON format using https://www.boost.org/doc/libs/release/libs/json/[Boost.JSON]. The `output` function is enabled for:
* Types directly assignable to `boost::json::value`
* Types for which a `tag_invoke` overload for `value_from_tag` can be found via ADL
@@ -4510,10 +4510,10 @@ See <<tutorial-serialization>>.
'''
[[json_writer_nlohmann]]
=== `json_writer_nlohmann`
[[json_encoder_nlohmann]]
=== `json_encoder_nlohmann`
.#include <boost/leaf/serialization/json_writer_nlohmann.hpp>
.#include <boost/leaf/serialization/json_encoder_nlohmann.hpp>
[source,c++]
----
namespace boost { namespace leaf {
@@ -4521,23 +4521,23 @@ namespace boost { namespace leaf {
namespace serialization
{
template <class Json>
struct json_writer_nlohmann
struct json_encoder_nlohmann
{
Json & j_;
// Enabled if to_json is defined for Json and T.
// Enabled if to_json is available for Json and T.
template <class T>
friend void write( json_writer_nlohmann &, T const & x );
friend void output( json_encoder_nlohmann &, T const & x );
template <class T>
friend void write_nested( json_writer_nlohmann &, T const &, char const * name );
friend void output_at( json_encoder_nlohmann &, T const &, char const * name );
};
}
} }
----
The `json_writer_nlohmann` 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>>.
The `json_encoder_nlohmann` type 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>>.
'''
@@ -4612,8 +4612,8 @@ namespace boost { namespace leaf {
void unload();
template <class Writer>
void write_to( Writer & w ) const;
template <class Encoder>
void output_to( Encoder & e ) const;
template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> &, result const & );
@@ -4661,8 +4661,8 @@ namespace boost { namespace leaf {
void unload();
template <class Writer>
void write_to( Writer & w ) const;
template <class Encoder>
void output_to( Encoder & e ) const;
template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> &, result const &);
@@ -4678,7 +4678,7 @@ namespace boost { namespace leaf {
} }
----
[.text-right]
<<result::result>> | <<result::operator_eq>> | <<result::has_value>> | <<result::has_error>> | <<result::operator_bool>> | <<result::value>> | <<result::operator_ptr>> | <<result::operator_deref>> | <<result::error>> | <<result::load>> | <<result::write_to>>
<<result::result>> | <<result::operator_eq>> | <<result::has_value>> | <<result::has_error>> | <<result::operator_bool>> | <<result::value>> | <<result::operator_ptr>> | <<result::operator_deref>> | <<result::error>> | <<result::load>> | <<result::output_to>>
The `result<T>` type can be returned by functions which produce a value of type `T` but may fail doing so.
@@ -4982,8 +4982,8 @@ A member type of `result<T>`, defined as a synonym for `T`.
'''
[[result::write_to]]
==== `write_to`
[[result::output_to]]
==== `output_to`
.#include <boost/leaf/result.hpp>
[source,c++]
@@ -4991,17 +4991,17 @@ A member type of `result<T>`, defined as a synonym for `T`.
namespace boost { namespace leaf {
template <class T>
template <class Writer>
void result<T>::write_to( Writer & w ) const;
template <class Encoder>
void result<T>::output_to( Encoder & e ) const;
} }
----
The `write_to` member function is used with the serialization system; see <<tutorial-serialization>>.
The `output_to` member function is used with the serialization system; see <<tutorial-serialization>>.
If the result is in <<result,value state>>, outputs the value. If it is in <<result,error state>>, outputs the <<error_id>>. If the result holds <<try_capture_all,captured error objects>>, outputs them as well.
NOTE: Result objects carry error objects only when in <<try_capture_all,capture state>>. Otherwise, to output error objects, use `write_to` on <<diagnostic_details>> in an error handling scope.
NOTE: Result objects carry error objects only when in <<try_capture_all,capture state>>. Otherwise, to output error objects, use `output_to` on <<diagnostic_details>> in an error handling scope.
'''

View File

@@ -58,11 +58,11 @@ struct e_errno
return os << err.value << ", \"" << std::strerror(err.value) << '"';
}
template <class Writer>
friend void write( Writer & w, e_errno const & e )
template <class Encoder>
friend void output( Encoder & e, e_errno const & x )
{
write_nested(w, e.value, "errno");
write_nested(w, std::strerror(e.value), "strerror");
output_at(e, x.value, "errno");
output_at(e, std::strerror(x.value), "strerror");
}
};

View File

@@ -204,11 +204,11 @@ namespace detail
tuple_for_each<I-1,Tup>::unload(tup, err_id);
}
static void write_to(writer & w, void const * tup, error_id id)
static void output_to(encoder & e, void const * tup, error_id id)
{
BOOST_LEAF_ASSERT(tup != nullptr);
tuple_for_each<I-1,Tup>::write_to(w, tup, id);
std::get<I-1>(*static_cast<Tup const *>(tup)).write_to(w, id);
tuple_for_each<I-1,Tup>::output_to(e, tup, id);
std::get<I-1>(*static_cast<Tup const *>(tup)).output_to(e, id);
}
};
@@ -218,13 +218,13 @@ 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(writer &, void const *, error_id) { }
BOOST_LEAF_CONSTEXPR static void output_to(encoder &, void const *, error_id) { }
};
template <class Tup>
void serialize_tuple_contents(writer & w, void const * tup, error_id id)
void output_tuple_contents(encoder & e, void const * tup, error_id id)
{
tuple_for_each<std::tuple_size<Tup>::value, Tup>::write_to(w, tup, id);
tuple_for_each<std::tuple_size<Tup>::value, Tup>::output_to(e, tup, id);
}
} // namespace detail
@@ -368,9 +368,9 @@ public:
return is_active_;
}
void write_to( detail::diagnostics_writer & w ) const
void output_to( detail::diagnostics_writer & e ) const
{
detail::serialize_tuple_contents<Tup>(w, &tup_, error_id());
detail::output_tuple_contents<Tup>(e, &tup_, error_id());
}
template <class CharT, class Traits>
@@ -378,7 +378,7 @@ public:
{
detail::diagnostics_writer w(os);
w.set_prefix("Contents:");
ctx.write_to(w);
ctx.output_to(w);
return os;
}

View File

@@ -11,6 +11,6 @@
#include <boost/leaf/on_error.hpp>
#include <boost/leaf/pred.hpp>
#include <boost/leaf/result.hpp>
#include <boost/leaf/serialization/json_writer_boost.hpp>
#include <boost/leaf/serialization/json_writer_nlohmann.hpp>
#include <boost/leaf/serialization/json_encoder_boost.hpp>
#include <boost/leaf/serialization/json_encoder_nlohmann.hpp>
#include <boost/leaf/to_variant.hpp>

View File

@@ -15,7 +15,7 @@ class error_id;
namespace detail
{
class writer;
class encoder;
class capture_list
{
@@ -29,7 +29,7 @@ namespace detail
friend class capture_list;
virtual void unload( int err_id ) = 0;
virtual void write_to(writer &, error_id const &) const = 0;
virtual void output_to(encoder &, error_id const &) const = 0;
protected:
@@ -90,14 +90,14 @@ namespace detail
} );
}
void write_to(writer & w, error_id const & id) const
void output_to(encoder & e, error_id const & id) const
{
if( first_ )
{
for_each(
[&w, &id]( node const & n )
[&e, &id]( node const & n )
{
n.write_to(w, id);
n.output_to(e, id);
} );
}
}

View File

@@ -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/detail/writer.hpp>
#include <boost/leaf/detail/encoder.hpp>
#include <boost/leaf/detail/exception_base.hpp>
#include <type_traits>
@@ -52,7 +52,7 @@ namespace detail
////////////////////////////////////////
class diagnostics_writer: public writer
class diagnostics_writer: public encoder
{
diagnostics_writer(diagnostics_writer const &) = delete;
diagnostics_writer & operator=(diagnostics_writer const &) = delete;
@@ -109,7 +109,7 @@ namespace detail
template <class CharT, class Traits>
explicit diagnostics_writer(std::basic_ostream<CharT, Traits> & os) noexcept:
writer(this),
encoder(this),
os_(os),
prefix_(BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER),
delimiter_(BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER),
@@ -119,7 +119,7 @@ namespace detail
template <class CharT, class Traits>
diagnostics_writer(std::basic_ostream<CharT, Traits> & os, error_id const & id, e_source_location const * loc, std::exception const * ex) noexcept:
writer(this),
encoder(this),
os_(os),
prefix_(BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER),
delimiter_(BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER),

View File

@@ -0,0 +1,92 @@
#ifndef BOOST_LEAF_DETAIL_ENCODER_HPP_INCLUDED
#define BOOST_LEAF_DETAIL_ENCODER_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 encoder_adl {};
template <class Encoder, class T>
auto output(Encoder & e, T const & x) -> decltype(output(e, x.value))
{
output(e, x.value);
}
}
namespace detail
{
class encoder:
serialization::encoder_adl
{
encoder(encoder const &) = delete;
encoder & operator=(encoder const &) = delete;
type_name const type_;
void * const e_;
bool dispatch_()
{
return false;
}
template <class F1, class... Fn>
bool dispatch_(F1 && f1, Fn && ... fn)
{
using encoder_type = typename std::decay<fn_arg_type<F1, 0>>::type;
if (encoder_type * e = get<encoder_type>())
{
std::forward<F1>(f1)(*e);
return true;
}
return dispatch_(std::forward<Fn>(fn)...);
}
protected:
template <class Encoder>
explicit encoder(Encoder * e) noexcept:
type_(get_type_name<Encoder>()),
e_(e)
{
}
public:
template <class Encoder>
Encoder * get() noexcept
{
return type_ == get_type_name<Encoder>() ? static_cast<Encoder *>(e_) : nullptr;
}
template <class... Fn>
bool dispatch(Fn && ... fn)
{
using encoder_types = leaf_detail_mp11::mp_list<typename std::decay<fn_arg_type<Fn, 0>>::type...>;
static_assert(std::is_same<encoder_types, leaf_detail_mp11::mp_unique<encoder_types>>::value, "Duplicate encoder types in dispatch");
return dispatch_(std::forward<Fn>(fn)...);
}
};
template <class Encoder>
struct encoder_adaptor:
encoder
{
explicit encoder_adaptor(Encoder & e) noexcept:
encoder(&e)
{
}
};
} // namespace detail
} } // namespace boost::leaf
#endif // #ifndef BOOST_LEAF_DETAIL_ENCODER_HPP_INCLUDED

View File

@@ -1,92 +0,0 @@
#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

View File

@@ -13,7 +13,7 @@ namespace boost { namespace leaf {
class diagnostic_info: public error_info
{
void const * tup_;
void (*serialize_tuple_contents_)(detail::writer &, void const *, error_id);
void (*output_tuple_contents_)(detail::encoder &, void const *, error_id);
protected:
@@ -23,25 +23,25 @@ protected:
BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei, Tup const & tup ) noexcept:
error_info(ei),
tup_(&tup),
serialize_tuple_contents_(&detail::serialize_tuple_contents<Tup>)
output_tuple_contents_(&detail::output_tuple_contents<Tup>)
{
}
template <class Writer>
void write_to_(Writer & w) const
template <class Encoder>
void output_to_(Encoder & e) const
{
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
serialize_tuple_contents_(w, tup_, error());
static_assert(std::is_base_of<detail::encoder, Encoder>::value, "Encoder must derive from detail::encoder");
output_tuple_contents_(e, tup_, error());
}
public:
template <class Writer>
void write_to(Writer & w) const
template <class Encoder>
void output_to(Encoder & e) const
{
detail::writer_adaptor<Writer> wa(w);
error_info::write_to_(wa);
write_to_(wa);
detail::encoder_adaptor<Encoder> ea(e);
error_info::output_to_(ea);
output_to_(ea);
}
template <class CharT, class Traits>
@@ -49,7 +49,7 @@ public:
{
detail::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
#if BOOST_LEAF_CFG_DIAGNOSTICS
x.write_to_(w);
x.output_to_(w);
#else
os << "\nboost::leaf::diagnostic_info N/A due to BOOST_LEAF_CFG_DIAGNOSTICS=0";
#endif
@@ -98,23 +98,23 @@ protected:
{
}
template <class Writer>
void write_to_(Writer & w) const
template <class Encoder>
void output_to_(Encoder & e) const
{
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
static_assert(std::is_base_of<detail::encoder, Encoder>::value, "Encoder must derive from detail::encoder");
if( da_ )
da_->write_to(w, error());
da_->output_to(e, error());
}
public:
template <class Writer>
void write_to(Writer & w) const
template <class Encoder>
void output_to(Encoder & e) const
{
detail::writer_adaptor<Writer> wa(w);
error_info::write_to_(wa);
diagnostic_info::write_to_(wa);
write_to_(wa);
detail::encoder_adaptor<Encoder> ea(e);
error_info::output_to_(ea);
diagnostic_info::output_to_(ea);
output_to_(ea);
}
template <class CharT, class Traits>
@@ -122,9 +122,9 @@ public:
{
detail::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
#if BOOST_LEAF_CFG_DIAGNOSTICS
x.diagnostic_info::write_to_(w);
x.diagnostic_info::output_to_(w);
w.set_prefix("\nDiagnostic details:" BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER);
x.write_to_(w);
x.output_to_(w);
#else
os << "\nboost::leaf::diagnostic_details N/A due to BOOST_LEAF_CFG_DIAGNOSTICS=0";
#endif
@@ -171,12 +171,12 @@ protected:
public:
template <class Writer>
void write_to(Writer & w) const
template <class Encoder>
void output_to(Encoder & e) const
{
detail::writer_adaptor<Writer> wa(w);
error_info::write_to_(wa);
diagnostic_info::write_to_(wa);
detail::encoder_adaptor<Encoder> ea(e);
error_info::output_to_(ea);
diagnostic_info::output_to_(ea);
}
template <class CharT, class Traits>
@@ -184,7 +184,7 @@ public:
{
detail::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
#if BOOST_LEAF_CFG_DIAGNOSTICS
x.diagnostic_info::write_to_(w);
x.diagnostic_info::output_to_(w);
os << "\nboost::leaf::diagnostic_details N/A due to BOOST_LEAF_CFG_CAPTURE=0";
#else
os << "\nboost::leaf::diagnostic_details N/A due to BOOST_LEAF_CFG_DIAGNOSTICS=0";

View File

@@ -21,20 +21,20 @@ namespace boost { namespace leaf {
namespace serialization
{
template <class Writer>
void write(Writer & w, std::error_code const & ec)
template <class Encoder>
void output(Encoder & e, std::error_code const & x)
{
write_nested(w, ec.category().name(), "category");
write_nested(w, ec.value(), "value");
write_nested(w, ec.message(), "message");
output_at(e, x.category().name(), "category");
output_at(e, x.value(), "value");
output_at(e, x.message(), "message");
}
template <class Writer>
void write(Writer & w, std::error_condition const & ec)
template <class Encoder>
void output(Encoder & e, std::error_condition const & x)
{
write_nested(w, ec.category().name(), "category");
write_nested(w, ec.value(), "value");
write_nested(w, ec.message(), "message");
output_at(e, x.category().name(), "category");
output_at(e, x.value(), "value");
output_at(e, x.message(), "message");
}
}
@@ -100,12 +100,12 @@ struct e_source_location
return os << x.file << '(' << x.line << ") in function " << x.function;
}
template <class Writer>
friend void write( Writer & w, e_source_location const & x )
template <class Encoder>
friend void output( Encoder & e, e_source_location const & x )
{
write_nested(w, x.file, "file");
write_nested(w, x.line, "line");
write_nested(w, x.function, "function");
output_at(e, x.file, "file");
output_at(e, x.line, "line");
output_at(e, x.function, "function");
}
};
@@ -119,9 +119,9 @@ struct show_in_diagnostics<e_source_location>: std::false_type
namespace serialization
{
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 && ...)
template <class Encoder, class T, class... Unused>
typename std::enable_if<std::is_base_of<detail::encoder, Encoder>::value>::type
serialize(Encoder &, T const &, char const *, Unused && ...)
{
}
}
@@ -129,18 +129,18 @@ namespace serialization
namespace detail
{
template <class T>
void serialize_(diagnostics_writer & w, T const & x)
void serialize_(diagnostics_writer & e, T const & x)
{
w.write(x);
e.write(x);
}
template <class T>
void serialize_(writer & w, T const & x)
void serialize_(encoder & e, T const & x)
{
using namespace serialization;
char zstr[1024];
serialize(w, x, to_zstr(zstr, get_type_name<T>()));
if( diagnostics_writer * dw = w.get<diagnostics_writer>() )
serialize(e, x, to_zstr(zstr, get_type_name<T>()));
if( diagnostics_writer * dw = e.get<diagnostics_writer>() )
dw->write(x);
}
}
@@ -201,15 +201,15 @@ namespace detail
void unload( int err_id ) noexcept(!BOOST_LEAF_CFG_CAPTURE);
template <class Writer,class ErrorID>
void write_to(Writer & w, ErrorID id) const
template <class Encoder,class ErrorID>
void output_to(Encoder & e, ErrorID id) const
{
static_assert(std::is_base_of<writer, Writer>::value, "Writer must derive from detail::writer");
static_assert(std::is_base_of<encoder, Encoder>::value, "Encoder must derive from detail::encoder");
if( int k = this->key() )
{
if( id && id.value() != k )
return;
serialize_(w, value(k));
serialize_(e, value(k));
}
}
@@ -271,9 +271,9 @@ namespace detail
{
impl::unload(err_id);
}
void write_to(writer & w, error_id const & id) const override
void output_to(encoder & e, error_id const & id) const override
{
impl::write_to(w, id);
impl::output_to(e, id);
}
public:
BOOST_LEAF_CONSTEXPR explicit capturing_slot_node( capture_list::node * * & last ):
@@ -306,7 +306,7 @@ namespace detail
{
std::rethrow_exception(ex_);
}
void write_to(writer &, error_id const &) const override
void output_to(encoder &, error_id const &) const override
{
}
std::exception_ptr const ex_;
@@ -406,7 +406,7 @@ namespace detail
}
using capture_list::unload;
using capture_list::write_to;
using capture_list::output_to;
}; // class dynamic_allocator
template <class E>
@@ -482,7 +482,7 @@ namespace detail
}
template <class ErrorID>
void write_to(writer &, ErrorID) const
void output_to(encoder &, ErrorID) const
{
}
}; // slot specialization for dynamic_allocator
@@ -838,10 +838,10 @@ public:
return os << (x.value_ / 4);
}
template <class Writer>
friend void write( Writer & w, error_id x )
template <class Encoder>
friend void output( Encoder & e, error_id x )
{
write(w, x.value_ / 4);
output(e, x.value_ / 4);
}
BOOST_LEAF_CONSTEXPR void load_source_location_( char const * file, int line, char const * function ) const noexcept(!BOOST_LEAF_CFG_CAPTURE)

View File

@@ -17,46 +17,46 @@ namespace boost { namespace leaf {
namespace serialization
{
template <class Writer>
void write(Writer & w, std::exception const & ex)
template <class Encoder>
void output(Encoder & e, std::exception const & x)
{
char const dynamic_type[] = "dynamic_type";
char const what[] = "what";
#ifdef BOOST_LEAF_NO_EXCEPTIONS
write_nested(w, "<<unknown>>", dynamic_type);
output_at(e, "<<unknown>>", dynamic_type);
#else
write_nested(w, detail::demangler(typeid(ex).name()).get(), dynamic_type);
output_at(e, detail::demangler(typeid(x).name()).get(), dynamic_type);
#endif
if( char const * wh = ex.what() )
write_nested(w, wh, what);
if( char const * wh = x.what() )
output_at(e, wh, what);
else
write_nested(w, "<<nullptr>>", what);
output_at(e, "<<nullptr>>", what);
}
template <class Writer>
void write(Writer & w, std::exception_ptr const & ep)
template <class Encoder>
void output(Encoder & e, std::exception_ptr const & x)
{
if( ep )
if( x )
{
#ifndef BOOST_LEAF_NO_EXCEPTIONS
try
{
std::rethrow_exception(ep);
std::rethrow_exception(x);
}
catch( std::exception const & ex )
{
write(w, ex);
output(e, ex);
return;
}
catch( ... )
{
}
#endif
write_nested(w, "<<unknown>>", "dynamic_type");
output_at(e, "<<unknown>>", "dynamic_type");
}
else
write_nested(w, "<<empty>>", "dynamic_type");
write_nested(w, "N/A", "what");
output_at(e, "<<empty>>", "dynamic_type");
output_at(e, "N/A", "what");
}
}

View File

@@ -45,14 +45,14 @@ protected:
error_info( error_info const & ) noexcept = default;
template <class Writer>
void write_to_(Writer & w) const
template <class Encoder>
void output_to_(Encoder & e) const
{
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
detail::serialize_(w, err_id_);
static_assert(std::is_base_of<detail::encoder, Encoder>::value, "Encoder must derive from detail::encoder");
detail::serialize_(e, err_id_);
#ifndef BOOST_LEAF_NO_EXCEPTIONS
if( ex_ )
detail::serialize_(w, *ex_);
detail::serialize_(e, *ex_);
#endif
}
@@ -87,11 +87,11 @@ public:
return loc_;
}
template <class Writer>
void write_to(Writer & w) const
template <class Encoder>
void output_to(Encoder & e) const
{
detail::writer_adaptor<Writer> wa(w);
write_to_(wa);
detail::encoder_adaptor<Encoder> ea(e);
output_to_(ea);
}
template <class CharT, class Traits>

View File

@@ -296,39 +296,39 @@ protected:
what_ = move_from(std::move(x));
}
template <class Writer>
error_id write_error_to(Writer & w) const
template <class Encoder>
error_id output_error_to(Encoder & e) const
{
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
static_assert(std::is_base_of<detail::encoder, Encoder>::value, "Encoder must derive from detail::encoder");
result_discriminant const what = what_;
BOOST_LEAF_ASSERT(what.kind() != result_discriminant::val);
error_id const err_id = what.get_error_id();
detail::serialize_(w, err_id);
detail::serialize_(e, err_id);
return err_id;
}
template <class Writer>
void write_capture_to(Writer & w, error_id err_id) const
template <class Encoder>
void output_capture_to(Encoder & e, error_id err_id) const
{
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
static_assert(std::is_base_of<detail::encoder, Encoder>::value, "Encoder must derive from detail::encoder");
if( what_.kind() == result_discriminant::err_id_capture_list )
{
#if BOOST_LEAF_CFG_CAPTURE
cap_.write_to(w, err_id);
cap_.output_to(e, err_id);
#else
BOOST_LEAF_ASSERT(0); // Possible ODR violation.
#endif
}
}
template <class Writer>
void print_error( Writer & w ) const
template <class DiagnosticsWriter>
void print_error( DiagnosticsWriter & dw ) 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(", ");
write_capture_to(w, err_id);
static_assert(std::is_base_of<detail::encoder, DiagnosticsWriter>::value, "DiagnosticsWriter must derive from detail::encoder");
error_id err_id = output_error_to(dw);
dw.set_prefix(", captured -> ");
dw.set_delimiter(", ");
output_capture_to(dw, err_id);
}
public:
@@ -576,14 +576,14 @@ public:
#endif
}
template <class Writer>
void write_to(Writer & w) const
template <class Encoder>
void output_to(Encoder & e) const
{
detail::writer_adaptor<Writer> wa(w);
detail::encoder_adaptor<Encoder> ea(e);
if( what_.kind() == result_discriminant::val )
detail::serialize_(wa, value());
detail::serialize_(ea, value());
else
write_capture_to(wa, write_error_to(wa));
output_capture_to(ea, output_error_to(ea));
}
template <class CharT, class Traits>
@@ -695,13 +695,13 @@ public:
BOOST_LEAF_ASSERT(has_value());
}
template <class Writer>
void write_to(Writer & w) const
template <class Encoder>
void output_to(Encoder & e) const
{
if( !*this )
{
detail::writer_adaptor<Writer> wa(w);
write_error_to(wa);
detail::encoder_adaptor<Encoder> ea(e);
output_error_to(ea);
}
}

View File

@@ -0,0 +1,53 @@
#ifndef BOOST_LEAF_SERIALIZATION_JSON_ENCODER_BOOST_HPP_INCLUDED
#define BOOST_LEAF_SERIALIZATION_JSON_ENCODER_BOOST_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 json {
class value;
struct value_from_tag;
} }
namespace boost { namespace leaf {
namespace serialization
{
template <class Value = boost::json::value, class ValueFromTag = boost::json::value_from_tag>
struct json_encoder_boost_
{
Value & v_;
template <class T>
friend auto output(json_encoder_boost_ & e, T const & x) -> decltype(std::declval<Value &>() = x, void())
{
e.v_ = x;
}
template <class T>
friend auto output(json_encoder_boost_ & e, T const & x) -> decltype(tag_invoke(std::declval<ValueFromTag>(), std::declval<Value &>(), x), void())
{
tag_invoke(ValueFromTag{}, e.v_, x);
}
template <class T>
friend void output_at(json_encoder_boost_ & e, T const & x, char const * name)
{
if( e.v_.is_null() )
e.v_.emplace_object();
json_encoder_boost_ nested{e.v_.as_object()[name]};
output(nested, x);
}
};
using json_encoder_boost = json_encoder_boost_<>;
}
} }
#endif

View File

@@ -0,0 +1,36 @@
#ifndef BOOST_LEAF_SERIALIZATION_JSON_ENCODER_NLOHMANN_HPP_INCLUDED
#define BOOST_LEAF_SERIALIZATION_JSON_ENCODER_NLOHMANN_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 json_encoder_nlohmann
{
Json & j_;
template <class T>
friend auto output(json_encoder_nlohmann & e, T const & x) -> decltype(to_json(std::declval<Json &>(), x), void())
{
to_json(e.j_, x);
}
template <class T>
friend void output_at(json_encoder_nlohmann & e, T const & x, char const * name)
{
json_encoder_nlohmann nested{e.j_[name]};
output(nested, x);
}
};
}
} }
#endif

View File

@@ -1,53 +0,0 @@
#ifndef BOOST_LEAF_SERIALIZATION_JSON_WRITER_BOOST_HPP_INCLUDED
#define BOOST_LEAF_SERIALIZATION_JSON_WRITER_BOOST_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 json {
class value;
struct value_from_tag;
} }
namespace boost { namespace leaf {
namespace serialization
{
template <class Value = boost::json::value, class ValueFromTag = boost::json::value_from_tag>
struct json_writer_boost_
{
Value & v_;
template <class T>
friend auto write(json_writer_boost_ & w, T const & x) -> decltype(std::declval<Value &>() = x, void())
{
w.v_ = x;
}
template <class T>
friend auto write(json_writer_boost_ & w, T const & x) -> decltype(tag_invoke(std::declval<ValueFromTag>(), std::declval<Value &>(), x), void())
{
tag_invoke(ValueFromTag{}, w.v_, x);
}
template <class T>
friend void write_nested(json_writer_boost_ & w, T const & x, char const * name)
{
if( w.v_.is_null() )
w.v_.emplace_object();
json_writer_boost_ nested{w.v_.as_object()[name]};
write(nested, x);
}
};
using json_writer_boost = json_writer_boost_<>;
}
} }
#endif

View File

@@ -1,36 +0,0 @@
#ifndef BOOST_LEAF_SERIALIZATION_JSON_WRITER_NLOHMANN_HPP_INCLUDED
#define BOOST_LEAF_SERIALIZATION_JSON_WRITER_NLOHMANN_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 json_writer_nlohmann
{
Json & j_;
template <class T>
friend auto write(json_writer_nlohmann & w, T const & x) -> decltype(to_json(std::declval<Json &>(), x), void())
{
to_json(w.j_, x);
}
template <class T>
friend void write_nested(json_writer_nlohmann & w, T const & x, char const * name)
{
json_writer_nlohmann nested{w.j_[name]};
write(nested, x);
}
};
}
} }
#endif

View File

@@ -141,7 +141,7 @@ if option_enable_unit_tests
'handle_basic_test',
'handle_some_other_result_test',
'handle_some_test',
'json_writer_nlohmann_test',
'json_encoder_nlohmann_test',
'match_member_test',
'match_test',
'match_value_test',
@@ -224,7 +224,7 @@ if option_enable_unit_tests
'_hpp_on_error_test',
'_hpp_pred_test',
'_hpp_result_test',
'_hpp_serialization_json_writer_nlohmann_test',
'_hpp_serialization_json_encoder_nlohmann_test',
'_hpp_to_variant_test',
]
foreach t : header_tests

View File

@@ -44,8 +44,8 @@ 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_nlohmann_test.cpp ;
compile _hpp_serialization_json_writer_boost_test.cpp ;
compile _hpp_serialization_json_encoder_nlohmann_test.cpp ;
compile _hpp_serialization_json_encoder_boost_test.cpp ;
compile _hpp_to_variant_test.cpp ;
run boost_exception_test.cpp ;
@@ -85,8 +85,8 @@ run handle_all_test.cpp ;
run handle_basic_test.cpp ;
run handle_some_other_result_test.cpp ;
run handle_some_test.cpp ;
run json_writer_nlohmann_test.cpp : : : <toolset>clang,<target-os>linux,<cxxstd>2b:<build>no <toolset>clang,<target-os>linux,<cxxstd>23:<build>no ;
run json_writer_boost_test.cpp /boost/json//boost_json : : : <exception-handling>off:<build>no <rtti>off:<build>no ;
run json_encoder_nlohmann_test.cpp : : : <toolset>clang,<target-os>linux,<cxxstd>2b:<build>no <toolset>clang,<target-os>linux,<cxxstd>23:<build>no ;
run json_encoder_boost_test.cpp /boost/json//boost_json : : : <exception-handling>off:<build>no <rtti>off:<build>no ;
run match_member_test.cpp ;
run match_test.cpp ;
run match_value_test.cpp ;
@@ -161,7 +161,8 @@ 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-serialization_json_encoder_boost.cpp ;
compile-fail _compile-fail-json_encoder_nlohmann.cpp ;
compile-fail _compile-fail-result_1.cpp ;
compile-fail _compile-fail-result_2.cpp ;
compile-fail _compile-fail-result_3.cpp ;

View File

@@ -0,0 +1,18 @@
// 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_encoder_boost.hpp>
#include <boost/json.hpp>
struct no_tag_invoke {};
struct e_no_tag_invoke
{
no_tag_invoke value;
};
boost::json::value v;
boost::leaf::serialization::json_encoder_boost e{v};
e_no_tag_invoke x;
auto y = (output(e, x), 0);

View File

@@ -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_nlohmann.hpp>
#include <boost/leaf/serialization/json_encoder_nlohmann.hpp>
#include "nlohmann/json.hpp"
struct no_to_json {};
@@ -13,6 +13,6 @@ struct e_no_to_json
};
nlohmann::json j;
boost::leaf::serialization::json_writer_nlohmann<nlohmann::json> w{j};
boost::leaf::serialization::json_encoder_nlohmann<nlohmann::json> w{j};
e_no_to_json e;
auto x = (write(w, e), 0);

View File

@@ -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/json_writer_boost.hpp>
#include <boost/leaf/serialization/json_writer_boost.hpp>
#include <boost/leaf/serialization/json_encoder_boost.hpp>
#include <boost/leaf/serialization/json_encoder_boost.hpp>
int main() { return 0; }

View File

@@ -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/json_writer_nlohmann.hpp>
#include <boost/leaf/serialization/json_writer_nlohmann.hpp>
#include <boost/leaf/serialization/json_encoder_nlohmann.hpp>
#include <boost/leaf/serialization/json_encoder_nlohmann.hpp>
int main() { return 0; }

View File

@@ -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_boost.hpp>
# include <boost/leaf/serialization/json_encoder_boost.hpp>
#endif
#include <boost/json.hpp>
@@ -27,17 +27,17 @@
namespace leaf = boost::leaf;
using output_writer = leaf::serialization::json_writer_boost;
using output_encoder = leaf::serialization::json_encoder_boost;
namespace boost { namespace leaf {
namespace serialization {
template <class Handle, class E>
void serialize(Handle & h, E const & e, char const * name)
template <class Handle, class T>
void serialize(Handle & h, T const & x, char const * name)
{
h.dispatch(
[&](json_writer_boost & w) { write_nested(w, e, name); }
[&](json_encoder_boost & e) { output_at(e, x, name); }
);
}
@@ -223,8 +223,8 @@ int main()
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
di.write_to(w);
output_encoder e{j};
di.output_to(e);
}
);
std::cout << __LINE__ << " diagnostic_info JSON output:\n" << boost::json::serialize(j) << std::endl;
@@ -241,8 +241,8 @@ int main()
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
dd.write_to(w);
output_encoder e{j};
dd.output_to(e);
}
);
std::cout << __LINE__ << " diagnostic_details JSON output:\n" << boost::json::serialize(j) << std::endl;
@@ -260,8 +260,8 @@ int main()
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
di.write_to(w);
output_encoder e{j};
di.output_to(e);
}
);
std::cout << __LINE__ << " leaf_throw diagnostic_info JSON output:\n" << boost::json::serialize(j) << std::endl;
@@ -279,8 +279,8 @@ int main()
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
dd.write_to(w);
output_encoder e{j};
dd.output_to(e);
}
);
std::cout << __LINE__ << " leaf_throw diagnostic_details JSON output:\n" << boost::json::serialize(j) << std::endl;
@@ -298,8 +298,8 @@ int main()
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
di.write_to(w);
output_encoder e{j};
di.output_to(e);
}
);
std::cout << __LINE__ << " throw_ diagnostic_info JSON output:\n" << boost::json::serialize(j) << std::endl;
@@ -316,8 +316,8 @@ int main()
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
dd.write_to(w);
output_encoder e{j};
dd.output_to(e);
}
);
std::cout << __LINE__ << " throw_ diagnostic_details JSON output:\n" << boost::json::serialize(j) << std::endl;
@@ -333,8 +333,8 @@ int main()
},
[&j](leaf::diagnostic_details const & dd, my_exception_ptr *)
{
output_writer w{j};
dd.write_to(w);
output_encoder e{j};
dd.output_to(e);
}
);
std::cout << __LINE__ << " std::exception_ptr JSON output:\n" << boost::json::serialize(j) << std::endl;
@@ -355,8 +355,8 @@ int main()
},
[&j](leaf::diagnostic_details const & dd, my_exception_ptr *)
{
output_writer w{j};
dd.write_to(w);
output_encoder e{j};
dd.output_to(e);
}
);
std::cout << __LINE__ << " non-std::exception_ptr JSON output:\n" << boost::json::serialize(j) << std::endl;
@@ -373,8 +373,8 @@ int main()
boost::json::value j;
leaf::result<int> r = 42;
BOOST_TEST(r);
output_writer w{j};
r.write_to(w);
output_encoder e{j};
r.output_to(e);
std::cout << __LINE__ << " result<int> success JSON output:\n" << boost::json::serialize(j) << std::endl;
BOOST_TEST_EQ(boost::json::value_to<int>(j.at("int")), 42);
}
@@ -383,8 +383,8 @@ int main()
boost::json::value j;
leaf::result<int> r = leaf::new_error();
BOOST_TEST(!r);
output_writer w{j};
r.write_to(w);
output_encoder e{j};
r.output_to(e);
std::cout << __LINE__ << " result<int> error JSON output:\n" << boost::json::serialize(j) << std::endl;
BOOST_TEST(boost::json::value_to<int>(j.at("boost::leaf::error_id")) > 0);
}
@@ -398,8 +398,8 @@ int main()
return leaf::new_error(my_error<1>{1, "error one"}, my_error<2>{2, "error two"});
} );
BOOST_TEST(!r);
output_writer w{j};
r.write_to(w);
output_encoder e{j};
r.output_to(e);
std::cout << __LINE__ << " result<int> captured error JSON output:\n" << boost::json::serialize(j) << std::endl;
BOOST_TEST(boost::json::value_to<int>(j.at("boost::leaf::error_id")) > 0);
auto const & e1j = j.at("my_error<1>");

View File

@@ -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_nlohmann.hpp>
# include <boost/leaf/serialization/json_encoder_nlohmann.hpp>
#endif
#include "nlohmann/json.hpp"
@@ -27,18 +27,18 @@
namespace leaf = boost::leaf;
using output_writer = leaf::serialization::json_writer_nlohmann<nlohmann::ordered_json>;
using output_encoder = leaf::serialization::json_encoder_nlohmann<nlohmann::ordered_json>;
namespace boost { namespace leaf {
namespace serialization {
template <class Handle, class E>
void serialize(Handle & h, E const & e, char const * name)
template <class Handle, class T>
void serialize(Handle & h, T const & x, char const * name)
{
h.dispatch(
[&](json_writer_nlohmann<nlohmann::json> & w) { write_nested(w, e, name); },
[&](json_writer_nlohmann<nlohmann::ordered_json> & w) { write_nested(w, e, name); }
[&](json_encoder_nlohmann<nlohmann::json> & e) { output_at(e, x, name); },
[&](json_encoder_nlohmann<nlohmann::ordered_json> & e) { output_at(e, x, name); }
);
}
@@ -224,8 +224,8 @@ int main()
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
di.write_to(w);
output_encoder e{j};
di.output_to(e);
}
);
std::cout << __LINE__ << " diagnostic_info JSON output:\n" << std::setw(2) << j << std::endl;
@@ -242,8 +242,8 @@ int main()
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
dd.write_to(w);
output_encoder e{j};
dd.output_to(e);
}
);
std::cout << __LINE__ << " diagnostic_details JSON output:\n" << std::setw(2) << j << std::endl;
@@ -261,8 +261,8 @@ int main()
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
di.write_to(w);
output_encoder e{j};
di.output_to(e);
}
);
std::cout << __LINE__ << " leaf_throw diagnostic_info JSON output:\n" << std::setw(2) << j << std::endl;
@@ -280,8 +280,8 @@ int main()
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
dd.write_to(w);
output_encoder e{j};
dd.output_to(e);
}
);
std::cout << __LINE__ << " leaf_throw diagnostic_details JSON output:\n" << std::setw(2) << j << std::endl;
@@ -299,8 +299,8 @@ int main()
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
di.write_to(w);
output_encoder e{j};
di.output_to(e);
}
);
std::cout << __LINE__ << " throw_ diagnostic_info JSON output:\n" << std::setw(2) << j << std::endl;
@@ -317,8 +317,8 @@ int main()
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
{
BOOST_TEST(e1 != nullptr);
output_writer w{j};
dd.write_to(w);
output_encoder e{j};
dd.output_to(e);
}
);
std::cout << __LINE__ << " throw_ diagnostic_details JSON output:\n" << std::setw(2) << j << std::endl;
@@ -334,8 +334,8 @@ int main()
},
[&j](leaf::diagnostic_details const & dd, my_exception_ptr *)
{
output_writer w{j};
dd.write_to(w);
output_encoder e{j};
dd.output_to(e);
}
);
std::cout << __LINE__ << " std::exception_ptr JSON output:\n" << std::setw(2) << j << std::endl;
@@ -356,8 +356,8 @@ int main()
},
[&j](leaf::diagnostic_details const & dd, my_exception_ptr *)
{
output_writer w{j};
dd.write_to(w);
output_encoder e{j};
dd.output_to(e);
}
);
std::cout << __LINE__ << " non-std::exception_ptr JSON output:\n" << std::setw(2) << j << std::endl;
@@ -374,8 +374,8 @@ int main()
nlohmann::ordered_json j;
leaf::result<int> r = 42;
BOOST_TEST(r);
output_writer w{j};
r.write_to(w);
output_encoder e{j};
r.output_to(e);
std::cout << __LINE__ << " result<int> success JSON output:\n" << std::setw(2) << j << std::endl;
BOOST_TEST_EQ(j["int"].get<int>(), 42);
}
@@ -384,8 +384,8 @@ int main()
nlohmann::ordered_json j;
leaf::result<int> r = leaf::new_error();
BOOST_TEST(!r);
output_writer w{j};
r.write_to(w);
output_encoder e{j};
r.output_to(e);
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);
}
@@ -399,8 +399,8 @@ int main()
return leaf::new_error(my_error<1>{1, "error one"}, my_error<2>{2, "error two"});
} );
BOOST_TEST(!r);
output_writer w{j};
r.write_to(w);
output_encoder e{j};
r.output_to(e);
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);
auto const & e1j = j["my_error<1>"];