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