100.00% Lines (2/2) 100.00% Functions (1/1)
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   // Copyright (c) 2026 Michael Vandeberg
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 5   // Distributed under the Boost Software License, Version 1.0. (See accompanying
6   // 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)
7   // 7   //
8   // Official repository: https://github.com/cppalliance/capy 8   // Official repository: https://github.com/cppalliance/capy
9   // 9   //
10   10  
11   #ifndef BOOST_CAPY_WRITE_HPP 11   #ifndef BOOST_CAPY_WRITE_HPP
12   #define BOOST_CAPY_WRITE_HPP 12   #define BOOST_CAPY_WRITE_HPP
13   13  
14   #include <boost/capy/detail/config.hpp> 14   #include <boost/capy/detail/config.hpp>
15   #include <boost/capy/io_task.hpp> 15   #include <boost/capy/io_task.hpp>
16   #include <boost/capy/buffers.hpp> 16   #include <boost/capy/buffers.hpp>
17   #include <boost/capy/buffers/consuming_buffers.hpp> 17   #include <boost/capy/buffers/consuming_buffers.hpp>
18   #include <boost/capy/concept/write_stream.hpp> 18   #include <boost/capy/concept/write_stream.hpp>
19   #include <system_error> 19   #include <system_error>
20   20  
21   #include <cstddef> 21   #include <cstddef>
22   22  
23   namespace boost { 23   namespace boost {
24   namespace capy { 24   namespace capy {
25   25  
26   /** Write an entire buffer sequence to a stream. 26   /** Write an entire buffer sequence to a stream.
27   27  
28   @par Await-effects 28   @par Await-effects
29   29  
30   Writes the contents of `buffers` to `stream` via awaiting 30   Writes the contents of `buffers` to `stream` via awaiting
31   `stream.write_some` with consecutive portions of data from `buffers` 31   `stream.write_some` with consecutive portions of data from `buffers`
32   until: 32   until:
33   33  
34   @li either the full content of @c buffers is processed, 34   @li either the full content of @c buffers is processed,
35   @li or a contingency in `stream.write_some` occurs. 35   @li or a contingency in `stream.write_some` occurs.
36   36  
37   If `buffer_size(buffers) == 0` then no awaiting `stream.write_some` 37   If `buffer_size(buffers) == 0` then no awaiting `stream.write_some`
38   is performed. This is not a contingency. 38   is performed. This is not a contingency.
39   39  
40   40  
41   @par Await-returns 41   @par Await-returns
42   42  
43   An object of type `io_result<std::size_t>` destructuring as `[ec, n]`. 43   An object of type `io_result<std::size_t>` destructuring as `[ec, n]`.
44   44  
45   Upon a contingency, `n` represents the number of bytes written 45   Upon a contingency, `n` represents the number of bytes written
46   so far. 46   so far.
47   47  
48   Otherwise `n` represents the number of bytes written. 48   Otherwise `n` represents the number of bytes written.
49   49  
50   Contingencies: 50   Contingencies:
51   51  
52   @li The first contingency reported from awaiting @c stream.write_some 52   @li The first contingency reported from awaiting @c stream.write_some
53   while not all bytes have been written. A contingency that accompanies 53   while not all bytes have been written. A contingency that accompanies
54   the write which transfers the last bytes is not reported: a completed 54   the write which transfers the last bytes is not reported: a completed
55   transfer is a success. 55   transfer is a success.
56   56  
57   Notable conditions: 57   Notable conditions:
58   58  
59   @li @c cond::canceled — Operation was cancelled, 59   @li @c cond::canceled — Operation was cancelled,
60   @li @c std::errc::broken_pipe — Peer closed connection. 60   @li @c std::errc::broken_pipe — Peer closed connection.
61   61  
62   62  
63   @par Await-postcondition 63   @par Await-postcondition
64   64  
65   If `n == buffer_size(buffers)` the transfer completed and `ec` is 65   If `n == buffer_size(buffers)` the transfer completed and `ec` is
66   success; otherwise `ec` is set. 66   success; otherwise `ec` is set.
67   67  
68   68  
69   @param stream The stream to write to. If the lifetime of `stream` ends 69   @param stream The stream to write to. If the lifetime of `stream` ends
70   before the coroutine finishes, the behavior is undefined. 70   before the coroutine finishes, the behavior is undefined.
71   71  
72   @param buffers The buffer sequence to write. If the lifetime of the buffer 72   @param buffers The buffer sequence to write. If the lifetime of the buffer
73   sequence represented by `buffers` ends 73   sequence represented by `buffers` ends
74   before the coroutine finishes, the behavior is undefined. 74   before the coroutine finishes, the behavior is undefined.
75   75  
76   @return A task yielding `io_result<std::size_t>` whose second element 76   @return A task yielding `io_result<std::size_t>` whose second element
77   is the number of bytes written. 77   is the number of bytes written.
78   78  
79   @par Remarks 79   @par Remarks
80   80  
81   Supports _IoAwaitable cancellation_. 81   Supports _IoAwaitable cancellation_.
82   82  
83   @par Example 83   @par Example
84   84  
85 - @code 85 + @par !example example
86 - capy::task<> send_response(capy::WriteStream auto& stream, std::string_view body)  
87 - {  
88 - auto [ec, n] = co_await capy::write(stream, capy::make_buffer(body));  
89 - if (ec)  
90 - throw std::system_error(ec);  
91 - // All bytes written successfully  
92 - }  
93 - @endcode  
94   86  
95   87  
96   @see WriteStream, ConstBufferSequence, IoAwaitable, io_result, cond. 88   @see WriteStream, ConstBufferSequence, IoAwaitable, io_result, cond.
97   */ 89   */
98   template <WriteStream S, ConstBufferSequence CB> 90   template <WriteStream S, ConstBufferSequence CB>
HITCBC 99   70 auto write(S& stream, CB buffers) -> io_task<std::size_t> 91   70 auto write(S& stream, CB buffers) -> io_task<std::size_t>
100   { 92   {
101   consuming_buffers consuming(buffers); 93   consuming_buffers consuming(buffers);
102   std::size_t const total_size = buffer_size(buffers); 94   std::size_t const total_size = buffer_size(buffers);
103   std::size_t total_written = 0; 95   std::size_t total_written = 0;
104   96  
105   while(total_written < total_size) 97   while(total_written < total_size)
106   { 98   {
107   auto [ec, n] = co_await stream.write_some(consuming.data()); 99   auto [ec, n] = co_await stream.write_some(consuming.data());
108   consuming.consume(n); 100   consuming.consume(n);
109   total_written += n; 101   total_written += n;
110   // A contingency that still completed the transfer is a success: 102   // A contingency that still completed the transfer is a success:
111   // report it only when not all bytes were written. 103   // report it only when not all bytes were written.
112   if(ec && total_written < total_size) 104   if(ec && total_written < total_size)
113   co_return {ec, total_written}; 105   co_return {ec, total_written};
114   } 106   }
115   107  
116   co_return {std::error_code(), total_written}; 108   co_return {std::error_code(), total_written};
HITCBC 117   140 } 109   140 }
118   110  
119   } // namespace capy 111   } // namespace capy
120   } // namespace boost 112   } // namespace boost
121   113  
122   #endif 114   #endif