--- /dev/null
+// Copyright (c) 2018-2020 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/detail/config.hpp>
+#include <boost/leaf/handle_errors.hpp>
+#include <boost/leaf/pred.hpp>
+#include <boost/leaf/result.hpp>
+#include "lightweight_test.hpp"
+
+namespace leaf = boost::leaf;
+
+template <int Tag> struct info { int value;};
+
+enum class error_code
+{
+ error1=1,
+ error2,
+ error3
+};
+
+struct error1_tag { };
+struct error2_tag { };
+struct error3_tag { };
+
+leaf::result<int> compute_answer( int what_to_do ) noexcept
+{
+ switch( what_to_do )
+ {
+ case 0:
+ return 42;
+ case 1:
+ return leaf::new_error(error_code::error1);
+ case 2:
+ return leaf::new_error(error_code::error2);
+ case 3:
+ return leaf::new_error(error_code::error3);
+ case 4:
+ return leaf::new_error(error1_tag{}, error_code::error1);
+ case 5:
+ return leaf::new_error(error2_tag{}, error_code::error2);
+ default:
+ BOOST_LEAF_ASSERT(what_to_do==6);
+ return leaf::new_error(error3_tag{}, error_code::error3);
+ }
+}
+
+leaf::result<int> handle_some_errors( int what_to_do )
+{
+ return leaf::try_handle_some(
+ [=]
+ {
+ return compute_answer(what_to_do);
+ },
+ []( error1_tag, leaf::match<error_code, error_code::error1> )
+ {
+ return -1;
+ },
+ []( leaf::match<error_code, error_code::error1> )
+ {
+ return -2;
+ } );
+}
+
+leaf::result<float> handle_some_errors_float( int what_to_do )
+{
+ return leaf::try_handle_some(
+ [=]() -> leaf::result<float>
+ {
+ return compute_answer(what_to_do);
+ },
+ []( error2_tag, leaf::match<error_code, error_code::error2> )
+ {
+ return -1.0f;
+ },
+ []( leaf::match<error_code, error_code::error2> )
+ {
+ return -2.0f;
+ } );
+}
+
+leaf::result<void> handle_some_errors_void( int what_to_do )
+{
+ return leaf::try_handle_some(
+ [=]() -> leaf::result<void>
+ {
+ BOOST_LEAF_AUTO(answer, compute_answer(what_to_do));
+ (void) answer;
+ return { };
+ },
+ []( leaf::match<error_code, error_code::error3> )
+ {
+ } );
+}
+
+int main()
+{
+ {
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ return leaf::try_handle_some(
+ []() -> leaf::result<int>
+ {
+ return leaf::try_handle_some(
+ []() -> leaf::result<int>
+ {
+ return leaf::new_error(40);
+ },
+ []( leaf::error_info const & ei, int & v )
+ {
+ ++v;
+ return ei.error();
+ });
+ },
+ []( leaf::error_info const & ei, int & v )
+ {
+ ++v;
+ return ei.error();
+ });
+ },
+ []( int v )
+ {
+ BOOST_TEST_EQ(v, 42);
+ return 1;
+ },
+ []
+ {
+ return 2;
+ });
+ BOOST_TEST_EQ(r, 1);
+ }
+ {
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ return leaf::try_handle_some(
+ []() -> leaf::result<int>
+ {
+ return leaf::try_handle_some(
+ []() -> leaf::result<int>
+ {
+ return leaf::new_error(40);
+ },
+ []( leaf::error_info const & ei, int * v )
+ {
+ ++*v;
+ return ei.error();
+ });
+ },
+ []( leaf::error_info const & ei, int * v )
+ {
+ ++*v;
+ return ei.error();
+ });
+ },
+ []( int v )
+ {
+ BOOST_TEST_EQ(v, 42);
+ return 1;
+ },
+ []
+ {
+ return 2;
+ });
+ BOOST_TEST_EQ(r, 1);
+ }
+
+ ///////////////////////////
+
+ BOOST_TEST_EQ(handle_some_errors(0).value(), 42);
+ BOOST_TEST_EQ(handle_some_errors(1).value(), -2);
+ BOOST_TEST_EQ(handle_some_errors(4).value(), -1);
+ {
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ BOOST_LEAF_AUTO(answer, handle_some_errors(3));
+ (void) answer;
+ return 0;
+ },
+ []( leaf::match<error_code, error_code::error3> )
+ {
+ return 1;
+ },
+ []
+ {
+ return 2;
+ } );
+ BOOST_TEST_EQ(r, 1);
+ }
+
+ ///////////////////////////
+
+ BOOST_TEST_EQ(handle_some_errors_float(0).value(), 42.0f);
+ BOOST_TEST_EQ(handle_some_errors_float(2).value(), -2.0f);
+ BOOST_TEST_EQ(handle_some_errors_float(5).value(), -1.0f);
+ {
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ BOOST_LEAF_AUTO(answer, handle_some_errors_float(1));
+ (void) answer;
+ return 0;
+ },
+ []( leaf::match<error_code, error_code::error1> )
+ {
+ return 1;
+ },
+ []
+ {
+ return 2;
+ } );
+ BOOST_TEST_EQ(r, 1);
+ }
+
+ ///////////////////////////
+
+ BOOST_TEST(handle_some_errors_void(0));
+ BOOST_TEST(handle_some_errors_void(3));
+ {
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ BOOST_LEAF_CHECK(handle_some_errors_void(2));
+ return 0;
+ },
+ []( leaf::match<error_code, error_code::error2> )
+ {
+ return 1;
+ },
+ []
+ {
+ return 2;
+ } );
+ BOOST_TEST_EQ(r, 1);
+ }
+
+ ///////////////////////////
+
+#ifndef BOOST_LEAF_NO_EXCEPTIONS
+ {
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ BOOST_LEAF_CHECK(handle_some_errors_void(2));
+ return 0;
+ },
+ []( std::exception const & )
+ {
+ return 1;
+ },
+ []
+ {
+ return 2;
+ } );
+ BOOST_TEST_EQ(r, 2);
+ }
+#endif
+
+ ///////////////////////////
+
+ {
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ return leaf::new_error( info<1>{42} );
+ },
+ []( info<1> const & i1 )
+ {
+ BOOST_TEST_EQ(i1.value, 42);
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ return leaf::new_error( info<1>{43} );
+ },
+ []()
+ {
+ return -1;
+ } );
+ BOOST_TEST_EQ(r, -1);
+ BOOST_TEST_EQ(i1.value, 42);
+ return 0;
+ },
+ []()
+ {
+ return -1;
+ } );
+ BOOST_TEST_EQ(r, 0);
+ }
+
+ ///////////////////////////
+
+ {
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ return leaf::new_error( info<1>{42} );
+ },
+ []( info<1> const & i1 )
+ {
+ BOOST_TEST_EQ(i1.value, 42);
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ return leaf::new_error( info<1>{43} );
+ },
+ []( info<1> const & i1 )
+ {
+ BOOST_TEST_EQ(i1.value, 43);
+ return -1;
+ },
+ []()
+ {
+ return -2;
+ } );
+ BOOST_TEST_EQ(r, -1);
+ BOOST_TEST_EQ(i1.value, 42);
+ return 0;
+ },
+ []()
+ {
+ return -1;
+ } );
+ BOOST_TEST_EQ(r, 0);
+ }
+
+ ///////////////////////////
+
+ {
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ return leaf::try_handle_some(
+ []() -> leaf::result<int>
+ {
+ return leaf::new_error( info<1>{1} );
+ },
+ []( leaf::error_info const & err, info<1> const & i1, info<2> const * i2 )
+ {
+ //We have space for info<2> in the context but i2 is null.
+ BOOST_TEST_EQ(i1.value, 1);
+ BOOST_TEST(!i2);
+ return err.error().load(info<2>{2});
+ } );
+ },
+ []( info<1> const & i1, info<2> const & i2 )
+ {
+ BOOST_TEST_EQ(i1.value, 1);
+ BOOST_TEST_EQ(i2.value, 2);
+ return 0;
+ },
+ []()
+ {
+ return -1;
+ } );
+ BOOST_TEST_EQ(r, 0);
+ }
+
+ ///////////////////////////
+
+ {
+ int r = leaf::try_handle_all(
+ []() -> leaf::result<int>
+ {
+ return leaf::try_handle_some(
+ []() -> leaf::result<int>
+ {
+ return leaf::new_error( info<1>{1}, info<2>{-2} );
+ },
+ []( leaf::error_info const & err, info<1> const & i1, info<2> const & i2 )
+ {
+ BOOST_TEST_EQ(i1.value, 1);
+ BOOST_TEST_EQ(i2.value, -2);
+ return err.error().load(info<2>{2});
+ } );
+ },
+ []( info<1> const & i1, info<2> const & i2 )
+ {
+ BOOST_TEST_EQ(i1.value, 1);
+ BOOST_TEST_EQ(i2.value, 2);
+ return 0;
+ },
+ []()
+ {
+ return -1;
+ } );
+ BOOST_TEST_EQ(r, 0);
+ }
+
+ ///////////////////////////
+
+ return boost::report_errors();
+}