Blame view

3rdparty/boost_1_81_0/boost/beast/http/serializer.hpp 12.2 KB
63e88f80   Hu Chunming   提交三方库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
  //
  // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  //
  // Distributed under the Boost Software License, Version 1.0. (See accompanying
  // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  //
  // Official repository: https://github.com/boostorg/beast
  //
  
  #ifndef BOOST_BEAST_HTTP_SERIALIZER_HPP
  #define BOOST_BEAST_HTTP_SERIALIZER_HPP
  
  #include <boost/beast/core/detail/config.hpp>
  #include <boost/beast/core/buffers_cat.hpp>
  #include <boost/beast/core/buffers_prefix.hpp>
  #include <boost/beast/core/buffers_suffix.hpp>
  #include <boost/beast/core/string.hpp>
  #include <boost/beast/core/detail/variant.hpp>
  #include <boost/beast/http/message.hpp>
  #include <boost/beast/http/chunk_encode.hpp>
  #include <boost/asio/buffer.hpp>
  #include <boost/optional.hpp>
  
  namespace boost {
  namespace beast {
  namespace http {
  
  /** Provides buffer oriented HTTP message serialization functionality.
  
      An object of this type is used to serialize a complete
      HTTP message into a sequence of octets. To use this class,
      construct an instance with the message to be serialized.
      The implementation will automatically perform chunk encoding
      if the contents of the message indicate that chunk encoding
      is required.
  
      Chunked output produced by the serializer never contains chunk
      extensions or trailers, and the location of chunk boundaries
      is not specified. If callers require chunk extensions, trailers,
      or control over the exact contents of each chunk they should
      use the serializer to write just the message header, and then
      assume control over serializing the chunked payload by using
      the chunk buffer sequence types @ref chunk_body, @ref chunk_crlf,
      @ref chunk_header, and @ref chunk_last.
  
      @tparam isRequest `true` if the message is a request.
  
      @tparam Body The body type of the message.
  
      @tparam Fields The type of fields in the message.
  */
  template<
      bool isRequest,
      class Body,
      class Fields = fields>
  class serializer
  {
  public:
      static_assert(is_body<Body>::value,
          "Body type requirements not met");
  
      static_assert(is_body_writer<Body>::value,
          "BodyWriter type requirements not met");
  
      /** The type of message this serializer uses
  
          This may be const or non-const depending on the
          implementation of the corresponding <em>BodyWriter</em>.
      */
  #if BOOST_BEAST_DOXYGEN
      using value_type = __implementation_defined__;
  #else
      using value_type = typename std::conditional<
          std::is_constructible<typename Body::writer,
              header<isRequest, Fields>&,
              typename Body::value_type&>::value &&
          ! std::is_constructible<typename Body::writer,
              header<isRequest, Fields> const&,
              typename Body::value_type const&>::value,
          message<isRequest, Body, Fields>,
          message<isRequest, Body, Fields> const>::type;
  #endif
  
  private:
      enum
      {
          do_construct        =   0,
  
          do_init             =  10,
          do_header_only      =  20,
          do_header           =  30,
          do_body             =  40,
          
          do_init_c           =  50,
          do_header_only_c    =  60,
          do_header_c         =  70,
          do_body_c           =  80,
          do_final_c          =  90,
      #ifndef BOOST_BEAST_NO_BIG_VARIANTS
          do_body_final_c     = 100,
          do_all_c            = 110,
      #endif
  
          do_complete         = 120
      };
  
      void fwrinit(std::true_type);
      void fwrinit(std::false_type);
  
      template<std::size_t, class Visit>
      void
      do_visit(error_code& ec, Visit& visit);
  
      using writer = typename Body::writer;
  
      using cb1_t = buffers_suffix<typename
          Fields::writer::const_buffers_type>;        // header
      using pcb1_t  = buffers_prefix_view<cb1_t const&>;
  
      using cb2_t = buffers_suffix<buffers_cat_view<
          typename Fields::writer::const_buffers_type,// header
          typename writer::const_buffers_type>>;      // body
      using pcb2_t = buffers_prefix_view<cb2_t const&>;
  
      using cb3_t = buffers_suffix<
          typename writer::const_buffers_type>;       // body
      using pcb3_t = buffers_prefix_view<cb3_t const&>;
  
      using cb4_t = buffers_suffix<buffers_cat_view<
          typename Fields::writer::const_buffers_type,// header
          detail::chunk_size,                         // chunk-size
          net::const_buffer,                          // chunk-ext
          chunk_crlf,                                 // crlf
          typename writer::const_buffers_type,        // body
          chunk_crlf>>;                               // crlf
      using pcb4_t = buffers_prefix_view<cb4_t const&>;
  
      using cb5_t = buffers_suffix<buffers_cat_view<
          detail::chunk_size,                         // chunk-header
          net::const_buffer,                          // chunk-ext
          chunk_crlf,                                 // crlf
          typename writer::const_buffers_type,        // body
          chunk_crlf>>;                               // crlf
      using pcb5_t = buffers_prefix_view<cb5_t const&>;
  
      using cb6_t = buffers_suffix<buffers_cat_view<
          detail::chunk_size,                         // chunk-header
          net::const_buffer,                          // chunk-size
          chunk_crlf,                                 // crlf
          typename writer::const_buffers_type,        // body
          chunk_crlf,                                 // crlf
          net::const_buffer,                          // chunk-final
          net::const_buffer,                          // trailers 
          chunk_crlf>>;                               // crlf
      using pcb6_t = buffers_prefix_view<cb6_t const&>;
  
      using cb7_t = buffers_suffix<buffers_cat_view<
          typename Fields::writer::const_buffers_type,// header
          detail::chunk_size,                         // chunk-size
          net::const_buffer,                          // chunk-ext
          chunk_crlf,                                 // crlf
          typename writer::const_buffers_type,        // body
          chunk_crlf,                                 // crlf
          net::const_buffer,                          // chunk-final
          net::const_buffer,                          // trailers 
          chunk_crlf>>;                               // crlf
      using pcb7_t = buffers_prefix_view<cb7_t const&>;
  
      using cb8_t = buffers_suffix<buffers_cat_view<
          net::const_buffer,                          // chunk-final
          net::const_buffer,                          // trailers 
          chunk_crlf>>;                               // crlf
      using pcb8_t = buffers_prefix_view<cb8_t const&>;
  
      value_type& m_;
      writer wr_;
      boost::optional<typename Fields::writer> fwr_;
      beast::detail::variant<
          cb1_t, cb2_t, cb3_t, cb4_t,
          cb5_t ,cb6_t, cb7_t, cb8_t> v_;
      beast::detail::variant<
          pcb1_t, pcb2_t, pcb3_t, pcb4_t,
          pcb5_t ,pcb6_t, pcb7_t, pcb8_t> pv_;
      std::size_t limit_ =
          (std::numeric_limits<std::size_t>::max)();
      int s_ = do_construct;
      bool split_ = false;
      bool header_done_ = false;
      bool more_ = false;
  
  public:
      /// Constructor
      serializer(serializer&&) = default;
  
      /// Constructor
      serializer(serializer const&) = default;
  
      /// Assignment
      serializer& operator=(serializer const&) = delete;
  
      /** Constructor
  
          The implementation guarantees that the message passed on
          construction will not be accessed until the first call to
          @ref next. This allows the message to be lazily created.
          For example, if the header is filled in before serialization.
  
          @param msg A reference to the message to serialize, which must
          remain valid for the lifetime of the serializer. Depending on
          the type of Body used, this may or may not be a `const` reference.
  
          @note This function participates in overload resolution only if
          Body::writer is constructible from a `const` message reference.
      */
      explicit
      serializer(value_type& msg);
  
      /// Returns the message being serialized
      value_type&
      get()
      {
          return m_;
      }
  
      /// Returns the serialized buffer size limit
      std::size_t
      limit()
      {
          return limit_;
      }
  
      /** Set the serialized buffer size limit
  
          This function adjusts the limit on the maximum size of the
          buffers passed to the visitor. The new size limit takes effect
          in the following call to @ref next.
  
          The default is no buffer size limit.
  
          @param limit The new buffer size limit. If this number
          is zero, the size limit is removed.
      */
      void
      limit(std::size_t limit)
      {
          limit_ = limit > 0 ? limit :
              (std::numeric_limits<std::size_t>::max)();
      }
  
      /** Returns `true` if we will pause after writing the complete header.
      */
      bool
      split()
      {
          return split_;
      }
  
      /** Set whether the header and body are written separately.
  
          When the split feature is enabled, the implementation will
          write only the octets corresponding to the serialized header
          first. If the header has already been written, this function
          will have no effect on output.
      */
      void
      split(bool v)
      {
          split_ = v;
      }
  
      /** Return `true` if serialization of the header is complete.
  
          This function indicates whether or not all buffers containing
          serialized header octets have been retrieved.
      */
      bool
      is_header_done()
      {
          return header_done_;
      }
  
      /** Return `true` if serialization is complete.
  
          The operation is complete when all octets corresponding
          to the serialized representation of the message have been
          successfully retrieved.
      */
      bool
      is_done() const
      {
          return s_ == do_complete;
      }
  
      /** Returns the next set of buffers in the serialization.
  
          This function will attempt to call the `visit` function
          object with a <em>ConstBufferSequence</em> of unspecified type
          representing the next set of buffers in the serialization
          of the message represented by this object. 
  
          If there are no more buffers in the serialization, the
          visit function will not be called. In this case, no error
          will be indicated, and the function @ref is_done will
          return `true`.
  
          @param ec Set to the error, if any occurred.
  
          @param visit The function to call. The equivalent function
          signature of this object must be:
          @code
              template<class ConstBufferSequence>
              void visit(error_code&, ConstBufferSequence const&);
          @endcode
          The function is not copied, if no error occurs it will be
          invoked before the call to @ref next returns.
  
      */
      template<class Visit>
      void
      next(error_code& ec, Visit&& visit);
  
      /** Consume buffer octets in the serialization.
  
          This function should be called after one or more octets
          contained in the buffers provided in the prior call
          to @ref next have been used.
  
          After a call to @ref consume, callers should check the
          return value of @ref is_done to determine if the entire
          message has been serialized.
  
          @param n The number of octets to consume. This number must
          be greater than zero and no greater than the number of
          octets in the buffers provided in the prior call to @ref next.
      */
      void
      consume(std::size_t n);
  
      /** Provides low-level access to the associated <em>BodyWriter</em>
  
          This function provides access to the instance of the writer
          associated with the body and created by the serializer
          upon construction. The behavior of accessing this object
          is defined by the specification of the particular writer
          and its associated body.
  
          @return A reference to the writer.
      */
      writer&
      writer_impl()
      {
          return wr_;
      }
  };
  
  /// A serializer for HTTP/1 requests
  template<class Body, class Fields = fields>
  using request_serializer = serializer<true, Body, Fields>;
  
  /// A serializer for HTTP/1 responses
  template<class Body, class Fields = fields>
  using response_serializer = serializer<false, Body, Fields>;
  
  } // http
  } // beast
  } // boost
  
  #include <boost/beast/http/impl/serializer.hpp>
  
  #endif