Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/capy
8 : //
9 :
10 : #ifndef BOOST_CAPY_IO_RESULT_HPP
11 : #define BOOST_CAPY_IO_RESULT_HPP
12 :
13 : #include <boost/capy/detail/config.hpp>
14 : #include <boost/system/error_code.hpp>
15 :
16 : #include <cstddef>
17 : #include <tuple>
18 : #include <type_traits>
19 :
20 : namespace boost {
21 : namespace capy {
22 :
23 : /** Result type for asynchronous I/O operations.
24 :
25 : This template provides a unified result type for async operations,
26 : always containing a `system::error_code` plus optional additional
27 : values. It supports structured bindings.
28 :
29 : @tparam Args Additional value types beyond the error code.
30 :
31 : @par Usage
32 : @code
33 : // Error code path (default)
34 : auto [ec, n] = co_await s.read_some(buf);
35 : if (ec) { ... }
36 :
37 : // Exception path (opt-in)
38 : auto n = (co_await s.read_some(buf)).value();
39 : @endcode
40 : */
41 : template<class... Args>
42 : struct io_result
43 : {
44 : static_assert("io_result only supports upt to 3 template arguments");
45 : };
46 :
47 : /** Result type for void operations.
48 :
49 : Used by operations like `connect()` that don't return a value
50 : beyond success/failure.
51 :
52 : @par Example
53 : @code
54 : auto [ec] = co_await s.connect(ep);
55 : if (ec) { ... }
56 :
57 : // Or with exceptions:
58 : (co_await s.connect(ep)).value();
59 : @endcode
60 : */
61 : template<>
62 : struct io_result<>
63 : {
64 : /** The error code from the operation. */
65 : system::error_code ec;
66 : };
67 :
68 : /** Result type for byte transfer operations.
69 :
70 : Used by operations like `read_some()` and `write_some()` that
71 : return the number of bytes transferred.
72 :
73 : @par Example
74 : @code
75 : auto [ec, n] = co_await s.read_some(buf);
76 : if (ec) { ... }
77 :
78 : // Or with exceptions:
79 : auto n = (co_await s.read_some(buf)).value();
80 : @endcode
81 : */
82 : template<typename T1>
83 : struct io_result<T1>
84 : {
85 : system::error_code ec;
86 : T1 t1{};
87 : };
88 :
89 : template<typename T1, typename T2>
90 : struct io_result<T1, T2>
91 : {
92 : system::error_code ec;
93 : T1 t1{};
94 : T2 t2{};
95 : };
96 :
97 : template<typename T1, typename T2, typename T3>
98 : struct io_result<T1, T2, T3>
99 : {
100 : system::error_code ec;
101 : T1 t1{};
102 : T2 t2{};
103 : T3 t3{};
104 : };
105 :
106 : //----------------------------------------------------------
107 :
108 : template<std::size_t I, class... Args>
109 : constexpr auto&
110 : get(io_result<Args...>& r) noexcept
111 : {
112 : if constexpr(I == 0)
113 : return r.ec;
114 : else if constexpr(I == 1)
115 : return r.t1;
116 : else if constexpr(I == 2)
117 : return r.t2;
118 : else
119 : return r.t3;
120 : }
121 :
122 : template<std::size_t I, class... Args>
123 : constexpr auto const&
124 : get(io_result<Args...> const& r) noexcept
125 : {
126 : if constexpr(I == 0)
127 : return r.ec;
128 : else if constexpr(I == 1)
129 : return r.t1;
130 : else if constexpr(I == 2)
131 : return r.t2;
132 : else
133 : return r.t3;
134 : }
135 :
136 : template<std::size_t I, class... Args>
137 : constexpr auto&&
138 41 : get(io_result<Args...>&& r) noexcept
139 : {
140 : if constexpr(I == 0)
141 20 : return std::move(r.ec);
142 : else if constexpr(I == 1)
143 19 : return std::move(r.t1);
144 : else if constexpr(I == 2)
145 1 : return std::move(r.t2);
146 : else
147 1 : return std::move(r.t3);
148 : }
149 :
150 : } // namespace capy
151 : } // namespace boost
152 :
153 : template<class... Args>
154 : struct std::tuple_size<boost::capy::io_result<Args...>>
155 : : std::integral_constant<std::size_t, 1 + sizeof...(Args)> {};
156 :
157 : template<class... Args>
158 : struct std::tuple_element<0, boost::capy::io_result<Args...>>
159 : {
160 : using type = boost::system::error_code;
161 : };
162 :
163 : template<std::size_t I, class... Args>
164 : struct std::tuple_element<I, boost::capy::io_result<Args...>>
165 : {
166 : using type = std::tuple_element_t<I - 1, std::tuple<Args...>>;
167 : };
168 :
169 : #endif
|