include/boost/capy/read.hpp

100.0% Lines (2/0/2) 100.0% List of functions (4/0/4)
read.hpp
f(x) Functions (4)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2026 Michael Vandeberg
4 //
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)
7 //
8 // Official repository: https://github.com/cppalliance/capy
9 //
10
11 #ifndef BOOST_CAPY_READ_HPP
12 #define BOOST_CAPY_READ_HPP
13
14 #include <boost/capy/detail/config.hpp>
15 #include <boost/capy/cond.hpp>
16 #include <boost/capy/io_task.hpp>
17 #include <boost/capy/buffers.hpp>
18 #include <boost/capy/buffers/consuming_buffers.hpp>
19 #include <boost/capy/concept/read_stream.hpp>
20
21 #include <algorithm>
22 #include <cstddef>
23
24 namespace boost {
25 namespace capy {
26
27 /** Read data from a stream until the buffer sequence is full.
28
29 @par Await-effects
30
31 Reads data from `stream` via awaiting `stream.read_some` repeatedly
32 until:
33
34 @li either the entire buffer sequence @c buffers is filled,
35 @li or a contingency occurs on `stream.read_some`.
36
37 If `buffer_size(buffers) == 0` then no awaiting `stream.read_some`
38 is performed. This is not a contingency.
39
40 @par Await-returns
41 An object of type `io_result<std::size_t>` destructuring as `[ec, n]`.
42
43 Upon a contingency, `n` represents the number of bytes read so far,
44 inclusive of the last partial read.
45
46 Contingencies:
47
48 @li The first contingency reported from awaiting @c stream.read_some
49 while `buffers` is not yet filled. A contingency that accompanies
50 the read which fills `buffers` is not reported: a completed
51 transfer is a success.
52
53 Notable conditions:
54
55 @li @c cond::canceled — Operation was cancelled,
56 @li @c cond::eof — Stream reached end before @c buffers was filled.
57
58 @par Await-postcondition
59 If `n == buffer_size(buffers)` the transfer completed and `ec` is
60 success; otherwise `ec` is set.
61
62 @param stream The stream to read from. If the lifetime of `stream` ends
63 before the coroutine finishes, the behavior is undefined.
64
65 @param buffers The buffer sequence to fill. If the lifetime of the buffer
66 sequence represented by `buffers` ends before the coroutine finishes, the behavior is undefined.
67
68 @return A task yielding `io_result<std::size_t>` whose second element
69 is the number of bytes read.
70
71 @par Remarks
72 Supports _IoAwaitable cancellation_.
73
74
75 @par Example
76
77 @par !example example
78
79
80 @see ReadStream, MutableBufferSequence
81 */
82 template <typename S, typename MB>
83 requires ReadStream<S> && MutableBufferSequence<MB>
84 auto
85 99x read(S& stream, MB buffers) ->
86 io_task<std::size_t>
87 {
88 consuming_buffers consuming(buffers);
89 std::size_t const total_size = buffer_size(buffers);
90 std::size_t total_read = 0;
91
92 while(total_read < total_size)
93 {
94 auto [ec, n] = co_await stream.read_some(consuming.data());
95 consuming.consume(n);
96 total_read += n;
97 // A contingency that still completed the transfer is a success:
98 // report it only when the buffer was not filled.
99 if(ec && total_read < total_size)
100 co_return {ec, total_read};
101 }
102
103 co_return {std::error_code(), total_read};
104 198x }
105
106 } // namespace capy
107 } // namespace boost
108
109 #endif
110