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