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   // 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_IO_RESULT_HPP 10   #ifndef BOOST_CAPY_IO_RESULT_HPP
11   #define BOOST_CAPY_IO_RESULT_HPP 11   #define BOOST_CAPY_IO_RESULT_HPP
12   12  
13   #include <boost/capy/detail/config.hpp> 13   #include <boost/capy/detail/config.hpp>
14   #include <system_error> 14   #include <system_error>
15   15  
16   #include <cstddef> 16   #include <cstddef>
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   23  
24   /** Result type for asynchronous I/O operations. 24   /** Result type for asynchronous I/O operations.
25   25  
26   This template provides a unified result type for async operations, 26   This template provides a unified result type for async operations,
27   always containing a `std::error_code` plus optional additional 27   always containing a `std::error_code` plus optional additional
28   values. It supports structured bindings via the tuple protocol. 28   values. It supports structured bindings via the tuple protocol.
29   29  
30   @par Example 30   @par Example
31   @code 31   @code
32   auto [ec, n] = co_await s.read_some(buf); 32   auto [ec, n] = co_await s.read_some(buf);
33   if (ec) { ... } 33   if (ec) { ... }
34   @endcode 34   @endcode
35   35  
36   @note Payload members are only meaningful when 36   @note Payload members are only meaningful when
37   `ec` does not indicate an error. 37   `ec` does not indicate an error.
38   38  
39   @tparam Ts Ordered payload types following the leading 39   @tparam Ts Ordered payload types following the leading
40   `std::error_code`. 40   `std::error_code`.
41   */ 41   */
42   template<class... Ts> 42   template<class... Ts>
43   struct [[nodiscard]] io_result 43   struct [[nodiscard]] io_result
44   { 44   {
45   /// The error code from the operation. 45   /// The error code from the operation.
46   std::error_code ec; 46   std::error_code ec;
47   47  
48   /// The payload values. Unspecified when `ec` is set. 48   /// The payload values. Unspecified when `ec` is set.
49   std::tuple<Ts...> values; 49   std::tuple<Ts...> values;
50   50  
51   /// Construct a default io_result. 51   /// Construct a default io_result.
HITCBC 52   750 io_result() = default; 52   750 io_result() = default;
53   53  
54   /// Construct from an error code and payload values. 54   /// Construct from an error code and payload values.
HITCBC 55   5863 io_result(std::error_code ec_, Ts... ts) 55   5863 io_result(std::error_code ec_, Ts... ts)
HITCBC 56   5863 : ec(ec_) 56   5863 : ec(ec_)
HITCBC 57   5526 , values(std::move(ts)...) 57   5526 , values(std::move(ts)...)
58   { 58   {
HITCBC 59   5863 } 59   5863 }
60   60  
61   /// @cond 61   /// @cond
62   template<std::size_t I> 62   template<std::size_t I>
63   decltype(auto) get() & noexcept 63   decltype(auto) get() & noexcept
64   { 64   {
65   static_assert(I < 1 + sizeof...(Ts), "index out of range"); 65   static_assert(I < 1 + sizeof...(Ts), "index out of range");
66   if constexpr (I == 0) return (ec); 66   if constexpr (I == 0) return (ec);
67   else return std::get<I - 1>(values); 67   else return std::get<I - 1>(values);
68   } 68   }
69   69  
70   template<std::size_t I> 70   template<std::size_t I>
71   decltype(auto) get() const& noexcept 71   decltype(auto) get() const& noexcept
72   { 72   {
73   static_assert(I < 1 + sizeof...(Ts), "index out of range"); 73   static_assert(I < 1 + sizeof...(Ts), "index out of range");
74   if constexpr (I == 0) return (ec); 74   if constexpr (I == 0) return (ec);
75   else return std::get<I - 1>(values); 75   else return std::get<I - 1>(values);
76   } 76   }
77   77  
78   template<std::size_t I> 78   template<std::size_t I>
HITCBC 79   11479 decltype(auto) get() && noexcept 79   11479 decltype(auto) get() && noexcept
80   { 80   {
81   static_assert(I < 1 + sizeof...(Ts), "index out of range"); 81   static_assert(I < 1 + sizeof...(Ts), "index out of range");
HITCBC 82   6192 if constexpr (I == 0) return std::move(ec); 82   6192 if constexpr (I == 0) return std::move(ec);
HITCBC 83   5287 else return std::get<I - 1>(std::move(values)); 83   5287 else return std::get<I - 1>(std::move(values));
84   } 84   }
85   /// @endcond 85   /// @endcond
86   }; 86   };
87   87  
88   /// @cond 88   /// @cond
89   template<std::size_t I, class... Ts> 89   template<std::size_t I, class... Ts>
90   decltype(auto) get(io_result<Ts...>& r) noexcept 90   decltype(auto) get(io_result<Ts...>& r) noexcept
91   { 91   {
92   return r.template get<I>(); 92   return r.template get<I>();
93   } 93   }
94   94  
95   template<std::size_t I, class... Ts> 95   template<std::size_t I, class... Ts>
96   decltype(auto) get(io_result<Ts...> const& r) noexcept 96   decltype(auto) get(io_result<Ts...> const& r) noexcept
97   { 97   {
98   return r.template get<I>(); 98   return r.template get<I>();
99   } 99   }
100   100  
101   template<std::size_t I, class... Ts> 101   template<std::size_t I, class... Ts>
102   decltype(auto) get(io_result<Ts...>&& r) noexcept 102   decltype(auto) get(io_result<Ts...>&& r) noexcept
103   { 103   {
104   return std::move(r).template get<I>(); 104   return std::move(r).template get<I>();
105   } 105   }
106   /// @endcond 106   /// @endcond
107   107  
108   } // namespace capy 108   } // namespace capy
109   } // namespace boost 109   } // namespace boost
110   110  
111   // Tuple protocol for structured bindings 111   // Tuple protocol for structured bindings
112   namespace std { 112   namespace std {
113   113  
114   template<class... Ts> 114   template<class... Ts>
115   struct tuple_size<boost::capy::io_result<Ts...>> 115   struct tuple_size<boost::capy::io_result<Ts...>>
116   : std::integral_constant<std::size_t, 1 + sizeof...(Ts)> {}; 116   : std::integral_constant<std::size_t, 1 + sizeof...(Ts)> {};
117   117  
118   template<class... Ts> 118   template<class... Ts>
119   struct tuple_element<0, boost::capy::io_result<Ts...>> 119   struct tuple_element<0, boost::capy::io_result<Ts...>>
120   { 120   {
121   using type = std::error_code; 121   using type = std::error_code;
122   }; 122   };
123   123  
124   template<std::size_t I, class... Ts> 124   template<std::size_t I, class... Ts>
125   struct tuple_element<I, boost::capy::io_result<Ts...>> 125   struct tuple_element<I, boost::capy::io_result<Ts...>>
126   { 126   {
127   using type = std::tuple_element_t<I - 1, std::tuple<Ts...>>; 127   using type = std::tuple_element_t<I - 1, std::tuple<Ts...>>;
128   }; 128   };
129   129  
130   } // namespace std 130   } // namespace std
131   131  
132   #endif // BOOST_CAPY_IO_RESULT_HPP 132   #endif // BOOST_CAPY_IO_RESULT_HPP