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