1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
// Copyright (c) 2024 Dmitry Arkhipov (grisumbras@yandex.ru)
3  
// Copyright (c) 2024 Dmitry Arkhipov (grisumbras@yandex.ru)
4  
//
4  
//
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
//
7  
//
8  
// Official repository: https://github.com/boostorg/json
8  
// Official repository: https://github.com/boostorg/json
9  
//
9  
//
10  

10  

11  
#ifndef BOOST_JSON_RESULT_FOR_HPP
11  
#ifndef BOOST_JSON_RESULT_FOR_HPP
12  
#define BOOST_JSON_RESULT_FOR_HPP
12  
#define BOOST_JSON_RESULT_FOR_HPP
13  

13  

14  
#include <boost/json/detail/config.hpp>
14  
#include <boost/json/detail/config.hpp>
15  
#include <boost/json/fwd.hpp>
15  
#include <boost/json/fwd.hpp>
16  
#include <boost/assert/source_location.hpp>
16  
#include <boost/assert/source_location.hpp>
17  
#include <boost/system/result.hpp>
17  
#include <boost/system/result.hpp>
18  

18  

19  
namespace boost {
19  
namespace boost {
20  
namespace json {
20  
namespace json {
21  

21  

22  
/**
22  
/**
23  
   Helper trait that returns @ref boost::system::result.
23  
   Helper trait that returns @ref boost::system::result.
24  

24  

25  
   The primary template is an incomplete type. The library provides a partial
25  
   The primary template is an incomplete type. The library provides a partial
26  
   specialisation `result_for<T1, value>`, that has nested type alias `type`
26  
   specialisation `result_for<T1, value>`, that has nested type alias `type`
27  
   that aliases the type `result<T1>`.
27  
   that aliases the type `result<T1>`.
28  

28  

29  
   The purpose of this trait is to let users provide non-throwing conversions
29  
   The purpose of this trait is to let users provide non-throwing conversions
30  
   for their types without creating a physical dependency on Boost.Json. For
30  
   for their types without creating a physical dependency on Boost.Json. For
31  
   example:
31  
   example:
32  

32  

33  
   @code
33  
   @code
34  
   namespace boost {
34  
   namespace boost {
35  
   namespace json {
35  
   namespace json {
36  

36  

37  
   template<class T>
37  
   template<class T>
38  
   struct value_to_tag;
38  
   struct value_to_tag;
39  

39  

40  
   template<class T1, class T2>
40  
   template<class T1, class T2>
41  
   struct result_for;
41  
   struct result_for;
42  
   }
42  
   }
43  
   }
43  
   }
44  

44  

45  
   namespace mine
45  
   namespace mine
46  
   {
46  
   {
47  
       class my_class;
47  
       class my_class;
48  
       ...
48  
       ...
49  
       template<class JsonValue>
49  
       template<class JsonValue>
50  
       boost::json::result_for<my_class, JsonValue>
50  
       boost::json::result_for<my_class, JsonValue>
51  
       tag_invoke(boost::json::try_value_to_tag<my_class>, const JsonValue& jv)
51  
       tag_invoke(boost::json::try_value_to_tag<my_class>, const JsonValue& jv)
52  
       { ... }
52  
       { ... }
53  
   }
53  
   }
54  
   @endcode
54  
   @endcode
55  

55  

56  
   @see @ref try_value_to, @ref try_value_to_tag
56  
   @see @ref try_value_to, @ref try_value_to_tag
57  
*/
57  
*/
58  
template <class T1, class T2>
58  
template <class T1, class T2>
59  
struct result_for;
59  
struct result_for;
60  

60  

61  
/** Create @ref boost::system::result containing a portable error code.
61  
/** Create @ref boost::system::result containing a portable error code.
62  

62  

63  
    This function constructs a `boost::system::result<T>` that stores
63  
    This function constructs a `boost::system::result<T>` that stores
64  
    `error_code` with `value()` equal to `e` and `category()` equal to
64  
    `error_code` with `value()` equal to `e` and `category()` equal to
65  
    @ref boost::system::generic_category().
65  
    @ref boost::system::generic_category().
66  

66  

67  
    The main use for this function is in implementation of functions returning
67  
    The main use for this function is in implementation of functions returning
68  
    `boost::system::result`, without including `boost/json/system_error.hpp` or
68  
    `boost::system::result`, without including `boost/json/system_error.hpp` or
69  
    even `<system_error>`. In particular, it may be useful for customizations
69  
    even `<system_error>`. In particular, it may be useful for customizations
70  
    of @ref try_value_to without creating a physical dependency on Boost.JSON.
70  
    of @ref try_value_to without creating a physical dependency on Boost.JSON.
71  
    For example:
71  
    For example:
72  

72  

73  
    @code
73  
    @code
74  
    #include <cerrno>
74  
    #include <cerrno>
75  
    #include <boost/assert/source_location.hpp>
75  
    #include <boost/assert/source_location.hpp>
76  

76  

77  
    namespace boost {
77  
    namespace boost {
78  
    namespace json {
78  
    namespace json {
79  

79  

80  
    class value;
80  
    class value;
81  

81  

82  
    template<class T>
82  
    template<class T>
83  
    struct try_value_to_tag;
83  
    struct try_value_to_tag;
84  

84  

85  
    template<class T1, class T2>
85  
    template<class T1, class T2>
86  
    struct result_for;
86  
    struct result_for;
87  

87  

88  
    template <class T>
88  
    template <class T>
89  
    typename result_for<T, value>::type
89  
    typename result_for<T, value>::type
90  
    result_from_errno(int e, boost::source_location const* loc) noexcept
90  
    result_from_errno(int e, boost::source_location const* loc) noexcept
91  

91  

92  
    }
92  
    }
93  
    }
93  
    }
94  

94  

95  
    namespace mine {
95  
    namespace mine {
96  

96  

97  
    class my_class;
97  
    class my_class;
98  
    ...
98  
    ...
99  
    template<class JsonValue>
99  
    template<class JsonValue>
100  
    boost::json::result_for<my_class, JsonValue>
100  
    boost::json::result_for<my_class, JsonValue>
101  
    tag_invoke(boost::json::try_value_to_tag<my_class>, const JsonValue& jv)
101  
    tag_invoke(boost::json::try_value_to_tag<my_class>, const JsonValue& jv)
102  
    {
102  
    {
103  
        BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
103  
        BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
104  
        if( !jv.is_null() )
104  
        if( !jv.is_null() )
105  
            return boost::json::result_from_errno<my_class>(EINVAL, &loc);
105  
            return boost::json::result_from_errno<my_class>(EINVAL, &loc);
106  
        return my_class();
106  
        return my_class();
107  
    }
107  
    }
108  

108  

109  
    }
109  
    }
110  
    @endcode
110  
    @endcode
111  

111  

112  
    @par Exception Safety
112  
    @par Exception Safety
113  
    Does not throw exceptions.
113  
    Does not throw exceptions.
114  

114  

115  
    @tparam T The value type of returned `result`.
115  
    @tparam T The value type of returned `result`.
116  
    @param e The error value.
116  
    @param e The error value.
117  
    @param loc The error location.
117  
    @param loc The error location.
118  

118  

119  
    @returns A @ref boost::system::result containing an error.
119  
    @returns A @ref boost::system::result containing an error.
120  

120  

121  
    @see @ref try_value_to_tag, @ref try_value_to, @ref result_for.
121  
    @see @ref try_value_to_tag, @ref try_value_to, @ref result_for.
122  
*/
122  
*/
123  
template <class T>
123  
template <class T>
124  
typename result_for<T, value>::type
124  
typename result_for<T, value>::type
125  
result_from_errno(int e, boost::source_location const* loc) noexcept
125  
result_from_errno(int e, boost::source_location const* loc) noexcept
126  
{
126  
{
127  
    system::error_code ec(e, system::generic_category(), loc);
127  
    system::error_code ec(e, system::generic_category(), loc);
128  
    return {system::in_place_error, ec};
128  
    return {system::in_place_error, ec};
129  
}
129  
}
130  

130  

131  
} // namespace json
131  
} // namespace json
132  
} // namespace boost
132  
} // namespace boost
133  

133  

134  
#endif // BOOST_JSON_RESULT_FOR_HPP
134  
#endif // BOOST_JSON_RESULT_FOR_HPP