include/boost/capy/write_at_least.hpp

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