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_SYMBOL_VISIBLE 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 : BOOST_HTTP_PROTO_DECL 133 : virtual 134 : results 135 : on_write( 136 : buffers::const_buffer b, 137 : bool more) = 0; 138 : 139 : /** Derived class override. 140 : 141 : This pure virtual function is called by 142 : the implementation and must be overriden. 143 : The callee should attempt to consume data 144 : from the given constant buffer sequence. 145 : The return value must be set to indicate 146 : the number of bytes consumed from the 147 : buffers, and the error if any occurred. 148 : 149 : @par Preconditions 150 : @li @ref init was called, and 151 : @li This is the first call to @ref on_write, 152 : or the last value of `more` was `true`. 153 : 154 : @return The result of the operation. 155 : 156 : @param bs The buffer sequence to use. 157 : Each buffer in the sequence must 158 : be completely consumed before data 159 : is consumed from the next buffer. 160 : If `more` is true then the results 161 : must indicate that the buffer was 162 : consumed completely, or that an error 163 : occurred. 164 : 165 : @param more `true` if there will be one 166 : or more subsequent calls to @ref write. 167 : */ 168 : BOOST_HTTP_PROTO_DECL 169 : virtual 170 : results 171 : on_write( 172 : buffers::const_buffer_span bs, 173 : bool more); 174 : 175 : private: 176 : results 177 2 : write_impl( 178 : buffers::const_buffer const& b, 179 : bool more) 180 : { 181 2 : return on_write(b, more); 182 : } 183 : 184 : results 185 2 : write_impl( 186 : buffers::mutable_buffer const& b, 187 : bool more) 188 : { 189 2 : return on_write(b, more); 190 : } 191 : 192 : results 193 5 : write_impl( 194 : buffers::const_buffer_span const& bs, 195 : bool more) 196 : { 197 5 : return on_write(bs, more); 198 : } 199 : 200 : template<class T> 201 : results 202 : write_impl(T const&, bool); 203 : }; 204 : 205 : //------------------------------------------------ 206 : 207 : /** Metafunction which determines if T is a sink 208 : 209 : @see 210 : @ref sink. 211 : */ 212 : #ifdef BOOST_HTTP_PROTO_DOCS 213 : template<class T> 214 : using is_sink = __see_below__; 215 : #else 216 : template<class T> 217 : using is_sink = 218 : std::is_convertible< 219 : typename std::decay<T>::type*, 220 : sink*>; 221 : #endif 222 : 223 : } // http_proto 224 : } // boost 225 : 226 : #include <boost/http_proto/impl/sink.hpp> 227 : 228 : #endif