libs/capy/include/boost/capy/io/push_to.hpp

100.0% Lines (4/4) 100.0% Functions (3/3) 100.0% Branches (2/2)
libs/capy/include/boost/capy/io/push_to.hpp
Line Branch Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
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_IO_PUSH_TO_HPP
11 #define BOOST_CAPY_IO_PUSH_TO_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/buffers.hpp>
15 #include <boost/capy/cond.hpp>
16 #include <boost/capy/concept/buffer_source.hpp>
17 #include <boost/capy/concept/write_sink.hpp>
18 #include <boost/capy/concept/write_stream.hpp>
19 #include <boost/capy/io_task.hpp>
20
21 #include <cstddef>
22 #include <span>
23
24 namespace boost {
25 namespace capy {
26
27 /** Transfer data from a BufferSource to a WriteSink.
28
29 This function pulls data from the source and writes it to the
30 sink until the source is exhausted or an error occurs. When
31 the source signals completion, `write_eof()` is called on the
32 sink to finalize the transfer.
33
34 @tparam Src The source type, must satisfy @ref BufferSource.
35 @tparam Sink The sink type, must satisfy @ref WriteSink.
36
37 @param source The source to pull data from.
38 @param sink The sink to write data to.
39
40 @return A task that yields `(std::error_code, std::size_t)`.
41 On success, `ec` is default-constructed (no error) and `n` is
42 the total number of bytes transferred. On error, `ec` contains
43 the error code and `n` is the total number of bytes transferred
44 before the error.
45
46 @par Example
47 @code
48 task<void> transfer_body(BufferSource auto& source, WriteSink auto& sink)
49 {
50 auto [ec, n] = co_await push_to(source, sink);
51 if (ec)
52 {
53 // Handle error
54 }
55 // n bytes were transferred
56 }
57 @endcode
58
59 @see BufferSource, WriteSink
60 */
61 template<BufferSource Src, WriteSink Sink>
62 io_task<std::size_t>
63
1/1
✓ Branch 1 taken 140 times.
140 push_to(Src& source, Sink& sink)
64 {
65 const_buffer arr[detail::max_iovec_];
66 std::size_t total = 0;
67
68 for(;;)
69 {
70 auto [ec, bufs] = co_await source.pull(arr);
71 if(ec == cond::eof)
72 {
73 auto [eof_ec] = co_await sink.write_eof();
74 co_return {eof_ec, total};
75 }
76 if(ec)
77 co_return {ec, total};
78
79 auto [write_ec, n] = co_await sink.write(bufs);
80 total += n;
81 source.consume(n);
82 if(write_ec)
83 co_return {write_ec, total};
84 }
85 280 }
86
87 /** Transfer data from a BufferSource to a WriteStream.
88
89 This function pulls data from the source and writes it to the
90 stream until the source is exhausted or an error occurs. The
91 stream uses `write_some()` which may perform partial writes,
92 so this function loops until all pulled data is consumed.
93
94 Unlike the WriteSink overload, this function does not signal
95 EOF explicitly since WriteStream does not provide a write_eof
96 method. The transfer completes when the source is exhausted.
97
98 @tparam Src The source type, must satisfy @ref BufferSource.
99 @tparam Stream The stream type, must satisfy @ref WriteStream.
100
101 @param source The source to pull data from.
102 @param stream The stream to write data to.
103
104 @return A task that yields `(std::error_code, std::size_t)`.
105 On success, `ec` is default-constructed (no error) and `n` is
106 the total number of bytes transferred. On error, `ec` contains
107 the error code and `n` is the total number of bytes transferred
108 before the error.
109
110 @par Example
111 @code
112 task<void> transfer_body(BufferSource auto& source, WriteStream auto& stream)
113 {
114 auto [ec, n] = co_await push_to(source, stream);
115 if (ec)
116 {
117 // Handle error
118 }
119 // n bytes were transferred
120 }
121 @endcode
122
123 @see BufferSource, WriteStream, pull_from
124 */
125 template<BufferSource Src, WriteStream Stream>
126 requires (!WriteSink<Stream>)
127 io_task<std::size_t>
128
1/1
✓ Branch 1 taken 104 times.
104 push_to(Src& source, Stream& stream)
129 {
130 const_buffer arr[detail::max_iovec_];
131 std::size_t total = 0;
132
133 for(;;)
134 {
135 auto [ec, bufs] = co_await source.pull(arr);
136 if(ec == cond::eof)
137 co_return {{}, total};
138 if(ec)
139 co_return {ec, total};
140
141 auto [write_ec, n] = co_await stream.write_some(bufs);
142 if(write_ec)
143 co_return {write_ec, total};
144
145 total += n;
146 source.consume(n);
147 }
148 208 }
149
150 } // namespace capy
151 } // namespace boost
152
153 #endif
154