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