Line data Source code
1 : // 2 : // Copyright (c) 2019 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_SERIALIZER_HPP 11 : #define BOOST_HTTP_PROTO_SERIALIZER_HPP 12 : 13 : #include <boost/http_proto/detail/config.hpp> 14 : #include <boost/http_proto/source.hpp> 15 : #include <boost/http_proto/detail/array_of_buffers.hpp> 16 : #include <boost/http_proto/detail/header.hpp> 17 : #include <boost/http_proto/detail/workspace.hpp> 18 : #include <boost/buffers/circular_buffer.hpp> 19 : #include <boost/buffers/type_traits.hpp> 20 : #include <boost/system/result.hpp> 21 : #include <cstdint> 22 : #include <memory> 23 : #include <type_traits> 24 : 25 : namespace boost { 26 : namespace http_proto { 27 : 28 : #ifndef BOOST_HTTP_PROTO_DOCS 29 : class request; 30 : class response; 31 : class request_view; 32 : class response_view; 33 : class message_view_base; 34 : #endif 35 : 36 : /** A serializer for HTTP/1 messages 37 : 38 : This is used to serialize one or more complete 39 : HTTP/1 messages. Each message consists of a 40 : required header followed by an optional body. 41 : */ 42 : class BOOST_SYMBOL_VISIBLE 43 0 : serializer 44 : { 45 : public: 46 : /** A ConstBuffers representing the output 47 : */ 48 : class const_buffers_type; 49 : 50 : struct stream; 51 : 52 : /** Destructor 53 : */ 54 : BOOST_HTTP_PROTO_DECL 55 : ~serializer(); 56 : 57 : /** Constructor 58 : */ 59 : BOOST_HTTP_PROTO_DECL 60 : serializer(); 61 : 62 : /** Constructor 63 : */ 64 : BOOST_HTTP_PROTO_DECL 65 : serializer( 66 : serializer&&) noexcept; 67 : 68 : /** Constructor 69 : */ 70 : BOOST_HTTP_PROTO_DECL 71 : explicit 72 : serializer( 73 : std::size_t buffer_size); 74 : 75 : //-------------------------------------------- 76 : 77 : /** Prepare the serializer for a new stream 78 : */ 79 : BOOST_HTTP_PROTO_DECL 80 : void 81 : reset() noexcept; 82 : 83 : /** Prepare the serializer for a new message 84 : 85 : The message will not contain a body. 86 : Changing the contents of the message 87 : after calling this function and before 88 : @ref is_done returns `true` results in 89 : undefined behavior. 90 : */ 91 : void 92 4 : start( 93 : message_view_base const& m) 94 : { 95 4 : start_empty(m); 96 4 : } 97 : 98 : /** Prepare the serializer for a new message 99 : 100 : Changing the contents of the message 101 : after calling this function and before 102 : @ref is_done returns `true` results in 103 : undefined behavior. 104 : 105 : @par Constraints 106 : @code 107 : is_const_buffers< ConstBuffers >::value == true 108 : @endcode 109 : */ 110 : template< 111 : class ConstBufferSequence 112 : #ifndef BOOST_HTTP_PROTO_DOCS 113 : ,class = typename 114 : std::enable_if< 115 : buffers::is_const_buffer_sequence< 116 : ConstBufferSequence>::value 117 : >::type 118 : #endif 119 : > 120 : void 121 : start( 122 : message_view_base const& m, 123 : ConstBufferSequence&& body); 124 : 125 : /** Prepare the serializer for a new message 126 : 127 : Changing the contents of the message 128 : after calling this function and before 129 : @ref is_done returns `true` results in 130 : undefined behavior. 131 : */ 132 : template< 133 : class Source 134 : #ifndef BOOST_HTTP_PROTO_DOCS 135 : ,class = typename std::enable_if< 136 : is_source<Source>::value>::type 137 : #endif 138 : > 139 : auto 140 : start( 141 : message_view_base const& m, 142 : Source&& body) -> 143 : typename std::decay< 144 : Source>::type&; 145 : 146 : //-------------------------------------------- 147 : 148 : BOOST_HTTP_PROTO_DECL 149 : stream 150 : start_stream( 151 : message_view_base const& m); 152 : 153 : //-------------------------------------------- 154 : 155 : /** Return true if serialization is complete. 156 : */ 157 : bool 158 21 : is_done() const noexcept 159 : { 160 21 : return is_done_; 161 : } 162 : 163 : /** Return the output area. 164 : 165 : This function will serialize some or 166 : all of the content and return the 167 : corresponding output buffers. 168 : 169 : @par Preconditions 170 : @code 171 : this->is_done() == false 172 : @endcode 173 : */ 174 : BOOST_HTTP_PROTO_DECL 175 : auto 176 : prepare() -> 177 : system::result< 178 : const_buffers_type>; 179 : 180 : /** Consume bytes from the output area. 181 : */ 182 : BOOST_HTTP_PROTO_DECL 183 : void 184 : consume(std::size_t n); 185 : 186 : private: 187 : static void copy( 188 : buffers::const_buffer*, 189 : buffers::const_buffer const*, 190 : std::size_t n) noexcept; 191 : auto 192 : make_array(std::size_t n) -> 193 : detail::array_of_const_buffers; 194 : 195 : BOOST_HTTP_PROTO_DECL void start_init(message_view_base const&); 196 : BOOST_HTTP_PROTO_DECL void start_empty(message_view_base const&); 197 : BOOST_HTTP_PROTO_DECL void start_buffers(message_view_base const&); 198 : BOOST_HTTP_PROTO_DECL void start_source(message_view_base const&, source*); 199 : 200 : enum class style 201 : { 202 : empty, 203 : buffers, 204 : source, 205 : stream 206 : }; 207 : 208 : static 209 : constexpr 210 : std::size_t 211 : chunked_overhead_ = 212 : 16 + // size 213 : 2 + // CRLF 214 : 2 + // CRLF 215 : 1 + // "0" 216 : 2 + // CRLF 217 : 2; // CRLF 218 : 219 : detail::workspace ws_; 220 : detail::array_of_const_buffers buf_; 221 : source* src_; 222 : 223 : buffers::circular_buffer tmp0_; 224 : buffers::circular_buffer tmp1_; 225 : detail::array_of_const_buffers out_; 226 : 227 : buffers::const_buffer* hp_; // header 228 : 229 : style st_; 230 : bool more_; 231 : bool is_done_; 232 : bool is_chunked_; 233 : bool is_expect_continue_; 234 : }; 235 : 236 : //------------------------------------------------ 237 : 238 : struct serializer::stream 239 : { 240 : /** Constructor. 241 : */ 242 : stream() = default; 243 : 244 : /** Constructor. 245 : */ 246 : stream(stream const&) = default; 247 : 248 : /** Constructor. 249 : */ 250 : stream& operator= 251 : (stream const&) = default; 252 : 253 : using buffers_type = 254 : buffers::mutable_buffer_pair; 255 : 256 : BOOST_HTTP_PROTO_DECL 257 : std::size_t 258 : capacity() const; 259 : 260 : BOOST_HTTP_PROTO_DECL 261 : std::size_t 262 : size() const; 263 : 264 : BOOST_HTTP_PROTO_DECL 265 : buffers_type 266 : prepare(std::size_t n) const; 267 : 268 : BOOST_HTTP_PROTO_DECL 269 : void 270 : commit(std::size_t n) const; 271 : 272 : BOOST_HTTP_PROTO_DECL 273 : void 274 : close() const; 275 : 276 : private: 277 : friend class serializer; 278 : 279 : explicit 280 0 : stream( 281 : serializer& sr) noexcept 282 0 : : sr_(&sr) 283 : { 284 0 : } 285 : 286 : serializer* sr_ = nullptr; 287 : }; 288 : 289 : } // http_proto 290 : } // boost 291 : 292 : #include <boost/http_proto/impl/serializer.hpp> 293 : 294 : #endif