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   // 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_WRITE_HPP 10   #ifndef BOOST_CAPY_WRITE_HPP
11   #define BOOST_CAPY_WRITE_HPP 11   #define BOOST_CAPY_WRITE_HPP
12   12  
13   #include <boost/capy/detail/config.hpp> 13   #include <boost/capy/detail/config.hpp>
14   #include <boost/capy/io_task.hpp> 14   #include <boost/capy/io_task.hpp>
15   #include <boost/capy/buffers.hpp> 15   #include <boost/capy/buffers.hpp>
16   #include <boost/capy/buffers/buffer_slice.hpp> 16   #include <boost/capy/buffers/buffer_slice.hpp>
17   #include <boost/capy/concept/write_stream.hpp> 17   #include <boost/capy/concept/write_stream.hpp>
18   #include <system_error> 18   #include <system_error>
19   19  
20   #include <cstddef> 20   #include <cstddef>
21   21  
22   namespace boost { 22   namespace boost {
23   namespace capy { 23   namespace capy {
24   24  
25 - /** Asynchronously write the entire buffer sequence. 25 + /** Make an awaitable for writing a buffer sequence to a stream.
26   26  
27 - Writes data to the stream by calling `write_some` repeatedly 27 + @par Await-effects
28 - until the entire buffer sequence is written or an error occurs. 28 +
  29 + Writes the contents of `buffers` to `stream` via awaiting on
  30 + `stream.write_some` with consecutive portions of data form `buffers`
  31 + until:
  32 +
  33 + @li either the full content of @c buffers is processed,
  34 + @li or a contingency occurs.
  35 +
  36 +
  37 + @par Await-returns
  38 +
  39 + An object of type `io_result<std::size_t>` destructuring as `[ec, n]`.
  40 +
  41 + Upon a contingency, `n` represents the number of bytes written
  42 + so far.
  43 +
  44 + Otherwise `n` represents the number of bytes written.
  45 +
  46 + Contingencies:
  47 +
  48 + @li Whatever the first contingency is reported from
  49 + awaiting on @c stream.write_some .
  50 +
  51 + Notable conditions:
  52 +
  53 + @li @c cond::canceled — Operation was cancelled,
  54 + @li @c std::errc::broken_pipe — Peer closed connection.
  55 +
  56 +
  57 + @par Await-postcondition
  58 +
  59 + `ec || n == buffer_size(buffers)`.
29 - @li The operation completes when:  
30 - @li The entire buffer sequence has been written  
31 - @li An error occurs  
32 - @li The operation is cancelled  
33   60  
34   61  
35   @par Cancellation 62   @par Cancellation
36   Supports cancellation via `stop_token` propagated through the 63   Supports cancellation via `stop_token` propagated through the
37 - IoAwaitable protocol. When cancelled, returns with `cond::canceled`. 64 + `IoAwaitable` protocol. When cancelled, returns with `cond::canceled`.
38   65  
39 - @param stream The stream to write to. The caller retains ownership. 66 + @param stream The stream to write to. If the lifetime of `stream` ends
40 - @param buffers The buffer sequence to write. The caller retains 67 + before the coroutine finishes, the behavior is undefined.
41 - ownership and must ensure validity until the operation completes. 68 +
  69 + @param buffers The buffer sequence to write. If the lifetime of `buffers` ends
  70 + before the coroutine finishes, the behavior is undefined.
42 - @return An awaitable that await-returns `(error_code, std::size_t)`.  
43 - On success, `n` equals `buffer_size(buffers)`. On error,  
44 - `n` is the number of bytes written before the error. Compare  
45 - error codes to conditions:  
46 - @li `cond::canceled` - Operation was cancelled  
47 - @li `std::errc::broken_pipe` - Peer closed connection  
48   71  
49   72  
50   @par Example 73   @par Example
51   74  
52   @code 75   @code
53 - task<> send_response( WriteStream auto& stream, std::string_view body ) 76 + task<> send_response(capy::WriteStream auto& stream, std::string_view body)
54   { 77   {
55 - auto [ec, n] = co_await write( stream, make_buffer( body ) ); 78 + auto [ec, n] = co_await capy::write(stream, capy::make_buffer(body));
56 - if( ec ) 79 + if (ec)
57 - detail::throw_system_error( ec ); 80 + throw std::system_error(ec);
  81 +
58   // All bytes written successfully 82   // All bytes written successfully
59   } 83   }
60   @endcode 84   @endcode
61   85  
  86 + @return
  87 +
62   @see write_some, WriteStream, ConstBufferSequence 88   @see write_some, WriteStream, ConstBufferSequence
63   */ 89   */
64 - auto 90 + template <WriteStream S, ConstBufferSequence CB>
HITCBC 65 - 50 write( 91 + 50 auto write(S& stream, CB buffers) -> io_task<std::size_t>
66 - WriteStream auto& stream,  
67 - ConstBufferSequence auto buffers) ->  
68 - io_task<std::size_t>  
69   { 92   {
70   auto consuming = buffer_slice(buffers); 93   auto consuming = buffer_slice(buffers);
71   std::size_t const total_size = buffer_size(buffers); 94   std::size_t const total_size = buffer_size(buffers);
72   std::size_t total_written = 0; 95   std::size_t total_written = 0;
73   96  
74   while(total_written < total_size) 97   while(total_written < total_size)
75   { 98   {
76   auto [ec, n] = co_await stream.write_some(consuming.data()); 99   auto [ec, n] = co_await stream.write_some(consuming.data());
77   consuming.remove_prefix(n); 100   consuming.remove_prefix(n);
78   total_written += n; 101   total_written += n;
79   if(ec) 102   if(ec)
80   co_return {ec, total_written}; 103   co_return {ec, total_written};
81   } 104   }
82   105  
83   co_return {{}, total_written}; 106   co_return {{}, total_written};
HITCBC 84   100 } 107   100 }
85   108  
86   } // namespace capy 109   } // namespace capy
87   } // namespace boost 110   } // namespace boost
88   111  
89   #endif 112   #endif