diff --git a/doc/leaf.adoc b/doc/leaf.adoc index ef5e04d..c4726b9 100644 --- a/doc/leaf.adoc +++ b/doc/leaf.adoc @@ -1733,7 +1733,7 @@ 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 `output_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 `serialize_to` member function available on the following types: * <> * <> @@ -1811,7 +1811,7 @@ To support multiple output formats, pass multiple functions to `h.dispatch`: [source,c++] ---- h.dispatch( - [&](json_encoder_nlohmann & e) { output_at(e, x, name); }, + [&](nlohmann_json_encoder & e) { output_at(e, x, name); }, [&](xml_encoder & xe) { output_at(xe, x, name); } ); ---- @@ -1820,19 +1820,19 @@ h.dispatch( LEAF provides encoders for JSON serialization with two popular JSON libraries: -* <> for https://github.com/nlohmann/json[nlohmann/json] -* <> for https://www.boost.org/doc/libs/release/libs/json/[Boost.JSON] +* <> for https://github.com/nlohmann/json[nlohmann/json] +* <> for https://www.boost.org/doc/libs/release/libs/json/[Boost.JSON] -Below is an example using `json_encoder_nlohmann`. We just need to define the required `serialize` function template (see <>): +Below is an example using `nlohmann_json_encoder`. We just need to define the required `serialize` function template (see <>): [source,c++] ---- -#include +#include #include "nlohmann/json.hpp" namespace leaf = boost::leaf; -using json_encoder_nlohmann = leaf::serialization::json_encoder_nlohmann; +using nlohmann_json_encoder = leaf::serialization::nlohmann_json_encoder; namespace boost { namespace leaf { @@ -1841,7 +1841,7 @@ namespace serialization { template void serialize(Handle & h, T const & x, char const * name) { - h.dispatch([&](json_encoder_nlohmann & e) { + h.dispatch([&](nlohmann_json_encoder & e) { output_at(e, x, name); }); } @@ -1884,8 +1884,8 @@ leaf::try_handle_all( [](leaf::diagnostic_details const & dd) { nlohmann::json j; - json_encoder_nlohmann e(j); - dd.output_to(e); + nlohmann_json_encoder e(j); + dd.serialize_to(e); std::cout << j.dump(2) << std::endl; } ); @@ -1906,7 +1906,7 @@ leaf::try_handle_all( [.text-right] <> | <> | <> -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. +NOTE: In the example above, `e_api_response` uses an unqualified call to `to_json` for serialization. This is to demonstrate that `nlohmann_json_encoder` 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. ''' @@ -2074,7 +2074,7 @@ std::error_category const & resource_condition_category() <2> namespace std { template <> <5> - class is_error_condition_enum: std::true_type + struct is_error_condition_enum: std::true_type { }; } @@ -2522,11 +2522,9 @@ namespace boost { namespace leaf { template error_id load( Item && ... item ) noexcept; - - void unload(); template - void output_to( Encoder & e ) const; + void serialize_to( Encoder & e ) const; template friend std::ostream & operator<<( std::basic_ostream &, result const & ); @@ -2571,17 +2569,15 @@ namespace boost { namespace leaf { template error_id load( Item && ... item ) noexcept; - - void unload(); template - void output_to( Encoder & e ) const; + void serialize_to( Encoder & e ) const; template friend std::ostream & operator<<( std::basic_ostream &, result const &); }; - struct bad_result: std::exception { }; + class bad_result: std::exception { }; template struct is_result_type>: std::true_type @@ -2628,11 +2624,6 @@ namespace boost { namespace leaf { void unload( error_id ) noexcept; - void print( std::ostream & os ) const; - - template - friend std::ostream & operator<<( std::basic_ostream &, context const & ); - template R handle_error( R &, H && ... ) const; }; @@ -2867,28 +2858,28 @@ Reference: <> === Serialization -[[json_encoder_boost.hpp]] -==== `json_encoder_boost.hpp` +[[boost_json_encoder.hpp]] +==== `boost_json_encoder.hpp` ==== -.#include +.#include [source,c++] ---- namespace boost { namespace leaf { namespace serialization { - struct json_encoder_boost + struct boost_json_encoder { 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 - friend void output( json_encoder_boost &, T const & x ); + friend void output( boost_json_encoder &, T const & x ); template - friend void output_at( json_encoder_boost &, T const &, char const * name ); + friend void output_at( boost_json_encoder &, T const &, char const * name ); }; } @@ -2896,14 +2887,14 @@ namespace serialization ---- [.text-right] -Reference: <> +Reference: <> ==== -[[json_encoder_nlohmann.hpp]] -==== `json_encoder_nlohmann.hpp` +[[nlohmann_json_encoder.hpp]] +==== `nlohmann_json_encoder.hpp` ==== -.#include +.#include [source,c++] ---- namespace boost { namespace leaf { @@ -2911,16 +2902,16 @@ namespace boost { namespace leaf { namespace serialization { template - struct json_encoder_nlohmann + struct nlohmann_json_encoder { Json & j_; // Enabled if to_json is available for Json and T. template - friend void output( json_encoder_nlohmann &, T const & x ); + friend void output( nlohmann_json_encoder &, T const & x ); template - friend void output_at( json_encoder_nlohmann &, T const &, char const * name ); + friend void output_at( nlohmann_json_encoder &, T const &, char const * name ); }; } @@ -2928,7 +2919,7 @@ namespace serialization ---- [.text-right] -Reference: <> +Reference: <> ==== [[functions]] @@ -3662,6 +3653,42 @@ TIP: The contents of each Reference section are organized alphabetically. ''' +[[boost_json_encoder]] +=== `boost_json_encoder` + +.#include +[source,c++] +---- +namespace boost { namespace leaf { + +namespace serialization +{ + struct boost_json_encoder + { + 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 + friend void output( boost_json_encoder &, T const & x ); + + template + friend void output_at( boost_json_encoder &, T const &, char const * name ); + }; +} + +} } +---- + +The `boost_json_encoder` 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 + +See <>. + +''' + [[context]] === `context` @@ -3688,8 +3715,6 @@ namespace boost { namespace leaf { void unload( error_id ) noexcept; - void print( std::ostream & os ) const; - template R handle_error( error_id, H && ... ) const; @@ -3701,7 +3726,7 @@ namespace boost { namespace leaf { } } ---- [.text-right] -<> | <> | <> | <> | <> | <> | <> | <> +<> | <> | <> | <> | <> | <> | <> The `context` class template provides storage for each of the specified `E...` types. Typically, `context` objects are not used directly; they're created internally when the <>, <> or <> functions are invoked, instantiated with types that are automatically deduced from the types of the arguments of the passed handlers. @@ -3837,31 +3862,6 @@ Returns: :: `true` if the `*this` is active in any thread, `false` otherwise. ''' -[[context::print]] -==== `print` - -.#include -[source,c++] ----- -namespace boost { namespace leaf { - - template - void context::print( std::ostream & os ) const; - - template - friend std::ostream & context::operator<<( std::basic_ostream &, context const & ) - { - ctx.print(os); - return os; - } - -} } ----- - -Effects: :: Prints all error objects currently stored in `*this`, together with the unique error ID each individual error object is associated with. - -''' - [[context::unload]] ==== `unload` @@ -3936,7 +3936,7 @@ namespace boost { namespace leaf { public: template - void output_to( Encoder & e ) const; + void serialize_to( Encoder & e ) const; template friend std::ostream & operator<<( std::basic_ostream &, 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 <>). -The `output_to` member function is used with the serialization system; see <>. +The `serialize_to` member function is used with the serialization system; see <>. [NOTE] -- @@ -3980,7 +3980,7 @@ namespace boost { namespace leaf { public: template - void output_to( Encoder & e ) const; + void serialize_to( Encoder & e ) const; template friend std::ostream & operator<<( std::basic_ostream &, 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 `output_to` member function is used with the serialization system; see <>. +The `serialize_to` member function is used with the serialization system; see <>. [NOTE] -- @@ -4449,7 +4449,7 @@ namespace boost { namespace leaf { std::exception const * exception() const noexcept; template - void output_to( Encoder & e ) const; + void serialize_to( Encoder & e ) const; template friend std::ostream & operator<<( std::basic_ostream &, error_info const & ); @@ -4470,50 +4470,14 @@ 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 <> local to the <>, <> or <> scope that invoked the handler, but only if it is associated with the <> returned by `error()`. -The `output_to` member function is used with the serialization system; see <>. +The `serialize_to` member function is used with the serialization system; see <>. ''' -[[json_encoder_boost]] -=== `json_encoder_boost` +[[nlohmann_json_encoder]] +=== `nlohmann_json_encoder` -.#include -[source,c++] ----- -namespace boost { namespace leaf { - -namespace serialization -{ - 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 - friend void output( json_encoder_boost &, T const & x ); - - template - friend void output_at( json_encoder_boost &, T const &, char const * name ); - }; -} - -} } ----- - -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 - -See <>. - -''' - -[[json_encoder_nlohmann]] -=== `json_encoder_nlohmann` - -.#include +.#include [source,c++] ---- namespace boost { namespace leaf { @@ -4521,23 +4485,23 @@ namespace boost { namespace leaf { namespace serialization { template - struct json_encoder_nlohmann + struct nlohmann_json_encoder { Json & j_; // Enabled if to_json is available for Json and T. template - friend void output( json_encoder_nlohmann &, T const & x ); + friend void output( nlohmann_json_encoder &, T const & x ); template - friend void output_at( json_encoder_nlohmann &, T const &, char const * name ); + friend void output_at( nlohmann_json_encoder &, T const &, char const * name ); }; } } } ---- -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 <>. +The `nlohmann_json_encoder` 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 <>. ''' @@ -4609,11 +4573,9 @@ namespace boost { namespace leaf { template error_id load( Item && ... item ) noexcept; - - void unload(); template - void output_to( Encoder & e ) const; + void serialize_to( Encoder & e ) const; template friend std::ostream & operator<<( std::basic_ostream &, result const & ); @@ -4658,17 +4620,15 @@ namespace boost { namespace leaf { template error_id load( Item && ... item ) noexcept; - - void unload(); template - void output_to( Encoder & e ) const; + void serialize_to( Encoder & e ) const; template friend std::ostream & operator<<( std::basic_ostream &, result const &); }; - struct bad_result: std::exception { }; + class bad_result: std::exception { }; template struct is_result_type>: std::true_type @@ -4678,7 +4638,7 @@ namespace boost { namespace leaf { } } ---- [.text-right] -<> | <> | <> | <> | <> | <> | <> | <> | <> | <> | <> +<> | <> | <> | <> | <> | <> | <> | <> | <> | <> | <> The `result` type can be returned by functions which produce a value of type `T` but may fail doing so. @@ -4960,7 +4920,7 @@ namespace boost { namespace leaf { template T & result::value(); - struct bad_result: std::exception { }; + class bad_result: std::exception { }; } } ---- @@ -4982,8 +4942,8 @@ A member type of `result`, defined as a synonym for `T`. ''' -[[result::output_to]] -==== `output_to` +[[result::serialize_to]] +==== `serialize_to` .#include [source,c++] @@ -4992,16 +4952,16 @@ namespace boost { namespace leaf { template template - void result::output_to( Encoder & e ) const; + void result::serialize_to( Encoder & e ) const; } } ---- -The `output_to` member function is used with the serialization system; see <>. +The `serialize_to` member function is used with the serialization system; see <>. If the result is in <>, outputs the value. If it is in <>, outputs the <>. If the result holds <>, outputs them as well. -NOTE: Result objects carry error objects only when in <>. Otherwise, to output error objects, use `output_to` on <> in an error handling scope. +NOTE: Result objects carry error objects only when in <>. Otherwise, to output error objects, use `serialize_to` on <> in an error handling scope. ''' @@ -5270,7 +5230,7 @@ leaf::try_handle_some( namespace boost { namespace leaf { template - class match + struct match { <> matched; diff --git a/doc/whitepaper.md b/doc/whitepaper.md index d7e49cf..5ae182b 100644 --- a/doc/whitepaper.md +++ b/doc/whitepaper.md @@ -28,7 +28,7 @@ What makes the above function interesting is that syntactically, it returns an ` variant compute_value(); // (B) ``` -Are the two functions (A) and (B) semantically equivalent? It appears that any algorithm working with the result from (A) can be transformed to handle a call to (B) without any loss of functionality. This follows directly form the fact that either way there are three distinct outcomes, so the differences should be purely mechanical rather than in logic. +Are the two functions (A) and (B) semantically equivalent? It appears that any algorithm working with the result from (A) can be transformed to handle a call to (B) without any loss of functionality. This follows directly from the fact that either way there are three distinct outcomes, so the differences should be purely mechanical rather than in logic. In fact there is one subtle but critical difference: (A) encodes explicitly in the return object an additional bit of information -- "success-or-error" -- while in (B) that knowledge is implicit: we have to keep it in mind as we write the caller function, but it is not reflected in the program state. @@ -67,7 +67,7 @@ Consider a function which opens a file using [`open()`](http://man7.org/linux/ma * Was the file opened successfully but the attempt to read it failed? * Was there a parsing error after the file was successfully read? -Such simple booleans may be sufficient sometimes, but usually they are not. Reasonably, we need to respond differently depending on whether the call to `open()` resulted in `ENOENT` vs. `EACCESS` -- and if we got `EEXIST`, that would be a logic error. Therefore we need to know the relevant `errno` also. +Such simple booleans may be sufficient sometimes, but usually they are not. Reasonably, we need to respond differently depending on whether the call to `open()` resulted in `ENOENT` vs. `EACCES` -- and if we got `EEXIST`, that would be a logic error. Therefore we need to know the relevant `errno` also. Secondly, if the file failed to open, we need to know the `pathname` passed to `open()`, in case it happens to be incorrect. But what if it is correct and yet `open()` failed? Right, we probably need to know the `flags` argument passed to `open()` as well. @@ -257,7 +257,7 @@ Contemporary C++ exception handling is notorious for overhead[3](#reference * **Table-based** implementations (e.g. Itanium, x64) add to the cost of stack frames but only on the sad path. In fact, the performance of the happy path is often improved. However, if an exception is thrown and stack unwinding must commence, the table-based approach leads to a reduction in speed, compared to frame-based implementations. -Table-based exception handling has been designed based on the questionable assumption that it is critical to eliminate speed overhead in programs that don't `throw`. I'm saying questionable, because in practice such programs are compiled with `-fno-exceptions`. +Table-based exception handling has been designed based on the assumption that it is critical to eliminate speed overhead in programs that don't `throw`. This assumption merits scrutiny, because in practice such programs are compiled with `-fno-exceptions`. Ironically, the (older and less sophisticated) frame-based approach is preferable when we need to better control the cost of exception handling. The reason is that the overhead added to the happy path can be easily eliminated by inlining -- which is what we do anyway to deal with all other function-call overhead. This leaves only the cost of the sad path, which is also much more predictable, compared to the table-based approach. @@ -338,7 +338,7 @@ main: ret ``` -Bluntly, this is not acceptable, since it is trivial to determine at compile time that the `throw`/`catch` pair is noop. What if the generated code is improved _only_ in this simple use case, where the `throw` and the matching `catch` are in the same stack frame? Under this condition, there is no need to invoke the ABI machinery to allocate an exception object or navigate the unwind tables; the analysis of the control flow can and should happen at compile time. We'd end up with simply +This represents a missed optimization opportunity, since it is trivial to determine at compile time that the `throw`/`catch` pair is noop. What if the generated code is improved _only_ in this simple use case, where the `throw` and the matching `catch` are in the same stack frame? Under this condition, there is no need to invoke the ABI machinery to allocate an exception object or navigate the unwind tables; the analysis of the control flow can and should happen at compile time. We'd end up with simply ```x86asm main: @@ -360,9 +360,9 @@ Using LEAF, *error handling* functions match error objects similarly to the way Without exception handling, this is achieved using the following syntax: ```c++ -leaf::handle_all( +leaf::try_handle_all( - // The first function passed to handle_all is akin to a try-block. + // The first function passed to try_handle_all is akin to a try-block. []() -> leaf::result { // Operations which may fail, returning a T in case of success. @@ -399,7 +399,7 @@ With exception handling: ```c++ leaf::try_catch( - // The first function passed to handle_all is akin to a try-block. + // The first function passed to try_catch is akin to a try-block. []() -> T { // Operations which may fail, returning a T in case of success. @@ -431,9 +431,9 @@ leaf::try_catch( ); ``` -In LEAF, error objects are allocated using automatic duration, stored in a `std::tuple` in the scope of `leaf::handle_all` (or `leaf::try_catch`). The type arguments of the `std::tuple` template are automatically deduced from the types of the arguments of the error handling lambdas. If the try-block attempts to communicate error objects of any other type, these objects are discarded, since no error handler can make any use of them. +In LEAF, error objects are allocated using automatic duration, stored in a `std::tuple` in the scope of `leaf::try_handle_all` (or `leaf::try_catch`). The type arguments of the `std::tuple` template are automatically deduced from the types of the arguments of the error handling lambdas. If the try-block attempts to communicate error objects of any other type, these objects are discarded, since no error handler can make any use of them. -The `leaf::result` template can be used as a return value for functions that may fail to produce a `T`. It carries the [*failure flag*](#1-the-semantics-of-a-failure) and, in case it is set, an integer serial number of the failure, while actual error objects are immediately moved into the matching storage reserved in the scope of an error handling function (e.g. `handle_all`) found in the call stack. +The `leaf::result` template can be used as a return value for functions that may fail to produce a `T`. It carries the [*failure flag*](#1-the-semantics-of-a-failure) and, in case it is set, an integer serial number of the failure, while actual error objects are immediately moved into the matching storage reserved in the scope of an error handling function (e.g. `try_handle_all`) found in the call stack. ## 7. Exception-safety vs. failure-safety diff --git a/include/boost/leaf/context.hpp b/include/boost/leaf/context.hpp index 035ff5a..5ae3bba 100644 --- a/include/boost/leaf/context.hpp +++ b/include/boost/leaf/context.hpp @@ -195,7 +195,7 @@ namespace detail tuple_for_each::deactivate(tup); } - BOOST_LEAF_CONSTEXPR static void unload( Tup & tup, int err_id ) noexcept + BOOST_LEAF_CONSTEXPR static void unload( Tup & tup, int err_id ) noexcept(!BOOST_LEAF_CFG_CAPTURE) { static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); BOOST_LEAF_ASSERT(err_id != 0); @@ -204,11 +204,11 @@ namespace detail tuple_for_each::unload(tup, err_id); } - static void output_to(encoder & e, void const * tup, error_id id) + static void serialize_to(encoder & e, void const * tup, error_id id) { BOOST_LEAF_ASSERT(tup != nullptr); - tuple_for_each::output_to(e, tup, id); - std::get(*static_cast(tup)).output_to(e, id); + tuple_for_each::serialize_to(e, tup, id); + std::get(*static_cast(tup)).serialize_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 output_to(encoder &, void const *, error_id) { } + BOOST_LEAF_CONSTEXPR static void serialize_to(encoder &, void const *, error_id) { } }; template - void output_tuple_contents(encoder & e, void const * tup, error_id id) + void serialize_tuple_contents_to(encoder & e, void const * tup, error_id id) { - tuple_for_each::value, Tup>::output_to(e, tup, id); + tuple_for_each::value, Tup>::serialize_to(e, tup, id); } } // namespace detail @@ -357,7 +357,7 @@ public: tuple_for_each::value,Tup>::deactivate(tup_); } - BOOST_LEAF_CONSTEXPR void unload(error_id id) noexcept + BOOST_LEAF_CONSTEXPR void unload(error_id id) noexcept(!BOOST_LEAF_CFG_CAPTURE) { BOOST_LEAF_ASSERT(!is_active()); detail::tuple_for_each::value,Tup>::unload(tup_, id.value()); @@ -368,20 +368,6 @@ public: return is_active_; } - void output_to( detail::diagnostics_writer & e ) const - { - detail::output_tuple_contents(e, &tup_, error_id()); - } - - template - friend std::ostream & operator<<( std::basic_ostream & os, context const & ctx ) - { - detail::diagnostics_writer w(os); - w.set_prefix("Contents:"); - ctx.output_to(w); - return os; - } - template BOOST_LEAF_CONSTEXPR T const * get(error_id err) const noexcept { diff --git a/include/boost/leaf/detail/all.hpp b/include/boost/leaf/detail/all.hpp index ec58341..b5dfb54 100644 --- a/include/boost/leaf/detail/all.hpp +++ b/include/boost/leaf/detail/all.hpp @@ -11,6 +11,6 @@ #include #include #include -#include -#include +#include +#include #include diff --git a/include/boost/leaf/detail/capture_list.hpp b/include/boost/leaf/detail/capture_list.hpp index 04d71cf..3c42418 100644 --- a/include/boost/leaf/detail/capture_list.hpp +++ b/include/boost/leaf/detail/capture_list.hpp @@ -29,7 +29,7 @@ namespace detail friend class capture_list; virtual void unload( int err_id ) = 0; - virtual void output_to(encoder &, error_id const &) const = 0; + virtual void serialize_to(encoder &, error_id const &) const = 0; protected: @@ -90,14 +90,14 @@ namespace detail } ); } - void output_to(encoder & e, error_id const & id) const + void serialize_to(encoder & e, error_id const & id) const { if( first_ ) { for_each( [&e, &id]( node const & n ) { - n.output_to(e, id); + n.serialize_to(e, id); } ); } } diff --git a/include/boost/leaf/diagnostics.hpp b/include/boost/leaf/diagnostics.hpp index 69eee88..04758f5 100644 --- a/include/boost/leaf/diagnostics.hpp +++ b/include/boost/leaf/diagnostics.hpp @@ -13,7 +13,7 @@ namespace boost { namespace leaf { class diagnostic_info: public error_info { void const * tup_; - void (*output_tuple_contents_)(detail::encoder &, void const *, error_id); + void (*serialize_tuple_contents_to_)(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), - output_tuple_contents_(&detail::output_tuple_contents) + serialize_tuple_contents_to_(&detail::serialize_tuple_contents_to) { } template - void output_to_(Encoder & e) const + void serialize_to_(Encoder & e) const { static_assert(std::is_base_of::value, "Encoder must derive from detail::encoder"); - output_tuple_contents_(e, tup_, error()); + serialize_tuple_contents_to_(e, tup_, error()); } public: template - void output_to(Encoder & e) const + void serialize_to(Encoder & e) const { detail::encoder_adaptor ea(e); - error_info::output_to_(ea); - output_to_(ea); + error_info::serialize_to_(ea); + serialize_to_(ea); } template @@ -49,7 +49,7 @@ public: { detail::diagnostics_writer w(os, x.error(), x.source_location(), x.exception()); #if BOOST_LEAF_CFG_DIAGNOSTICS - x.output_to_(w); + x.serialize_to_(w); #else os << "\nboost::leaf::diagnostic_info N/A due to BOOST_LEAF_CFG_DIAGNOSTICS=0"; #endif @@ -99,22 +99,22 @@ protected: } template - void output_to_(Encoder & e) const + void serialize_to_(Encoder & e) const { static_assert(std::is_base_of::value, "Encoder must derive from detail::encoder"); if( da_ ) - da_->output_to(e, error()); + da_->serialize_to(e, error()); } public: template - void output_to(Encoder & e) const + void serialize_to(Encoder & e) const { detail::encoder_adaptor ea(e); - error_info::output_to_(ea); - diagnostic_info::output_to_(ea); - output_to_(ea); + error_info::serialize_to_(ea); + diagnostic_info::serialize_to_(ea); + serialize_to_(ea); } template @@ -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::output_to_(w); + x.diagnostic_info::serialize_to_(w); w.set_prefix("\nDiagnostic details:" BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER); - x.output_to_(w); + x.serialize_to_(w); #else os << "\nboost::leaf::diagnostic_details N/A due to BOOST_LEAF_CFG_DIAGNOSTICS=0"; #endif @@ -172,11 +172,11 @@ protected: public: template - void output_to(Encoder & e) const + void serialize_to(Encoder & e) const { detail::encoder_adaptor ea(e); - error_info::output_to_(ea); - diagnostic_info::output_to_(ea); + error_info::serialize_to_(ea); + diagnostic_info::serialize_to_(ea); } template @@ -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::output_to_(w); + x.diagnostic_info::serialize_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"; @@ -217,8 +217,6 @@ namespace detail #endif // #else (#if BOOST_LEAF_CFG_CAPTURE) -using verbose_diagnostic_info = diagnostic_details; - } } // namespace boost::leaf #endif // #ifndef BOOST_LEAF_DIAGNOSTICS_HPP_INCLUDED diff --git a/include/boost/leaf/error.hpp b/include/boost/leaf/error.hpp index 7f31e96..360bc9b 100644 --- a/include/boost/leaf/error.hpp +++ b/include/boost/leaf/error.hpp @@ -118,7 +118,6 @@ struct show_in_diagnostics: std::false_type namespace serialization { - template typename std::enable_if::value>::type serialize(Encoder &, T const &, char const *, Unused && ...) @@ -202,7 +201,7 @@ namespace detail void unload( int err_id ) noexcept(!BOOST_LEAF_CFG_CAPTURE); template - void output_to(Encoder & e, ErrorID id) const + void serialize_to(Encoder & e, ErrorID id) const { static_assert(std::is_base_of::value, "Encoder must derive from detail::encoder"); if( int k = this->key() ) @@ -271,9 +270,9 @@ namespace detail { impl::unload(err_id); } - void output_to(encoder & e, error_id const & id) const override + void serialize_to(encoder & e, error_id const & id) const override { - impl::output_to(e, id); + impl::serialize_to(e, id); } public: BOOST_LEAF_CONSTEXPR explicit capturing_slot_node( capture_list::node * * & last ): @@ -306,7 +305,7 @@ namespace detail { std::rethrow_exception(ex_); } - void output_to(encoder &, error_id const &) const override + void serialize_to(encoder &, error_id const &) const override { } std::exception_ptr const ex_; @@ -406,7 +405,7 @@ namespace detail } using capture_list::unload; - using capture_list::output_to; + using capture_list::serialize_to; }; // class dynamic_allocator template @@ -482,7 +481,7 @@ namespace detail } template - void output_to(encoder &, ErrorID) const + void serialize_to(encoder &, ErrorID) const { } }; // slot specialization for dynamic_allocator @@ -863,13 +862,13 @@ namespace detail } } -inline error_id new_error() +BOOST_LEAF_ATTRIBUTE_NODISCARD inline error_id new_error() { return detail::make_error_id(detail::start_new_error()); } template -inline error_id new_error( Item && ... item ) +BOOST_LEAF_ATTRIBUTE_NODISCARD inline error_id new_error( Item && ... item ) { return detail::make_error_id(detail::start_new_error()).load(std::forward(item)...); } diff --git a/include/boost/leaf/handle_errors.hpp b/include/boost/leaf/handle_errors.hpp index 3f7740a..b4dad74 100644 --- a/include/boost/leaf/handle_errors.hpp +++ b/include/boost/leaf/handle_errors.hpp @@ -46,7 +46,7 @@ protected: error_info( error_info const & ) noexcept = default; template - void output_to_(Encoder & e) const + void serialize_to_(Encoder & e) const { static_assert(std::is_base_of::value, "Encoder must derive from detail::encoder"); detail::serialize_(e, err_id_); @@ -88,10 +88,10 @@ public: } template - void output_to(Encoder & e) const + void serialize_to(Encoder & e) const { detail::encoder_adaptor ea(e); - output_to_(ea); + serialize_to_(ea); } template diff --git a/include/boost/leaf/result.hpp b/include/boost/leaf/result.hpp index e106202..6f8fe15 100644 --- a/include/boost/leaf/result.hpp +++ b/include/boost/leaf/result.hpp @@ -314,7 +314,7 @@ protected: if( what_.kind() == result_discriminant::err_id_capture_list ) { #if BOOST_LEAF_CFG_CAPTURE - cap_.output_to(e, err_id); + cap_.serialize_to(e, err_id); #else BOOST_LEAF_ASSERT(0); // Possible ODR violation. #endif @@ -410,13 +410,13 @@ public: #endif // #else (#if defined(BOOST_STRICT_CONFIG) || !defined(__clang__)) #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR - result( std::error_code const & ec ) noexcept: + result( std::error_code const & ec ) noexcept(!BOOST_LEAF_CFG_CAPTURE): what_(error_id(ec)) { } template ::value, int>::type> - result( Enum e ) noexcept: + result( Enum e ) noexcept(!BOOST_LEAF_CFG_CAPTURE): what_(error_id(e)) { } @@ -577,7 +577,7 @@ public: } template - void output_to(Encoder & e) const + void serialize_to(Encoder & e) const { detail::encoder_adaptor ea(e); if( what_.kind() == result_discriminant::val ) @@ -652,13 +652,13 @@ public: } #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR - result( std::error_code const & ec ) noexcept: + result( std::error_code const & ec ) noexcept(!BOOST_LEAF_CFG_CAPTURE): base(ec) { } template ::value, int>::type> - result( Enum e ) noexcept: + result( Enum e ) noexcept(!BOOST_LEAF_CFG_CAPTURE): base(e) { } @@ -696,7 +696,7 @@ public: } template - void output_to(Encoder & e) const + void serialize_to(Encoder & e) const { if( !*this ) { diff --git a/include/boost/leaf/serialization/json_encoder_boost.hpp b/include/boost/leaf/serialization/boost_json_encoder.hpp similarity index 68% rename from include/boost/leaf/serialization/json_encoder_boost.hpp rename to include/boost/leaf/serialization/boost_json_encoder.hpp index 8d39fb8..4eac1b8 100644 --- a/include/boost/leaf/serialization/json_encoder_boost.hpp +++ b/include/boost/leaf/serialization/boost_json_encoder.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_LEAF_SERIALIZATION_JSON_ENCODER_BOOST_HPP_INCLUDED -#define BOOST_LEAF_SERIALIZATION_JSON_ENCODER_BOOST_HPP_INCLUDED +#ifndef BOOST_LEAF_SERIALIZATION_BOOST_JSON_ENCODER_HPP_INCLUDED +#define BOOST_LEAF_SERIALIZATION_BOOST_JSON_ENCODER_HPP_INCLUDED // Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -19,33 +19,33 @@ namespace boost { namespace leaf { namespace serialization { template - struct json_encoder_boost_ + struct boost_json_encoder_ { Value & v_; template - friend auto output(json_encoder_boost_ & e, T const & x) -> decltype(std::declval() = x, void()) + friend auto output(boost_json_encoder_ & e, T const & x) -> decltype(std::declval() = x, void()) { e.v_ = x; } template - friend auto output(json_encoder_boost_ & e, T const & x) -> decltype(tag_invoke(std::declval(), std::declval(), x), void()) + friend auto output(boost_json_encoder_ & e, T const & x) -> decltype(tag_invoke(std::declval(), std::declval(), x), void()) { tag_invoke(ValueFromTag{}, e.v_, x); } template - friend void output_at(json_encoder_boost_ & e, T const & x, char const * name) + friend void output_at(boost_json_encoder_ & 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]}; + boost_json_encoder_ nested{e.v_.as_object()[name]}; output(nested, x); } }; - using json_encoder_boost = json_encoder_boost_<>; + using boost_json_encoder = boost_json_encoder_<>; } } } diff --git a/include/boost/leaf/serialization/json_encoder_nlohmann.hpp b/include/boost/leaf/serialization/nlohmann_json_encoder.hpp similarity index 64% rename from include/boost/leaf/serialization/json_encoder_nlohmann.hpp rename to include/boost/leaf/serialization/nlohmann_json_encoder.hpp index 161fd1c..60b616f 100644 --- a/include/boost/leaf/serialization/json_encoder_nlohmann.hpp +++ b/include/boost/leaf/serialization/nlohmann_json_encoder.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_LEAF_SERIALIZATION_JSON_ENCODER_NLOHMANN_HPP_INCLUDED -#define BOOST_LEAF_SERIALIZATION_JSON_ENCODER_NLOHMANN_HPP_INCLUDED +#ifndef BOOST_LEAF_SERIALIZATION_NLOHMANN_JSON_ENCODER_HPP_INCLUDED +#define BOOST_LEAF_SERIALIZATION_NLOHMANN_JSON_ENCODER_HPP_INCLUDED // Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -12,20 +12,20 @@ namespace boost { namespace leaf { namespace serialization { template - struct json_encoder_nlohmann + struct nlohmann_json_encoder { Json & j_; template - friend auto output(json_encoder_nlohmann & e, T const & x) -> decltype(to_json(std::declval(), x), void()) + friend auto output(nlohmann_json_encoder & e, T const & x) -> decltype(to_json(std::declval(), x), void()) { to_json(e.j_, x); } template - friend void output_at(json_encoder_nlohmann & e, T const & x, char const * name) + friend void output_at(nlohmann_json_encoder & e, T const & x, char const * name) { - json_encoder_nlohmann nested{e.j_[name]}; + nlohmann_json_encoder nested{e.j_[name]}; output(nested, x); } }; diff --git a/meson.build b/meson.build index 808cef6..7e28a17 100644 --- a/meson.build +++ b/meson.build @@ -141,11 +141,11 @@ if option_enable_unit_tests 'handle_basic_test', 'handle_some_other_result_test', 'handle_some_test', - 'json_encoder_nlohmann_test', 'match_member_test', 'match_test', 'match_value_test', 'multiple_errors_test', + 'nlohmann_json_encoder_test', 'on_error_accumulate_basic_test', 'on_error_accumulate_nested_error_exception_test', 'on_error_accumulate_nested_error_result_test', @@ -173,7 +173,6 @@ if option_enable_unit_tests 'on_error_preload_nested_success_exception_test', 'on_error_preload_nested_success_result_test', 'optional_test', - 'type_name_test', 'print_test', 'result_bad_result_test', 'result_implicit_conversion_test', @@ -191,6 +190,7 @@ if option_enable_unit_tests 'try_catch_system_error_test', 'try_catch_test', 'try_exception_and_result_test', + 'type_name_test', ] if option_boost_available and option_exceptions tests += [ @@ -224,7 +224,7 @@ if option_enable_unit_tests '_hpp_on_error_test', '_hpp_pred_test', '_hpp_result_test', - '_hpp_serialization_json_encoder_nlohmann_test', + '_hpp_serialization_nlohmann_json_encoder_test', '_hpp_to_variant_test', ] foreach t : header_tests diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5e351fe..108d4b8 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -44,14 +44,15 @@ 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_encoder_nlohmann_test.cpp ; -compile _hpp_serialization_json_encoder_boost_test.cpp ; +compile _hpp_serialization_boost_json_encoder_test.cpp ; +compile _hpp_serialization_nlohmann_json_encoder_test.cpp ; compile _hpp_to_variant_test.cpp ; -run boost_exception_test.cpp ; run BOOST_LEAF_ASSIGN_test.cpp ; run BOOST_LEAF_AUTO_test.cpp ; run BOOST_LEAF_CHECK_test.cpp ; +run boost_exception_test.cpp ; +run boost_json_encoder_test.cpp /boost/json//boost_json : : : off:no off:no ; run capture_exception_async_test.cpp ; run capture_exception_result_async_test.cpp ; run capture_exception_result_unload_test.cpp ; @@ -85,12 +86,11 @@ run handle_all_test.cpp ; run handle_basic_test.cpp ; run handle_some_other_result_test.cpp ; run handle_some_test.cpp ; -run json_encoder_nlohmann_test.cpp : : : clang,linux,2b:no clang,linux,23:no ; -run json_encoder_boost_test.cpp /boost/json//boost_json : : : off:no off:no ; run match_member_test.cpp ; run match_test.cpp ; run match_value_test.cpp ; run multiple_errors_test.cpp ; +run nlohmann_json_encoder_test.cpp : : : clang,linux,2b:no clang,linux,23:no ; run on_error_accumulate_basic_test.cpp ; run on_error_accumulate_nested_error_exception_test.cpp ; run on_error_accumulate_nested_error_result_test.cpp ; @@ -118,7 +118,6 @@ run on_error_preload_nested_new_error_result_test.cpp ; run on_error_preload_nested_success_exception_test.cpp ; run on_error_preload_nested_success_result_test.cpp ; run optional_test.cpp ; -run type_name_test.cpp ; run print_test.cpp ; run result_bad_result_test.cpp ; run result_implicit_conversion_test.cpp ; @@ -136,6 +135,7 @@ run try_catch_error_id_test.cpp ; run try_catch_system_error_test.cpp ; run try_catch_test.cpp ; run try_exception_and_result_test.cpp ; +run type_name_test.cpp ; lib so_dll_lib1 : so_dll_lib1.cpp : shared hidden windows:BOOST_LEAF_CFG_WIN32=2 : : windows:BOOST_LEAF_CFG_WIN32=2 ; lib so_dll_lib2 : so_dll_lib2.cpp : shared hidden windows:BOOST_LEAF_CFG_WIN32=2 : : windows:BOOST_LEAF_CFG_WIN32=2 ; @@ -161,12 +161,12 @@ 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-serialization_json_encoder_boost.cpp ; -compile-fail _compile-fail-serialization_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 ; compile-fail _compile-fail-result_4.cpp ; +compile-fail _compile-fail-serialization_boost_json_encoder.cpp ; +compile-fail _compile-fail-serialization_nlohmann_json_encoder.cpp ; exe try_capture_all_exceptions : ../example/try_capture_all_exceptions.cpp : single:no off:no leaf_debug_capture0:no leaf_release_capture0:no ; exe try_capture_all_result : ../example/try_capture_all_result.cpp : single:no leaf_debug_capture0:no leaf_release_capture0:no leaf_debug_embedded:no leaf_release_embedded:no ; diff --git a/test/_compile-fail-serialization_json_encoder_boost.cpp b/test/_compile-fail-serialization_boost_json_encoder.cpp similarity index 77% rename from test/_compile-fail-serialization_json_encoder_boost.cpp rename to test/_compile-fail-serialization_boost_json_encoder.cpp index a807543..00a8b95 100644 --- a/test/_compile-fail-serialization_json_encoder_boost.cpp +++ b/test/_compile-fail-serialization_boost_json_encoder.cpp @@ -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 +#include #include struct no_tag_invoke {}; @@ -13,6 +13,6 @@ struct e_no_tag_invoke }; boost::json::value v; -boost::leaf::serialization::json_encoder_boost e{v}; +boost::leaf::serialization::boost_json_encoder e{v}; e_no_tag_invoke x; auto y = (output(e, x), 0); diff --git a/test/_compile-fail-serialization_json_encoder_nlohmann.cpp b/test/_compile-fail-serialization_nlohmann_json_encoder.cpp similarity index 70% rename from test/_compile-fail-serialization_json_encoder_nlohmann.cpp rename to test/_compile-fail-serialization_nlohmann_json_encoder.cpp index 929a249..767a851 100644 --- a/test/_compile-fail-serialization_json_encoder_nlohmann.cpp +++ b/test/_compile-fail-serialization_nlohmann_json_encoder.cpp @@ -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 +#include #include "nlohmann/json.hpp" struct no_to_json {}; @@ -13,6 +13,6 @@ struct e_no_to_json }; nlohmann::json j; -boost::leaf::serialization::json_encoder_nlohmann w{j}; +boost::leaf::serialization::nlohmann_json_encoder w{j}; e_no_to_json e; -auto x = (write(w, e), 0); +auto x = (output(w, e), 0); diff --git a/test/_hpp_serialization_json_encoder_boost_test.cpp b/test/_hpp_serialization_boost_json_encoder_test.cpp similarity index 67% rename from test/_hpp_serialization_json_encoder_boost_test.cpp rename to test/_hpp_serialization_boost_json_encoder_test.cpp index 82336ed..b36add4 100644 --- a/test/_hpp_serialization_json_encoder_boost_test.cpp +++ b/test/_hpp_serialization_boost_json_encoder_test.cpp @@ -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 -#include +#include +#include int main() { return 0; } diff --git a/test/_hpp_serialization_json_encoder_nlohmann_test.cpp b/test/_hpp_serialization_nlohmann_json_encoder_test.cpp similarity index 66% rename from test/_hpp_serialization_json_encoder_nlohmann_test.cpp rename to test/_hpp_serialization_nlohmann_json_encoder_test.cpp index 340ad25..3308959 100644 --- a/test/_hpp_serialization_json_encoder_nlohmann_test.cpp +++ b/test/_hpp_serialization_nlohmann_json_encoder_test.cpp @@ -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 -#include +#include +#include int main() { return 0; } diff --git a/test/json_encoder_boost_test.cpp b/test/boost_json_encoder_test.cpp similarity index 95% rename from test/json_encoder_boost_test.cpp rename to test/boost_json_encoder_test.cpp index 357c4ed..b570910 100644 --- a/test/json_encoder_boost_test.cpp +++ b/test/boost_json_encoder_test.cpp @@ -10,7 +10,7 @@ # include # include # include -# include +# include #endif #include @@ -27,7 +27,7 @@ namespace leaf = boost::leaf; -using output_encoder = leaf::serialization::json_encoder_boost; +using output_encoder = leaf::serialization::boost_json_encoder; namespace boost { namespace leaf { @@ -37,7 +37,7 @@ template void serialize(Handle & h, T const & x, char const * name) { h.dispatch( - [&](json_encoder_boost & e) { output_at(e, x, name); } + [&](boost_json_encoder & e) { output_at(e, x, name); } ); } @@ -194,7 +194,7 @@ void check_diagnostic_details(boost::json::value const & j, bool has_source_loca else { BOOST_TEST(j.as_object().find("int") == j.as_object().end()); - BOOST_TEST(j.as_object().find("my_error<2>") == j.as_object().end()); + BOOST_TEST(j.as_object().find("my_error2") == j.as_object().end()); BOOST_TEST(j.as_object().find("boost::leaf::e_errno") == j.as_object().end()); BOOST_TEST(j.as_object().find("boost::leaf::e_api_function") == j.as_object().end()); BOOST_TEST(j.as_object().find("std::error_code") == j.as_object().end()); @@ -224,7 +224,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - di.output_to(e); + di.serialize_to(e); } ); std::cout << __LINE__ << " diagnostic_info JSON output:\n" << boost::json::serialize(j) << std::endl; @@ -242,7 +242,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - dd.output_to(e); + dd.serialize_to(e); } ); std::cout << __LINE__ << " diagnostic_details JSON output:\n" << boost::json::serialize(j) << std::endl; @@ -261,7 +261,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - di.output_to(e); + di.serialize_to(e); } ); std::cout << __LINE__ << " leaf_throw diagnostic_info JSON output:\n" << boost::json::serialize(j) << std::endl; @@ -280,7 +280,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - dd.output_to(e); + dd.serialize_to(e); } ); std::cout << __LINE__ << " leaf_throw diagnostic_details JSON output:\n" << boost::json::serialize(j) << std::endl; @@ -299,7 +299,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - di.output_to(e); + di.serialize_to(e); } ); std::cout << __LINE__ << " throw_ diagnostic_info JSON output:\n" << boost::json::serialize(j) << std::endl; @@ -317,7 +317,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - dd.output_to(e); + dd.serialize_to(e); } ); std::cout << __LINE__ << " throw_ diagnostic_details JSON output:\n" << boost::json::serialize(j) << std::endl; @@ -334,7 +334,7 @@ int main() [&j](leaf::diagnostic_details const & dd, my_exception_ptr *) { output_encoder e{j}; - dd.output_to(e); + dd.serialize_to(e); } ); std::cout << __LINE__ << " std::exception_ptr JSON output:\n" << boost::json::serialize(j) << std::endl; @@ -356,7 +356,7 @@ int main() [&j](leaf::diagnostic_details const & dd, my_exception_ptr *) { output_encoder e{j}; - dd.output_to(e); + dd.serialize_to(e); } ); std::cout << __LINE__ << " non-std::exception_ptr JSON output:\n" << boost::json::serialize(j) << std::endl; @@ -374,7 +374,7 @@ int main() leaf::result r = 42; BOOST_TEST(r); output_encoder e{j}; - r.output_to(e); + r.serialize_to(e); std::cout << __LINE__ << " result success JSON output:\n" << boost::json::serialize(j) << std::endl; BOOST_TEST_EQ(boost::json::value_to(j.at("int")), 42); } @@ -384,7 +384,7 @@ int main() leaf::result r = leaf::new_error(); BOOST_TEST(!r); output_encoder e{j}; - r.output_to(e); + r.serialize_to(e); std::cout << __LINE__ << " result error JSON output:\n" << boost::json::serialize(j) << std::endl; BOOST_TEST(boost::json::value_to(j.at("boost::leaf::error_id")) > 0); } @@ -399,7 +399,7 @@ int main() } ); BOOST_TEST(!r); output_encoder e{j}; - r.output_to(e); + r.serialize_to(e); std::cout << __LINE__ << " result captured error JSON output:\n" << boost::json::serialize(j) << std::endl; BOOST_TEST(boost::json::value_to(j.at("boost::leaf::error_id")) > 0); auto const & e1j = j.at("my_error<1>"); diff --git a/test/ctx_remote_handle_all_test.cpp b/test/ctx_remote_handle_all_test.cpp index 05f6f61..4b8926c 100644 --- a/test/ctx_remote_handle_all_test.cpp +++ b/test/ctx_remote_handle_all_test.cpp @@ -48,8 +48,6 @@ int main() leaf::result r1 = f(ctx); BOOST_TEST(!r1); - std::cout << "ctx contents:" << std::endl << ctx; - int r2 = ctx.handle_error( r1.error(), std::move(handlers)); diff --git a/test/json_encoder_nlohmann_test.cpp b/test/nlohmann_json_encoder_test.cpp similarity index 91% rename from test/json_encoder_nlohmann_test.cpp rename to test/nlohmann_json_encoder_test.cpp index fa04210..acbe510 100644 --- a/test/json_encoder_nlohmann_test.cpp +++ b/test/nlohmann_json_encoder_test.cpp @@ -10,13 +10,14 @@ # include # include # include -# include +# include #endif #include "nlohmann/json.hpp" #include #include #include +#include #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR # include #endif @@ -27,7 +28,7 @@ namespace leaf = boost::leaf; -using output_encoder = leaf::serialization::json_encoder_nlohmann; +using output_encoder = leaf::serialization::nlohmann_json_encoder; namespace boost { namespace leaf { @@ -37,8 +38,8 @@ template void serialize(Handle & h, T const & x, char const * name) { h.dispatch( - [&](json_encoder_nlohmann & e) { output_at(e, x, name); }, - [&](json_encoder_nlohmann & e) { output_at(e, x, name); } + [&](nlohmann_json_encoder & e) { output_at(e, x, name); }, + [&](nlohmann_json_encoder & e) { output_at(e, x, name); } ); } @@ -77,6 +78,11 @@ struct my_error } }; +struct my_error_with_vector +{ + std::vector value; +}; + leaf::result fail() { return BOOST_LEAF_NEW_ERROR( @@ -88,6 +94,7 @@ leaf::result fail() 42, my_error<1>{1, "error one"}, my_error<2>{2, "error two"}, + my_error_with_vector{{10, 20, 30}}, leaf::e_errno{ENOENT}, leaf::e_api_function{"my_api_function"} ); } @@ -104,6 +111,7 @@ void leaf_throw() 42, my_error<1>{1, "error one"}, my_error<2>{2, "error two"}, + my_error_with_vector{{10, 20, 30}}, leaf::e_errno{ENOENT}, leaf::e_api_function{"my_api_function"} ); } @@ -119,6 +127,7 @@ void throw_() 42, my_error<1>{1, "error one"}, my_error<2>{2, "error two"}, + my_error_with_vector{{10, 20, 30}}, leaf::e_errno{ENOENT}, leaf::e_api_function{"my_api_function"} ); throw my_exception{}; @@ -168,6 +177,13 @@ void check_diagnostic_details(nlohmann::ordered_json const & j, bool has_source_ BOOST_TEST_EQ(e2j["code"].get(), 2); BOOST_TEST_EQ(e2j["message"].get(), "error two"); + auto const & vj = j["my_error_with_vector"]; + BOOST_TEST(vj.is_array()); + BOOST_TEST_EQ(vj.size(), 3); + BOOST_TEST_EQ(vj[0].get(), 10); + BOOST_TEST_EQ(vj[1].get(), 20); + BOOST_TEST_EQ(vj[2].get(), 30); + auto const & ej = j["boost::leaf::e_errno"]; BOOST_TEST_EQ(ej["errno"].get(), ENOENT); BOOST_TEST(!ej["strerror"].get().empty()); @@ -225,7 +241,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - di.output_to(e); + di.serialize_to(e); } ); std::cout << __LINE__ << " diagnostic_info JSON output:\n" << std::setw(2) << j << std::endl; @@ -243,7 +259,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - dd.output_to(e); + dd.serialize_to(e); } ); std::cout << __LINE__ << " diagnostic_details JSON output:\n" << std::setw(2) << j << std::endl; @@ -262,7 +278,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - di.output_to(e); + di.serialize_to(e); } ); std::cout << __LINE__ << " leaf_throw diagnostic_info JSON output:\n" << std::setw(2) << j << std::endl; @@ -281,7 +297,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - dd.output_to(e); + dd.serialize_to(e); } ); std::cout << __LINE__ << " leaf_throw diagnostic_details JSON output:\n" << std::setw(2) << j << std::endl; @@ -300,7 +316,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - di.output_to(e); + di.serialize_to(e); } ); std::cout << __LINE__ << " throw_ diagnostic_info JSON output:\n" << std::setw(2) << j << std::endl; @@ -318,7 +334,7 @@ int main() { BOOST_TEST(e1 != nullptr); output_encoder e{j}; - dd.output_to(e); + dd.serialize_to(e); } ); std::cout << __LINE__ << " throw_ diagnostic_details JSON output:\n" << std::setw(2) << j << std::endl; @@ -335,7 +351,7 @@ int main() [&j](leaf::diagnostic_details const & dd, my_exception_ptr *) { output_encoder e{j}; - dd.output_to(e); + dd.serialize_to(e); } ); std::cout << __LINE__ << " std::exception_ptr JSON output:\n" << std::setw(2) << j << std::endl; @@ -357,7 +373,7 @@ int main() [&j](leaf::diagnostic_details const & dd, my_exception_ptr *) { output_encoder e{j}; - dd.output_to(e); + dd.serialize_to(e); } ); std::cout << __LINE__ << " non-std::exception_ptr JSON output:\n" << std::setw(2) << j << std::endl; @@ -375,7 +391,7 @@ int main() leaf::result r = 42; BOOST_TEST(r); output_encoder e{j}; - r.output_to(e); + r.serialize_to(e); std::cout << __LINE__ << " result success JSON output:\n" << std::setw(2) << j << std::endl; BOOST_TEST_EQ(j["int"].get(), 42); } @@ -385,7 +401,7 @@ int main() leaf::result r = leaf::new_error(); BOOST_TEST(!r); output_encoder e{j}; - r.output_to(e); + r.serialize_to(e); std::cout << __LINE__ << " result error JSON output:\n" << std::setw(2) << j << std::endl; BOOST_TEST(j["boost::leaf::error_id"].get() > 0); } @@ -400,7 +416,7 @@ int main() } ); BOOST_TEST(!r); output_encoder e{j}; - r.output_to(e); + r.serialize_to(e); std::cout << __LINE__ << " result captured error JSON output:\n" << std::setw(2) << j << std::endl; BOOST_TEST(j["boost::leaf::error_id"].get() > 0); auto const & e1j = j["my_error<1>"];