LCOV - code coverage report
Current view: top level - capy/asio - stream.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 30 30
Test Date: 2026-05-01 02:54:45 Functions: 100.0 % 12 12

           TLA  Line data    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 HIT           1 :   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               1 :       : stream_(std::move(stream))
      57               1 :       , executor_(std::move(executor))
      58                 :   {
      59               1 :   }
      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               2 :   auto async_read_some(Buffer && buffer, CompletionToken && token)
      89                 :   {
      90               4 :     return asio_spawn(
      91                 :         executor_,
      92               2 :         stream_.read_some(as_asio_buffer_sequence(std::forward<Buffer>(buffer))),
      93               2 :         std::forward<CompletionToken>(token));
      94                 :   }
      95                 : 
      96                 :   /// Returns a reference inter to the underlying stream.
      97               1 :         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               1 :   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               1 :       : stream_(std::move(stream))
     142               1 :       , executor_(std::move(executor))
     143                 :   {
     144               1 :   }
     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               1 :   auto async_write_some(Buffer && buffer, CompletionToken && token)
     175                 :   {
     176               2 :     return asio_spawn(
     177                 :         executor_,
     178               1 :         stream_.write_some(as_asio_buffer_sequence(std::forward<Buffer>(buffer))),
     179               1 :         std::forward<CompletionToken>(token));
     180                 :   }
     181                 : 
     182                 :   /// Returns a reference to the underlying stream.
     183               1 :         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               1 :   explicit asio_read_stream(AsyncReadStream stream)
     331                 :       noexcept(std::is_nothrow_move_constructible_v<AsyncReadStream>)
     332               1 :       : stream_(std::move(stream))
     333                 :   {
     334               1 :   }
     335                 : 
     336                 :   asio_read_stream(const asio_read_stream&)
     337                 :       noexcept(std::is_nothrow_copy_constructible_v<AsyncReadStream>) = default;
     338               1 :   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               1 :   auto read_some(Seq buffers)
     351                 :   {
     352               2 :     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               1 :   explicit asio_write_stream(AsyncWriteStream stream)
     395                 :       noexcept(std::is_nothrow_move_constructible_v<AsyncWriteStream>)
     396               1 :       : stream_(std::move(stream))
     397                 :   {
     398               1 :   }
     399                 : 
     400                 :   asio_write_stream(const asio_write_stream&)
     401                 :       noexcept(std::is_nothrow_copy_constructible_v<AsyncWriteStream>) = default;
     402               1 :   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               1 :   auto write_some(Seq buffers)
     415                 :   {
     416               2 :     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                 : 
        

Generated by: LCOV version 2.3