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