TLA Line data Source code
1 : //
2 : // Copyright (c) 2026 Steve Gerbino
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_DETAIL_IO_RESULT_COMBINATORS_HPP
11 : #define BOOST_CAPY_DETAIL_IO_RESULT_COMBINATORS_HPP
12 :
13 : #include <boost/capy/concept/io_awaitable.hpp>
14 : #include <boost/capy/io_result.hpp>
15 :
16 : #include <system_error>
17 : #include <tuple>
18 : #include <type_traits>
19 : #include <utility>
20 :
21 : namespace boost {
22 : namespace capy {
23 : namespace detail {
24 :
25 : template<typename T>
26 : struct is_io_result : std::false_type {};
27 :
28 : template<typename... Args>
29 : struct is_io_result<io_result<Args...>> : std::true_type {};
30 :
31 : template<typename T>
32 : inline constexpr bool is_io_result_v = is_io_result<T>::value;
33 :
34 : /// True when every awaitable in the pack returns an io_result.
35 : template<typename... As>
36 : concept all_io_result_awaitables =
37 : (is_io_result_v<awaitable_result_t<As>> && ...);
38 :
39 : /// True when the io_result-aware when_all overload should be used.
40 : template<typename... As>
41 : concept when_all_io_eligible =
42 : (sizeof...(As) > 0)
43 : && all_io_result_awaitables<As...>;
44 :
45 : /// True when the io_result-aware when_any overload should be used.
46 : template<typename... As>
47 : concept when_any_io_eligible =
48 : (sizeof...(As) > 0)
49 : && all_io_result_awaitables<As...>;
50 :
51 : /// Map an io_result specialization to its contributed payload type.
52 : ///
53 : /// io_result<T> -> T (unwrap single)
54 : /// io_result<Ts...> -> tuple<Ts...> (zero, two, or more)
55 : template<typename IoResult>
56 : struct io_result_payload;
57 :
58 : template<typename T>
59 : struct io_result_payload<io_result<T>>
60 : {
61 : using type = T;
62 : };
63 :
64 : template<typename... Ts>
65 : struct io_result_payload<io_result<Ts...>>
66 : {
67 : using type = std::tuple<Ts...>;
68 : };
69 :
70 : template<typename IoResult>
71 : using io_result_payload_t =
72 : typename io_result_payload<IoResult>::type;
73 :
74 : /// Extract the payload value(s) from an io_result,
75 : /// matching the type produced by io_result_payload_t.
76 : template<typename T>
77 : T
78 HIT 66 : extract_io_payload(io_result<T>&& r)
79 : {
80 66 : return std::get<0>(std::move(r.values));
81 : }
82 :
83 : template<typename... Ts>
84 : std::tuple<Ts...>
85 38 : extract_io_payload(io_result<Ts...>&& r)
86 : {
87 38 : return std::move(r.values);
88 : }
89 :
90 : /// Reconstruct a success io_result from a payload extracted by when_any.
91 : template<typename IoResult>
92 : struct io_result_from_payload;
93 :
94 : template<typename T>
95 : struct io_result_from_payload<io_result<T>>
96 : {
97 : static io_result<T> apply(T t)
98 : {
99 : return io_result<T>{{}, std::move(t)};
100 : }
101 : };
102 :
103 : template<typename... Ts>
104 : struct io_result_from_payload<io_result<Ts...>>
105 : {
106 : static io_result<Ts...> apply(std::tuple<Ts...> t)
107 : {
108 : return std::apply([](auto&&... args) {
109 : return io_result<Ts...>{{}, std::move(args)...};
110 : }, std::move(t));
111 : }
112 : };
113 :
114 : /// Build the outer io_result for when_all from a tuple of child io_results.
115 : template<typename ResultType, typename Tuple, std::size_t... Is>
116 : ResultType
117 36 : build_when_all_io_result_impl(Tuple&& results, std::index_sequence<Is...>)
118 : {
119 36 : std::error_code ec;
120 71 : (void)((std::get<Is>(results).ec && !ec
121 20 : ? (ec = std::get<Is>(results).ec, true)
122 15 : : false) || ...);
123 :
124 37 : return ResultType{ec, extract_io_payload(
125 106 : std::move(std::get<Is>(results)))...};
126 17 : }
127 :
128 : template<typename ResultType, typename... IoResults>
129 : ResultType
130 36 : build_when_all_io_result(std::tuple<IoResults...>&& results)
131 : {
132 : return build_when_all_io_result_impl<ResultType>(
133 36 : std::move(results),
134 36 : std::index_sequence_for<IoResults...>{});
135 : }
136 :
137 : } // namespace detail
138 : } // namespace capy
139 : } // namespace boost
140 :
141 : #endif
|