boost::capy::ReadStream

Concept for types providing awaitable read operations.

Synopsis

template<typename T>
concept ReadStream = requires(T& stream, mutable_buffer_archetype buffers)
    {
        { stream.read_some(buffers) } ‐> IoAwaitable;
        requires awaitable_decomposes_to<
            decltype(stream.read_some(buffers)),
            std::error_code, std::size_t>;
    };

Description

A type satisfies ReadStream if it provides a read_some member function template that accepts any MutableBufferSequence and is an IoAwaitable yielding (error_code,std::size_t).

Syntactic Requirements

  • `T` must provide a `read_some` member function template accepting any MutableBufferSequence

  • The return type of `read_some` must satisfy IoAwaitable

  • The awaitable's result must decompose to `(error_code,std::size_t)` via structured bindings

Semantic Requirements

If buffer_size( buffers ) > 0, the operation reads one or more bytes from the stream into the buffer sequence:

  • On success: `!ec`, and `n` is the number of bytes read (at least 1).

  • On error: `ec`, and `n` is 0.

  • On end‐of‐file: `ec == cond::eof`, and `n` is 0.

If buffer_empty( buffers ) is true, the operation completes immediately. !ec, and n is 0.

Buffers in the sequence are filled completely before proceeding to the next buffer.

Design Rationale

The requirement that n is 0 whenever ec is set follows from a consistency constraint with the empty‐buffer rule. See the ReadStream design document for a complete derivation.

Buffer Lifetime

The caller must ensure that the memory referenced by buffers remains valid until the co_await expression returns.

Conforming Signatures

// Templated for any MutableBufferSequence
template< MutableBufferSequence MB >
IoAwaitable auto read_some( MB const& buffers );

template< MutableBufferSequence MB >
IoAwaitable auto read_some( MB buffers );  // by-value also permitted

Coroutine Buffer Lifetime: When implementing coroutine member functions, prefer accepting buffer sequences by value rather than by reference. Buffer sequences passed by reference may become dangling if the caller's stack frame is destroyed before the coroutine completes. Passing by value ensures the buffer sequence is copied into the coroutine frame and remains valid across suspension points.

Example

template< ReadStream Stream >
task<> read_all( Stream& s, char* buf, std::size_t size )
{
    std::size_t total = 0;
    while( total < size )
    {
        auto [ec, n] = co_await s.read_some(
            mutable_buffer( buf + total, size - total ) );
        if( ec )
            co_return;
        total += n;
    }
}

See Also

IoAwaitable, MutableBufferSequence, awaitable_decomposes_to

Created with MrDocs