100.00% Lines (8/8) 100.00% Functions (3/3)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
  3 + // Copyright (c) 2026 Michael Vandeberg
3   // 4   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 5   // 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   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 7   //
7   // Official repository: https://github.com/cppalliance/capy 8   // Official repository: https://github.com/cppalliance/capy
8   // 9   //
9   10  
10   #ifndef BOOST_CAPY_IO_RESULT_HPP 11   #ifndef BOOST_CAPY_IO_RESULT_HPP
11   #define BOOST_CAPY_IO_RESULT_HPP 12   #define BOOST_CAPY_IO_RESULT_HPP
12   13  
13   #include <boost/capy/detail/config.hpp> 14   #include <boost/capy/detail/config.hpp>
14   #include <system_error> 15   #include <system_error>
15   16  
16   #include <cstddef> 17   #include <cstddef>
17   #include <tuple> 18   #include <tuple>
18   #include <type_traits> 19   #include <type_traits>
19   #include <utility> 20   #include <utility>
20   21  
21   namespace boost { 22   namespace boost {
22   namespace capy { 23   namespace capy {
23   24  
24 - /** Result type for asynchronous I/O operations. 25 + /** Bundles an error code with optional payload values, exposed via the tuple protocol.
25   26  
26   This template provides a unified result type for async operations, 27   This template provides a unified result type for async operations,
27   always containing a `std::error_code` plus optional additional 28   always containing a `std::error_code` plus optional additional
28   values. It supports structured bindings via the tuple protocol. 29   values. It supports structured bindings via the tuple protocol.
29   30  
30   @par Example 31   @par Example
31   @code 32   @code
32   auto [ec, n] = co_await s.read_some(buf); 33   auto [ec, n] = co_await s.read_some(buf);
33   if (ec) { ... } 34   if (ec) { ... }
34   @endcode 35   @endcode
35   36  
36   @note Whether the payload is meaningful when `ec` is set is 37   @note Whether the payload is meaningful when `ec` is set is
37   defined by the operation that produced the result. Many I/O 38   defined by the operation that produced the result. Many I/O
38   operations report a meaningful partial result alongside `ec` 39   operations report a meaningful partial result alongside `ec`
39   (for example, the number of bytes transferred before the 40   (for example, the number of bytes transferred before the
40 - condition, as with EOF); others leave it unspecified. 41 + condition, as with EOF). Others leave it unspecified.
41   42  
42   @tparam Ts Ordered payload types following the leading 43   @tparam Ts Ordered payload types following the leading
43   `std::error_code`. 44   `std::error_code`.
44   */ 45   */
45   template<class... Ts> 46   template<class... Ts>
46   struct [[nodiscard]] io_result 47   struct [[nodiscard]] io_result
47   { 48   {
48   /// The error code from the operation. 49   /// The error code from the operation.
49   std::error_code ec; 50   std::error_code ec;
50   51  
51   /// The payload values. Their meaning when `ec` is set is defined 52   /// The payload values. Their meaning when `ec` is set is defined
52   /// by the producing operation (see the class note). 53   /// by the producing operation (see the class note).
53   std::tuple<Ts...> values; 54   std::tuple<Ts...> values;
54   55  
55   /// Construct a default io_result. 56   /// Construct a default io_result.
HITCBC 56   130 io_result() = default; 57   130 io_result() = default;
57   58  
58 - /// Construct from an error code and payload values. 59 + /** Construct from an error code and payload values.
  60 +
  61 + @param ec_ The error code for the operation.
  62 +
  63 + @param ts The payload values, in declaration order.
  64 + */
HITCBC 59   1990 io_result(std::error_code ec_, Ts... ts) 65   1983 io_result(std::error_code ec_, Ts... ts)
HITCBC 60   1990 : ec(ec_) 66   1983 : ec(ec_)
HITCBC 61   1755 , values(std::move(ts)...) 67   1755 , values(std::move(ts)...)
62   { 68   {
HITCBC 63   1990 } 69   1983 }
64   70  
65 - /// @cond 71 + /** Return the `I`-th element of the tuple protocol.
  72 +
  73 + Index 0 is @ref ec; index `I` for `I > 0` is the `I - 1`-th
  74 + payload value. This is the accessor structured bindings use.
  75 +
  76 + @tparam I The element index. Must be less than
  77 + `1 + sizeof...(Ts)`.
  78 +
  79 + @return A reference to the element.
  80 + */
66   template<std::size_t I> 81   template<std::size_t I>
67   decltype(auto) get() & noexcept 82   decltype(auto) get() & noexcept
68   { 83   {
69   static_assert(I < 1 + sizeof...(Ts), "index out of range"); 84   static_assert(I < 1 + sizeof...(Ts), "index out of range");
70   if constexpr (I == 0) return (ec); 85   if constexpr (I == 0) return (ec);
71   else return std::get<I - 1>(values); 86   else return std::get<I - 1>(values);
72   } 87   }
73   88  
  89 + /** Return the `I`-th element of the tuple protocol.
  90 +
  91 + Index 0 is @ref ec; index `I` for `I > 0` is the `I - 1`-th
  92 + payload value. This is the accessor structured bindings use.
  93 +
  94 + @tparam I The element index. Must be less than
  95 + `1 + sizeof...(Ts)`.
  96 +
  97 + @return A const reference to the element.
  98 + */
74   template<std::size_t I> 99   template<std::size_t I>
75   decltype(auto) get() const& noexcept 100   decltype(auto) get() const& noexcept
76   { 101   {
77   static_assert(I < 1 + sizeof...(Ts), "index out of range"); 102   static_assert(I < 1 + sizeof...(Ts), "index out of range");
78   if constexpr (I == 0) return (ec); 103   if constexpr (I == 0) return (ec);
79   else return std::get<I - 1>(values); 104   else return std::get<I - 1>(values);
80   } 105   }
81   106  
  107 + /** Return the `I`-th element of the tuple protocol, moved.
  108 +
  109 + Index 0 is @ref ec; index `I` for `I > 0` is the `I - 1`-th
  110 + payload value.
  111 +
  112 + @tparam I The element index. Must be less than
  113 + `1 + sizeof...(Ts)`.
  114 +
  115 + @return An rvalue reference to the element, suitable for moving
  116 + out of the result.
  117 + */
82   template<std::size_t I> 118   template<std::size_t I>
HITCBC 83   3123 decltype(auto) get() && noexcept 119   3116 decltype(auto) get() && noexcept
84   { 120   {
85   static_assert(I < 1 + sizeof...(Ts), "index out of range"); 121   static_assert(I < 1 + sizeof...(Ts), "index out of range");
HITCBC 86   1651 if constexpr (I == 0) return std::move(ec); 122   1644 if constexpr (I == 0) return std::move(ec);
HITCBC 87   1472 else return std::get<I - 1>(std::move(values)); 123   1472 else return std::get<I - 1>(std::move(values));
88 - /// @endcond  
89   } 124   }
90   }; 125   };
91   126  
92 - /// @cond 127 + /** Return the `I`-th element of the tuple protocol.
  128 +
  129 + @tparam I The element index. Must be less than
  130 + `1 + sizeof...(Ts)`.
  131 +
  132 + @param r The result to access.
  133 +
  134 + @return A reference to the element.
  135 + */
93   template<std::size_t I, class... Ts> 136   template<std::size_t I, class... Ts>
94   decltype(auto) get(io_result<Ts...>& r) noexcept 137   decltype(auto) get(io_result<Ts...>& r) noexcept
95   { 138   {
96   return r.template get<I>(); 139   return r.template get<I>();
97   } 140   }
98   141  
  142 + /** Return the `I`-th element of the tuple protocol.
  143 +
  144 + @tparam I The element index. Must be less than
  145 + `1 + sizeof...(Ts)`.
  146 +
  147 + @param r The result to access.
  148 +
  149 + @return A const reference to the element.
  150 + */
99   template<std::size_t I, class... Ts> 151   template<std::size_t I, class... Ts>
100   decltype(auto) get(io_result<Ts...> const& r) noexcept 152   decltype(auto) get(io_result<Ts...> const& r) noexcept
101   { 153   {
102   return r.template get<I>(); 154   return r.template get<I>();
103   } 155   }
104   156  
  157 + /** Return the `I`-th element of the tuple protocol, moved.
  158 +
  159 + @tparam I The element index. Must be less than
  160 + `1 + sizeof...(Ts)`.
  161 +
  162 + @param r The result to access.
  163 +
  164 + @return An rvalue reference to the element, suitable for moving out
  165 + of `r`.
  166 + */
105   template<std::size_t I, class... Ts> 167   template<std::size_t I, class... Ts>
106   decltype(auto) get(io_result<Ts...>&& r) noexcept 168   decltype(auto) get(io_result<Ts...>&& r) noexcept
107   { 169   {
108   return std::move(r).template get<I>(); 170   return std::move(r).template get<I>();
109 - /// @endcond  
110   } 171   }
111   172  
112   } // namespace capy 173   } // namespace capy
113   } // namespace boost 174   } // namespace boost
114   175  
115   // Tuple protocol for structured bindings 176   // Tuple protocol for structured bindings
116   namespace std { 177   namespace std {
117   178  
118   template<class... Ts> 179   template<class... Ts>
119   struct tuple_size<boost::capy::io_result<Ts...>> 180   struct tuple_size<boost::capy::io_result<Ts...>>
120   : std::integral_constant<std::size_t, 1 + sizeof...(Ts)> {}; 181   : std::integral_constant<std::size_t, 1 + sizeof...(Ts)> {};
121   182  
122   template<class... Ts> 183   template<class... Ts>
123   struct tuple_element<0, boost::capy::io_result<Ts...>> 184   struct tuple_element<0, boost::capy::io_result<Ts...>>
124   { 185   {
125   using type = std::error_code; 186   using type = std::error_code;
126   }; 187   };
127   188  
128   template<std::size_t I, class... Ts> 189   template<std::size_t I, class... Ts>
129   struct tuple_element<I, boost::capy::io_result<Ts...>> 190   struct tuple_element<I, boost::capy::io_result<Ts...>>
130   { 191   {
131   using type = std::tuple_element_t<I - 1, std::tuple<Ts...>>; 192   using type = std::tuple_element_t<I - 1, std::tuple<Ts...>>;
132   }; 193   };
133   194  
134   } // namespace std 195   } // namespace std
135   196  
136   #endif // BOOST_CAPY_IO_RESULT_HPP 197   #endif // BOOST_CAPY_IO_RESULT_HPP