Line data Source code
1 : // 2 : // Copyright (c) 2023 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/http_proto 8 : // 9 : 10 : #ifndef BOOST_HTTP_PROTO_SINK_HPP 11 : #define BOOST_HTTP_PROTO_SINK_HPP 12 : 13 : #include <boost/http_proto/detail/config.hpp> 14 : #include <boost/http_proto/buffered_base.hpp> 15 : #include <boost/buffers/const_buffer_span.hpp> 16 : #include <boost/buffers/type_traits.hpp> 17 : #include <boost/system/error_code.hpp> 18 : #include <cstddef> 19 : #include <type_traits> 20 : 21 : namespace boost { 22 : namespace http_proto { 23 : 24 : /** An algorithm for consuming buffers of data. 25 : 26 : This interface abstracts the consumption of 27 : a finite stream of data, passed by reading 28 : from caller-provided buffers until there 29 : is no more input data. 30 : 31 : @par Thread Safety 32 : Non-const member functions may not be 33 : called concurrently on the same instance. 34 : */ 35 : struct BOOST_HTTP_PROTO_DECL 36 : sink 37 : : buffered_base 38 : { 39 : /** The results of consuming data. 40 : */ 41 : struct results 42 : { 43 : /** The error, if any occurred. 44 : */ 45 : system::error_code ec; 46 : 47 : /** The number of bytes consumed in the input. 48 : */ 49 : std::size_t bytes = 0; 50 : 51 : /** Accumulate results. 52 : */ 53 : results& 54 : operator+=( 55 : results const& rv) noexcept; 56 : }; 57 : 58 : /** Consume data. 59 : 60 : This function attempts to write to the 61 : sink, by transferring data from the given 62 : constant buffer sequence. 63 : The return value indicates the number of 64 : bytes consumed from the buffers and the 65 : error if any occurred. 66 : 67 : @par Preconditions 68 : @li @ref init was called, and 69 : @li This is the first call to @ref write, 70 : or the last value of `more` was `true`. 71 : 72 : @par Postconditions 73 : @code 74 : rv.ec.failed() == true || rv.bytes == buffer_size(bs) 75 : @endcode 76 : 77 : @return The result of the operation. 78 : 79 : @param bs The buffers to use. 80 : Each buffer in the sequence will be 81 : consumed completely before the next 82 : buffer is accessed. 83 : 84 : @param more `true` if there will be one 85 : or more subsequent calls to @ref write. 86 : */ 87 : template<class ConstBufferSequence> 88 : results 89 9 : write( 90 : ConstBufferSequence const& bs, 91 : bool more) 92 : { 93 : static_assert( 94 : buffers::is_const_buffer_sequence< 95 : ConstBufferSequence>::value, 96 : "Type requirements not met"); 97 : 98 9 : return write_impl(bs, more); 99 : } 100 : 101 : #ifdef BOOST_HTTP_PROTO_DOCS 102 : protected: 103 : #else 104 : private: 105 : #endif 106 : /** Derived class override. 107 : 108 : This pure virtual function is called by 109 : the implementation and must be overriden. 110 : The callee should attempt to consume data 111 : from the given constant buffer. 112 : The return value must be set to indicate 113 : the number of bytes consumed from the 114 : buffers, and the error if any occurred. 115 : 116 : @par Preconditions 117 : @li @ref init was called, and 118 : @li This is the first call to @ref on_write, 119 : or the last value of `more` was `true`. 120 : 121 : @return The result of the operation. 122 : 123 : @param b The buffer to use. 124 : If `more` is true then the results 125 : must indicate that the buffer was 126 : consumed completely, or that an error 127 : occurred. 128 : 129 : @param more `true` if there will be one 130 : or more subsequent calls to @ref write. 131 : */ 132 : virtual 133 : results 134 : on_write( 135 : buffers::const_buffer b, 136 : bool more) = 0; 137 : 138 : /** Derived class override. 139 : 140 : This pure virtual function is called by 141 : the implementation and must be overriden. 142 : The callee should attempt to consume data 143 : from the given constant buffer sequence. 144 : The return value must be set to indicate 145 : the number of bytes consumed from the 146 : buffers, and the error if any occurred. 147 : 148 : @par Preconditions 149 : @li @ref init was called, and 150 : @li This is the first call to @ref on_write, 151 : or the last value of `more` was `true`. 152 : 153 : @return The result of the operation. 154 : 155 : @param bs The buffer sequence to use. 156 : Each buffer in the sequence must 157 : be completely consumed before data 158 : is consumed from the next buffer. 159 : If `more` is true then the results 160 : must indicate that the buffer was 161 : consumed completely, or that an error 162 : occurred. 163 : 164 : @param more `true` if there will be one 165 : or more subsequent calls to @ref write. 166 : */ 167 : virtual 168 : results 169 : on_write( 170 : buffers::const_buffer_span bs, 171 : bool more); 172 : 173 : private: 174 : results 175 2 : write_impl( 176 : buffers::const_buffer const& b, 177 : bool more) 178 : { 179 2 : return on_write(b, more); 180 : } 181 : 182 : results 183 2 : write_impl( 184 : buffers::mutable_buffer const& b, 185 : bool more) 186 : { 187 2 : return on_write(b, more); 188 : } 189 : 190 : results 191 5 : write_impl( 192 : buffers::const_buffer_span const& bs, 193 : bool more) 194 : { 195 5 : return on_write(bs, more); 196 : } 197 : 198 : template<class T> 199 : results 200 : write_impl(T const&, bool); 201 : }; 202 : 203 : //------------------------------------------------ 204 : 205 : /** Metafunction which determines if T is a sink 206 : 207 : @see 208 : @ref sink. 209 : */ 210 : #ifdef BOOST_HTTP_PROTO_DOCS 211 : template<class T> 212 : using is_sink = __see_below__; 213 : #else 214 : template<class T> 215 : using is_sink = 216 : std::is_convertible< 217 : typename std::decay<T>::type*, 218 : sink*>; 219 : #endif 220 : 221 : } // http_proto 222 : } // boost 223 : 224 : #include <boost/http_proto/impl/sink.hpp> 225 : 226 : #endif