1  
//
1  
//
2  
// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
2  
// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/capy
7  
// Official repository: https://github.com/cppalliance/capy
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_CAPY_WRITE_HPP
10  
#ifndef BOOST_CAPY_WRITE_HPP
11  
#define BOOST_CAPY_WRITE_HPP
11  
#define BOOST_CAPY_WRITE_HPP
12  

12  

13  
#include <boost/capy/detail/config.hpp>
13  
#include <boost/capy/detail/config.hpp>
14 -
#include <boost/capy/io_result.hpp>
14 +
#include <boost/capy/io_task.hpp>
15 -
#include <boost/capy/task.hpp>
 
16  
#include <boost/capy/buffers.hpp>
15  
#include <boost/capy/buffers.hpp>
17  
#include <boost/capy/buffers/consuming_buffers.hpp>
16  
#include <boost/capy/buffers/consuming_buffers.hpp>
18  
#include <boost/capy/concept/write_stream.hpp>
17  
#include <boost/capy/concept/write_stream.hpp>
19  
#include <system_error>
18  
#include <system_error>
20  

19  

21  
#include <cstddef>
20  
#include <cstddef>
22  

21  

23  
namespace boost {
22  
namespace boost {
24  
namespace capy {
23  
namespace capy {
25  

24  

26  
/** Asynchronously write the entire buffer sequence.
25  
/** Asynchronously write the entire buffer sequence.
27  

26  

28  
    Writes data to the stream by calling `write_some` repeatedly
27  
    Writes data to the stream by calling `write_some` repeatedly
29  
    until the entire buffer sequence is written or an error occurs.
28  
    until the entire buffer sequence is written or an error occurs.
30  

29  

31  
    @li The operation completes when:
30  
    @li The operation completes when:
32  
    @li The entire buffer sequence has been written
31  
    @li The entire buffer sequence has been written
33  
    @li An error occurs
32  
    @li An error occurs
34  
    @li The operation is cancelled
33  
    @li The operation is cancelled
35  

34  

36  
    @par Cancellation
35  
    @par Cancellation
37  
    Supports cancellation via `stop_token` propagated through the
36  
    Supports cancellation via `stop_token` propagated through the
38  
    IoAwaitable protocol. When cancelled, returns with `cond::canceled`.
37  
    IoAwaitable protocol. When cancelled, returns with `cond::canceled`.
39  

38  

40  
    @param stream The stream to write to. The caller retains ownership.
39  
    @param stream The stream to write to. The caller retains ownership.
41  
    @param buffers The buffer sequence to write. The caller retains
40  
    @param buffers The buffer sequence to write. The caller retains
42  
        ownership and must ensure validity until the operation completes.
41  
        ownership and must ensure validity until the operation completes.
43  

42  

44  
    @return An awaitable yielding `(error_code, std::size_t)`.
43  
    @return An awaitable yielding `(error_code, std::size_t)`.
45  
        On success, `n` equals `buffer_size(buffers)`. On error,
44  
        On success, `n` equals `buffer_size(buffers)`. On error,
46  
        `n` is the number of bytes written before the error. Compare
45  
        `n` is the number of bytes written before the error. Compare
47  
        error codes to conditions:
46  
        error codes to conditions:
48  
        @li `cond::canceled` - Operation was cancelled
47  
        @li `cond::canceled` - Operation was cancelled
49  
        @li `std::errc::broken_pipe` - Peer closed connection
48  
        @li `std::errc::broken_pipe` - Peer closed connection
50  

49  

51  
    @par Example
50  
    @par Example
52  

51  

53  
    @code
52  
    @code
54  
    task<> send_response( WriteStream auto& stream, std::string_view body )
53  
    task<> send_response( WriteStream auto& stream, std::string_view body )
55  
    {
54  
    {
56  
        auto [ec, n] = co_await write( stream, make_buffer( body ) );
55  
        auto [ec, n] = co_await write( stream, make_buffer( body ) );
57 -
        if( ec.failed() )
56 +
        if( ec )
58  
            detail::throw_system_error( ec );
57  
            detail::throw_system_error( ec );
59  
        // All bytes written successfully
58  
        // All bytes written successfully
60  
    }
59  
    }
61  
    @endcode
60  
    @endcode
62  

61  

63  
    @see write_some, WriteStream, ConstBufferSequence
62  
    @see write_some, WriteStream, ConstBufferSequence
64  
*/
63  
*/
65  
auto
64  
auto
66  
write(
65  
write(
67  
    WriteStream auto& stream,
66  
    WriteStream auto& stream,
68  
    ConstBufferSequence auto const& buffers) ->
67  
    ConstBufferSequence auto const& buffers) ->
69 -
        task<io_result<std::size_t>>
68 +
        io_task<std::size_t>
70  
{
69  
{
71  
    consuming_buffers consuming(buffers);
70  
    consuming_buffers consuming(buffers);
72  
    std::size_t const total_size = buffer_size(buffers);
71  
    std::size_t const total_size = buffer_size(buffers);
73  
    std::size_t total_written = 0;
72  
    std::size_t total_written = 0;
74  

73  

75  
    while(total_written < total_size)
74  
    while(total_written < total_size)
76  
    {
75  
    {
77  
        auto [ec, n] = co_await stream.write_some(consuming);
76  
        auto [ec, n] = co_await stream.write_some(consuming);
78  
        if(ec)
77  
        if(ec)
79  
            co_return {ec, total_written};
78  
            co_return {ec, total_written};
80  
        consuming.consume(n);
79  
        consuming.consume(n);
81  
        total_written += n;
80  
        total_written += n;
82  
    }
81  
    }
83  

82  

84  
    co_return {{}, total_written};
83  
    co_return {{}, total_written};
85  
}
84  
}
86  

85  

87  
} // namespace capy
86  
} // namespace capy
88  
} // namespace boost
87  
} // namespace boost
89  

88  

90  
#endif
89  
#endif