include/boost/capy/asio/stream.hpp

100.0% Lines (30/30) 100.0% List of functions (12/12)
stream.hpp
f(x) Functions (12)
Function Calls Lines Blocks
boost::capy::async_read_stream<boost::capy::noexcept_stream<boost::capy::test::read_stream>, boost::capy::thread_pool::executor_type>::async_read_stream(boost::capy::noexcept_stream<boost::capy::test::read_stream>, boost::capy::thread_pool::executor_type) :53 1x 100.0% 100.0% auto boost::capy::async_read_stream<boost::capy::noexcept_stream<boost::capy::test::read_stream>, boost::capy::thread_pool::executor_type>::async_read_some<boost::asio::mutable_buffer, boost::asio::detail::read_op<boost::capy::async_read_stream<boost::capy::noexcept_stream<boost::capy::test::read_stream>, boost::capy::thread_pool::executor_type>, boost::asio::mutable_buffer, boost::asio::mutable_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#2}> >(boost::asio::mutable_buffer&&, boost::asio::detail::read_op<boost::capy::async_read_stream<boost::capy::noexcept_stream<boost::capy::test::read_stream>, boost::capy::thread_pool::executor_type>, boost::asio::mutable_buffer, boost::asio::mutable_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#2}>&&) :88 2x 100.0% 90.0% boost::capy::async_read_stream<boost::capy::noexcept_stream<boost::capy::test::read_stream>, boost::capy::thread_pool::executor_type>::next_layer() :97 1x 100.0% 100.0% boost::capy::async_write_stream<boost::capy::noexcept_stream<boost::capy::test::write_stream>, boost::capy::thread_pool::executor_type>::async_write_stream(boost::capy::noexcept_stream<boost::capy::test::write_stream>, boost::capy::thread_pool::executor_type) :138 1x 100.0% 100.0% auto boost::capy::async_write_stream<boost::capy::noexcept_stream<boost::capy::test::write_stream>, boost::capy::thread_pool::executor_type>::async_write_some<boost::asio::const_buffer, boost::asio::detail::write_op<boost::capy::async_write_stream<boost::capy::noexcept_stream<boost::capy::test::write_stream>, boost::capy::thread_pool::executor_type>, boost::asio::const_buffer, boost::asio::const_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#1}> >(boost::asio::const_buffer&&, boost::asio::detail::write_op<boost::capy::async_write_stream<boost::capy::noexcept_stream<boost::capy::test::write_stream>, boost::capy::thread_pool::executor_type>, boost::asio::const_buffer, boost::asio::const_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#1}>&&) :174 1x 100.0% 90.0% boost::capy::async_write_stream<boost::capy::noexcept_stream<boost::capy::test::write_stream>, boost::capy::thread_pool::executor_type>::next_layer() :183 1x 100.0% 100.0% boost::capy::asio_read_stream<boost::asio::basic_readable_pipe<boost::asio::any_io_executor> >::asio_read_stream(boost::asio::basic_readable_pipe<boost::asio::any_io_executor>) :330 1x 100.0% 100.0% boost::capy::asio_read_stream<boost::asio::basic_readable_pipe<boost::asio::any_io_executor> >::asio_read_stream(boost::capy::asio_read_stream<boost::asio::basic_readable_pipe<boost::asio::any_io_executor> >&&) :338 1x 100.0% 100.0% auto boost::capy::asio_read_stream<boost::asio::basic_readable_pipe<boost::asio::any_io_executor> >::read_some<std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> >(std::span<boost::capy::mutable_buffer const, 18446744073709551615ul>) :350 1x 100.0% 100.0% boost::capy::asio_write_stream<boost::asio::basic_writable_pipe<boost::asio::any_io_executor> >::asio_write_stream(boost::asio::basic_writable_pipe<boost::asio::any_io_executor>) :394 1x 100.0% 100.0% boost::capy::asio_write_stream<boost::asio::basic_writable_pipe<boost::asio::any_io_executor> >::asio_write_stream(boost::capy::asio_write_stream<boost::asio::basic_writable_pipe<boost::asio::any_io_executor> >&&) :402 1x 100.0% 100.0% auto boost::capy::asio_write_stream<boost::asio::basic_writable_pipe<boost::asio::any_io_executor> >::write_some<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >(std::span<boost::capy::const_buffer const, 18446744073709551615ul>) :414 1x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.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 #ifndef BOOST_CAPY_ASIO_STREAM_HPP
10 #define BOOST_CAPY_ASIO_STREAM_HPP
11
12 #include <boost/capy/asio/as_io_awaitable.hpp>
13 #include <boost/capy/asio/buffers.hpp>
14 #include <boost/capy/asio/executor_adapter.hpp>
15 #include <boost/capy/asio/spawn.hpp>
16 #include <boost/capy/concept/stream.hpp>
17 #include <boost/capy/concept/executor.hpp>
18 #include <boost/capy/ex/any_executor.hpp>
19 #include <boost/capy/io/any_stream.hpp>
20 #include <boost/capy/io/any_read_stream.hpp>
21 #include <boost/capy/io/any_write_stream.hpp>
22
23 namespace boost::capy
24 {
25
26 /** Wraps a capy ReadStream for use with Asio async operations.
27
28 Adapts a capy `ReadStream` to provide Asio-style `async_read_some`
29 operations with completion token support.
30
31 @tparam Stream The underlying capy ReadStream type
32 @tparam Exec The executor type
33
34 @par Example
35 @code
36 capy::any_read_stream stream = ...;
37 auto exec = capy::wrap_asio_executor(io.get_executor());
38 capy::async_read_stream reader(std::move(stream), exec);
39
40 auto [ec, n] = co_await reader.async_read_some(buffer, capy::as_io_awaitable);
41 @endcode
42 */
43 template<ReadStream Stream = any_stream, Executor Exec = any_executor>
44 struct async_read_stream
45 {
46 using executor_type = asio_executor_adapter<Exec>;
47 using next_layer_type = Stream;
48
49 /// Default constructor.
50 async_read_stream() = default;
51
52 /// Construct from a stream and executor.
53 1x async_read_stream(Stream stream, Exec executor)
54 noexcept(std::is_nothrow_move_constructible_v<Stream> &&
55 std::is_nothrow_move_constructible_v<Exec>)
56 1x : stream_(std::move(stream))
57 1x , executor_(std::move(executor))
58 {
59 1x }
60
61 async_read_stream(const async_read_stream&)
62 noexcept(std::is_nothrow_copy_constructible_v<Stream> &&
63 std::is_nothrow_copy_constructible_v<Exec>) = default;
64 async_read_stream(async_read_stream&&)
65 noexcept(std::is_nothrow_move_constructible_v<Stream> &&
66 std::is_nothrow_move_constructible_v<Exec>) = default;
67 async_read_stream& operator=(const async_read_stream&)
68 noexcept(std::is_nothrow_copy_assignable_v<Stream> &&
69 std::is_nothrow_copy_assignable_v<Exec>) = default;
70 async_read_stream& operator=(async_read_stream&&)
71 noexcept(std::is_nothrow_move_assignable_v<Stream> &&
72 std::is_nothrow_move_assignable_v<Exec>) = default;
73
74 /// Returns the executor adapter for Asio compatibility.
75 executor_type get_executor() const { return executor_; }
76
77 /// Initiates an async read, returning a spawn handle.
78 template<typename Buffer>
79 auto async_read_some(Buffer && buffer)
80 {
81 return asio_spawn(
82 executor_,
83 stream_.read_some(as_asio_buffer_sequence(std::forward<Buffer>(buffer))));
84 }
85
86 /// Initiates an async read with a completion token.
87 template<typename Buffer, typename CompletionToken>
88 2x auto async_read_some(Buffer && buffer, CompletionToken && token)
89 {
90 4x return asio_spawn(
91 executor_,
92 2x stream_.read_some(as_asio_buffer_sequence(std::forward<Buffer>(buffer))),
93 2x std::forward<CompletionToken>(token));
94 }
95
96 /// Returns a reference inter to the underlying stream.
97 1x next_layer_type& next_layer() { return stream_; }
98 /// Returns a const reference to the underlying stream.
99 const next_layer_type& next_layer() const { return stream_; }
100
101 private:
102 Stream stream_;
103 Exec executor_;
104 };
105
106 // Deduction guides
107 template<ReadStream Stream, Executor Exec>
108 async_read_stream(Stream, Exec) -> async_read_stream<Stream, Exec>;
109
110
111 /** Wraps a capy WriteStream for use with Asio async operations.
112
113 Adapts a capy `WriteStream` to provide Asio-style `async_write_some`
114 operations with completion token support.
115
116 @tparam Stream The underlying capy WriteStream type
117 @tparam Exec The executor type
118
119 @par Example
120 @code
121 capy::any_write_stream stream = ...;
122 auto exec = capy::wrap_asio_executor(io.get_executor());
123 capy::async_write_stream writer(std::move(stream), exec);
124
125 auto [ec, n] = co_await writer.async_write_some(buffer, capy::as_io_awaitable);
126 @endcode
127 */
128 template<WriteStream Stream = any_stream, Executor Exec = any_executor>
129 struct async_write_stream
130 {
131 using executor_type = asio_executor_adapter<Exec>;
132 using next_layer_type = Stream;
133
134 /// Default constructor.
135 async_write_stream() = default;
136
137 /// Construct from a stream and executor.
138 1x async_write_stream(Stream stream, Exec executor)
139 noexcept(std::is_nothrow_move_constructible_v<Stream> &&
140 std::is_nothrow_move_constructible_v<Exec>)
141 1x : stream_(std::move(stream))
142 1x , executor_(std::move(executor))
143 {
144 1x }
145
146 async_write_stream(const async_write_stream&)
147 noexcept(std::is_nothrow_copy_constructible_v<Stream> &&
148 std::is_nothrow_copy_constructible_v<Exec>) = default;
149 async_write_stream(async_write_stream&&)
150 noexcept(std::is_nothrow_move_constructible_v<Stream> &&
151 std::is_nothrow_move_constructible_v<Exec>) = default;
152 async_write_stream& operator=(const async_write_stream&)
153 noexcept(std::is_nothrow_copy_assignable_v<Stream> &&
154 std::is_nothrow_copy_assignable_v<Exec>) = default;
155 async_write_stream& operator=(async_write_stream&&)
156 noexcept(std::is_nothrow_move_assignable_v<Stream> &&
157 std::is_nothrow_move_assignable_v<Exec>) = default;
158
159 /// Returns the executor adapter for Asio compatibility.
160 executor_type get_executor() const { return executor_; }
161
162 /// Initiates an async write, returning a spawn handle.
163 template<typename Buffer>
164 auto async_write_some(Buffer && buffer)
165 {
166
167 return asio_spawn(
168 executor_,
169 stream_.write_some(as_asio_buffer_sequence(std::forward<Buffer>(buffer))));
170 }
171
172 /// Initiates an async write with a completion token.
173 template<typename Buffer, typename CompletionToken>
174 1x auto async_write_some(Buffer && buffer, CompletionToken && token)
175 {
176 2x return asio_spawn(
177 executor_,
178 1x stream_.write_some(as_asio_buffer_sequence(std::forward<Buffer>(buffer))),
179 1x std::forward<CompletionToken>(token));
180 }
181
182 /// Returns a reference to the underlying stream.
183 1x next_layer_type& next_layer() { return stream_; }
184 /// Returns a const reference to the underlying stream.
185 const next_layer_type& next_layer() const { return stream_; }
186
187 private:
188 Stream stream_;
189 Exec executor_;
190 };
191
192 // Deduction guides
193 template<WriteStream Stream, Executor Exec>
194 async_write_stream(Stream, Exec) -> async_write_stream<Stream, Exec>;
195
196
197 /** Wraps a capy Stream for use with Asio async operations.
198
199 Adapts a capy `Stream` (supporting both read and write) to provide
200 Asio-style `async_read_some` and `async_write_some` operations
201 with completion token support.
202
203 @tparam Stream The underlying capy Stream type
204 @tparam Exec The executor type
205
206 @par Example
207 @code
208 capy::any_stream stream = ...;
209 auto exec = capy::wrap_asio_executor(io.get_executor());
210 capy::async_stream sock(std::move(stream), exec);
211
212 // Read
213 auto [ec1, n1] = co_await sock.async_read_some(read_buf, capy::as_io_awaitable);
214
215 // Write
216 auto [ec2, n2] = co_await sock.async_write_some(write_buf, capy::as_io_awaitable);
217 @endcode
218 */
219 template<Stream Stream = any_stream, Executor Exec = any_executor>
220 struct async_stream
221 {
222 using executor_type = asio_executor_adapter<Exec>;
223 using next_layer_type = Stream;
224
225 /// Default constructor.
226 async_stream() = default;
227
228 /// Construct from a stream and executor.
229 async_stream(Stream stream, Exec executor)
230 noexcept(std::is_nothrow_move_constructible_v<Stream> &&
231 std::is_nothrow_move_constructible_v<Exec>)
232 : stream_(std::move(stream))
233 , executor_(std::move(executor))
234 {
235 }
236
237 async_stream(const async_stream&)
238 noexcept(std::is_nothrow_copy_constructible_v<Stream> &&
239 std::is_nothrow_copy_constructible_v<Exec>) = default;
240 async_stream(async_stream&&)
241 noexcept(std::is_nothrow_move_constructible_v<Stream> &&
242 std::is_nothrow_move_constructible_v<Exec>) = default;
243 async_stream& operator=(const async_stream&)
244 noexcept(std::is_nothrow_copy_assignable_v<Stream> &&
245 std::is_nothrow_copy_assignable_v<Exec>) = default;
246 async_stream& operator=(async_stream&&)
247 noexcept(std::is_nothrow_move_assignable_v<Stream> &&
248 std::is_nothrow_move_assignable_v<Exec>) = default;
249
250 /// Returns the executor adapter for Asio compatibility.
251 executor_type get_executor() const { return executor_; }
252
253 /// Initiates an async read, returning a spawn handle.
254 template<typename Buffer>
255 auto async_read_some(Buffer && buffer)
256 {
257 return asio_spawn(
258 executor_,
259 stream_.read_some(as_asio_buffer_sequence(std::forward<Buffer>(buffer))));
260 }
261
262 /// Initiates an async read with a completion token.
263 template<typename Buffer, typename CompletionToken>
264 auto async_read_some(Buffer && buffer, CompletionToken && token)
265 {
266 return asio_spawn(
267 executor_,
268 stream_.read_some(as_asio_buffer_sequence(std::forward<Buffer>(buffer))),
269 std::forward<CompletionToken>(token));
270 }
271
272 /// Initiates an async write, returning a spawn handle.
273 template<typename Buffer>
274 auto async_write_some(Buffer && buffer)
275 {
276 return asio_spawn(
277 executor_,
278 stream_.write_some(as_asio_buffer_sequence(std::forward<Buffer>(buffer))));
279 }
280
281 /// Initiates an async write with a completion token.
282 template<typename Buffer, typename CompletionToken>
283 auto async_write_some(Buffer && buffer, CompletionToken && token)
284 {
285 return asio_spawn(
286 executor_,
287 stream_.write_some(as_asio_buffer_sequence(std::forward<Buffer>(buffer))),
288 std::forward<CompletionToken>(token));
289 }
290
291 /// Returns a reference to the underlying stream.
292 next_layer_type& next_layer() { return stream_; }
293 /// Returns a const reference to the underlying stream.
294 const next_layer_type& next_layer() const { return stream_; }
295
296 private:
297 Stream stream_;
298 Exec executor_;
299 };
300
301 // Deduction guides
302 template<Stream StreamT, Executor Exec>
303 async_stream(StreamT, Exec) -> async_stream<StreamT, Exec>;
304
305 /** Wraps an Asio AsyncReadStream for use with capy's ReadStream concept.
306
307 Adapts an Asio `AsyncReadStream` to provide capy-style `read_some`
308 operations that return an IoAwaitable.
309
310 @tparam AsyncReadStream The underlying Asio AsyncReadStream type
311
312 @par Example
313 @code
314 boost::asio::ip::tcp::socket socket(io);
315 capy::asio_read_stream reader(std::move(socket));
316
317 auto result = co_await reader.read_some(buffer);
318 @endcode
319 */
320 template<typename AsyncReadStream>
321 struct asio_read_stream
322 {
323 using executor_type = typename AsyncReadStream::executor_type;
324 using next_layer_type = AsyncReadStream;
325
326 /// Default constructor.
327 asio_read_stream() = default;
328
329 /// Construct from an Asio stream.
330 1x explicit asio_read_stream(AsyncReadStream stream)
331 noexcept(std::is_nothrow_move_constructible_v<AsyncReadStream>)
332 1x : stream_(std::move(stream))
333 {
334 1x }
335
336 asio_read_stream(const asio_read_stream&)
337 noexcept(std::is_nothrow_copy_constructible_v<AsyncReadStream>) = default;
338 1x asio_read_stream(asio_read_stream&&)
339 noexcept(std::is_nothrow_move_constructible_v<AsyncReadStream>) = default;
340 asio_read_stream& operator=(const asio_read_stream&)
341 noexcept(std::is_nothrow_copy_assignable_v<AsyncReadStream>) = default;
342 asio_read_stream& operator=(asio_read_stream&&)
343 noexcept(std::is_nothrow_move_assignable_v<AsyncReadStream>) = default;
344
345 /// Returns the executor from the underlying stream.
346 executor_type get_executor() const { return stream_.get_executor(); }
347
348 /// Initiates an async read, returning an IoAwaitable.
349 template<MutableBufferSequence Seq>
350 1x auto read_some(Seq buffers)
351 {
352 2x return stream_.async_read_some(as_asio_buffer_sequence(buffers), as_io_awaitable);
353 }
354
355 /// Returns a reference to the underlying stream.
356 next_layer_type& next_layer() { return stream_; }
357 /// Returns a const reference to the underlying stream.
358 const next_layer_type& next_layer() const { return stream_; }
359
360 private:
361 AsyncReadStream stream_;
362 };
363
364 // Deduction guide
365 template<typename AsyncReadStream>
366 asio_read_stream(AsyncReadStream) -> asio_read_stream<AsyncReadStream>;
367
368
369 /** Wraps an Asio AsyncWriteStream for use with capy's WriteStream concept.
370
371 Adapts an Asio `AsyncWriteStream` to provide capy-style `write_some`
372 operations that return an IoAwaitable.
373
374 @tparam AsyncWriteStream The underlying Asio AsyncWriteStream type
375
376 @par Example
377 @code
378 boost::asio::ip::tcp::socket socket(io);
379 capy::asio_write_stream writer(std::move(socket));
380
381 auto result = co_await writer.write_some(buffer);
382 @endcode
383 */
384 template<typename AsyncWriteStream>
385 struct asio_write_stream
386 {
387 using executor_type = typename AsyncWriteStream::executor_type;
388 using next_layer_type = AsyncWriteStream;
389
390 /// Default constructor.
391 asio_write_stream() = default;
392
393 /// Construct from an Asio stream.
394 1x explicit asio_write_stream(AsyncWriteStream stream)
395 noexcept(std::is_nothrow_move_constructible_v<AsyncWriteStream>)
396 1x : stream_(std::move(stream))
397 {
398 1x }
399
400 asio_write_stream(const asio_write_stream&)
401 noexcept(std::is_nothrow_copy_constructible_v<AsyncWriteStream>) = default;
402 1x asio_write_stream(asio_write_stream&&)
403 noexcept(std::is_nothrow_move_constructible_v<AsyncWriteStream>) = default;
404 asio_write_stream& operator=(const asio_write_stream&)
405 noexcept(std::is_nothrow_copy_assignable_v<AsyncWriteStream>) = default;
406 asio_write_stream& operator=(asio_write_stream&&)
407 noexcept(std::is_nothrow_move_assignable_v<AsyncWriteStream>) = default;
408
409 /// Returns the executor from the underlying stream.
410 executor_type get_executor() const { return stream_.get_executor(); }
411
412 /// Initiates an async write, returning an IoAwaitable.
413 template<ConstBufferSequence Seq>
414 1x auto write_some(Seq buffers)
415 {
416 2x return stream_.async_write_some(as_asio_buffer_sequence(buffers), as_io_awaitable);
417 }
418
419 /// Returns a reference to the underlying stream.
420 next_layer_type& next_layer() { return stream_; }
421 /// Returns a const reference to the underlying stream.
422 const next_layer_type& next_layer() const { return stream_; }
423
424 private:
425 AsyncWriteStream stream_;
426 };
427
428 // Deduction guide
429 template<typename AsyncWriteStream>
430 asio_write_stream(AsyncWriteStream) -> asio_write_stream<AsyncWriteStream>;
431
432
433 /** Wraps an Asio AsyncStream for use with capy's Stream concept.
434
435 Adapts an Asio stream (supporting both read and write) to provide
436 capy-style `read_some` and `write_some` operations that return
437 an IoAwaitable.
438
439 @tparam AsyncStream The underlying Asio stream type
440
441 @par Example
442 @code
443 boost::asio::ip::tcp::socket socket(io);
444 capy::asio_stream stream(std::move(socket));
445
446 // Read
447 auto read_result = co_await stream.read_some(read_buf);
448
449 // Write
450 auto write_result = co_await stream.write_some(write_buf);
451 @endcode
452 */
453 template<typename AsyncStream>
454 struct asio_stream
455 {
456 using executor_type = typename AsyncStream::executor_type;
457 using next_layer_type = AsyncStream;
458
459 /// Default constructor.
460 asio_stream() = default;
461
462 /// Construct from an Asio stream.
463 explicit asio_stream(AsyncStream stream)
464 noexcept(std::is_nothrow_move_constructible_v<AsyncStream>)
465 : stream_(std::move(stream))
466 {
467 }
468
469 asio_stream(const asio_stream&)
470 noexcept(std::is_nothrow_copy_constructible_v<AsyncStream>) = default;
471 asio_stream(asio_stream&&)
472 noexcept(std::is_nothrow_move_constructible_v<AsyncStream>) = default;
473 asio_stream& operator=(const asio_stream&)
474 noexcept(std::is_nothrow_copy_assignable_v<AsyncStream>) = default;
475 asio_stream& operator=(asio_stream&&)
476 noexcept(std::is_nothrow_move_assignable_v<AsyncStream>) = default;
477
478 /// Returns the executor from the underlying stream.
479 executor_type get_executor() const { return stream_.get_executor(); }
480
481 /// Initiates an async read, returning an IoAwaitable.
482 template<MutableBufferSequence Seq>
483 auto read_some(Seq buffers)
484 {
485 return stream_.async_read_some(as_asio_buffer_sequence(buffers), as_io_awaitable);
486 }
487
488 /// Initiates an async write, returning an IoAwaitable.
489 template<ConstBufferSequence Seq>
490 auto write_some(Seq buffers)
491 {
492 return stream_.async_write_some(as_asio_buffer_sequence(buffers), as_io_awaitable);
493 }
494
495 /// Returns a reference to the underlying stream.
496 next_layer_type& next_layer() { return stream_; }
497 /// Returns a const reference to the underlying stream.
498 const next_layer_type& next_layer() const { return stream_; }
499
500 private:
501 AsyncStream stream_;
502 };
503
504 // Deduction guide
505 template<typename AsyncStream>
506 asio_stream(AsyncStream) -> asio_stream<AsyncStream>;
507
508 }
509
510 #endif //BOOST_CAPY_ASIO_STREAM_HPP
511
512