100.00% Lines (2/2) 100.00% Functions (1/1)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2026 Michael Vandeberg 2   // Copyright (c) 2026 Michael Vandeberg
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_AT_LEAST_HPP 10   #ifndef BOOST_CAPY_WRITE_AT_LEAST_HPP
11   #define BOOST_CAPY_WRITE_AT_LEAST_HPP 11   #define BOOST_CAPY_WRITE_AT_LEAST_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/results.hpp>
  15 + #include <boost/capy/task.hpp>
15   #include <boost/capy/buffers.hpp> 16   #include <boost/capy/buffers.hpp>
16   #include <boost/capy/buffers/consuming_buffers.hpp> 17   #include <boost/capy/buffers/consuming_buffers.hpp>
17   #include <boost/capy/concept/write_stream.hpp> 18   #include <boost/capy/concept/write_stream.hpp>
18   19  
19   #include <cstddef> 20   #include <cstddef>
20   #include <system_error> 21   #include <system_error>
21   22  
22   namespace boost { 23   namespace boost {
23   namespace capy { 24   namespace capy {
24   25  
25   /** Write at least a minimum number of bytes to a stream. 26   /** Write at least a minimum number of bytes to a stream.
26   27  
27   This is a straightforward extension of @ref write. While @ref write 28   This is a straightforward extension of @ref write. While @ref write
28   transfers exactly `buffer_size(buffers)` bytes, `write_at_least` 29   transfers exactly `buffer_size(buffers)` bytes, `write_at_least`
29   transfers at least `n` bytes. The loop stops as soon as `n` bytes 30   transfers at least `n` bytes. The loop stops as soon as `n` bytes
30   have been written, even if `buffers` has not been fully consumed. 31   have been written, even if `buffers` has not been fully consumed.
31   Any bytes beyond `n` that a single `stream.write_some` happens to 32   Any bytes beyond `n` that a single `stream.write_some` happens to
32   transfer are counted. No further awaiting is performed to write the 33   transfer are counted. No further awaiting is performed to write the
33   remainder. 34   remainder.
34   35  
35   Provided for symmetry with @ref read_at_least. 36   Provided for symmetry with @ref read_at_least.
36   37  
37   @par Await-effects 38   @par Await-effects
38   39  
39   If `n > buffer_size(buffers)` the request is impossible to satisfy 40   If `n > buffer_size(buffers)` the request is impossible to satisfy
40   and the operation fails immediately with 41   and the operation fails immediately with
41   `{std::errc::invalid_argument, 0}` without awaiting `stream.write_some`. 42   `{std::errc::invalid_argument, 0}` without awaiting `stream.write_some`.
42   43  
43   Otherwise writes the contents of `buffers` to `stream` via awaiting 44   Otherwise writes the contents of `buffers` to `stream` via awaiting
44   `stream.write_some` with consecutive portions of data from `buffers` 45   `stream.write_some` with consecutive portions of data from `buffers`
45   until: 46   until:
46   47  
47   @li either at least `n` bytes have been written, 48   @li either at least `n` bytes have been written,
48   @li or a contingency in `stream.write_some` occurs. 49   @li or a contingency in `stream.write_some` occurs.
49   50  
50   If `n == 0` then no awaiting `stream.write_some` is performed. This is 51   If `n == 0` then no awaiting `stream.write_some` is performed. This is
51   not a contingency. 52   not a contingency.
52   53  
53   @par Await-returns 54   @par Await-returns
54 - An object of type `io_result<std::size_t>` destructuring as `[ec, n]`. 55 + An object of type `results<std::size_t>` destructuring as `[ec, n]`.
55   56  
56   Upon a contingency, the count represents the number of bytes written 57   Upon a contingency, the count represents the number of bytes written
57   so far. 58   so far.
58   59  
59   Contingencies: 60   Contingencies:
60   61  
61   @li The first contingency reported from awaiting @c stream.write_some 62   @li The first contingency reported from awaiting @c stream.write_some
62   while fewer than `n` bytes have been written. A contingency that 63   while fewer than `n` bytes have been written. A contingency that
63   accompanies the write which reaches `n` is not reported: a 64   accompanies the write which reaches `n` is not reported: a
64   satisfied request is a success. 65   satisfied request is a success.
65   66  
66   Notable conditions: 67   Notable conditions:
67   68  
68   @li @c std::errc::invalid_argument — `n` exceeds `buffer_size(buffers)`, 69   @li @c std::errc::invalid_argument — `n` exceeds `buffer_size(buffers)`,
69   @li @c cond::canceled — Operation was cancelled, 70   @li @c cond::canceled — Operation was cancelled,
70   @li @c std::errc::broken_pipe — Peer closed connection. 71   @li @c std::errc::broken_pipe — Peer closed connection.
71   72  
72   @par Await-postcondition 73   @par Await-postcondition
73   On success the returned count is greater than or equal to `n` and 74   On success the returned count is greater than or equal to `n` and
74   less than or equal to `buffer_size(buffers)`, and `ec` is success. 75   less than or equal to `buffer_size(buffers)`, and `ec` is success.
75   Otherwise `ec` is set. 76   Otherwise `ec` is set.
76   77  
77   @param stream The stream to write to. If the lifetime of `stream` ends 78   @param stream The stream to write to. If the lifetime of `stream` ends
78   before the coroutine finishes, the behavior is undefined. 79   before the coroutine finishes, the behavior is undefined.
79   80  
80   @param buffers The buffer sequence to write. If the lifetime of the 81   @param buffers The buffer sequence to write. If the lifetime of the
81   buffer sequence represented by `buffers` ends before the coroutine 82   buffer sequence represented by `buffers` ends before the coroutine
82   finishes, the behavior is undefined. 83   finishes, the behavior is undefined.
83   84  
84   @param n The minimum number of bytes to write. Must not exceed 85   @param n The minimum number of bytes to write. Must not exceed
85   `buffer_size(buffers)`. 86   `buffer_size(buffers)`.
86   87  
87 - @return A task yielding `io_result<std::size_t>` whose second element 88 + @return A task yielding `results<std::size_t>` whose second element
88   is the number of bytes written. 89   is the number of bytes written.
89   90  
90   @par Remarks 91   @par Remarks
91 - Supports _IoAwaitable cancellation_. 92 + Supports _ContextAwaitable cancellation_.
92   93  
93   @par Example 94   @par Example
94   95  
95   @par !example example 96   @par !example example
96   97  
97   98  
98   @see write, WriteStream, ConstBufferSequence 99   @see write, WriteStream, ConstBufferSequence
99   */ 100   */
100   template <WriteStream S, ConstBufferSequence CB> 101   template <WriteStream S, ConstBufferSequence CB>
101   auto 102   auto
HITCBC 102 - 33 write_at_least(S& stream, CB buffers, std::size_t n) -> io_task<std::size_t> 103 + 33 write_at_least(S& stream, CB buffers, std::size_t n) -> task<results<std::size_t>>
103   { 104   {
104   consuming_buffers consuming(buffers); 105   consuming_buffers consuming(buffers);
105   std::size_t const total_size = buffer_size(buffers); 106   std::size_t const total_size = buffer_size(buffers);
106   107  
107   if(n > total_size) 108   if(n > total_size)
108   co_return {make_error_code(std::errc::invalid_argument), 0}; 109   co_return {make_error_code(std::errc::invalid_argument), 0};
109   110  
110   std::size_t total_written = 0; 111   std::size_t total_written = 0;
111   112  
112   while(total_written < n) 113   while(total_written < n)
113   { 114   {
114   auto [ec, m] = co_await stream.write_some(consuming.data()); 115   auto [ec, m] = co_await stream.write_some(consuming.data());
115   consuming.consume(m); 116   consuming.consume(m);
116   total_written += m; 117   total_written += m;
117   // A contingency that still satisfied the request is a success: 118   // A contingency that still satisfied the request is a success:
118   // report it only when fewer than n bytes were written. 119   // report it only when fewer than n bytes were written.
119   if(ec && total_written < n) 120   if(ec && total_written < n)
120   co_return {ec, total_written}; 121   co_return {ec, total_written};
121   } 122   }
122   123  
123   co_return {std::error_code(), total_written}; 124   co_return {std::error_code(), total_written};
HITCBC 124   66 } 125   66 }
125   126  
126   } // namespace capy 127   } // namespace capy
127   } // namespace boost 128   } // namespace boost
128   129  
129   #endif 130   #endif