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