]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/http/impl/serializer.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / beast / http / impl / serializer.hpp
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_HTTP_IMPL_SERIALIZER_HPP
11 #define BOOST_BEAST_HTTP_IMPL_SERIALIZER_HPP
12
13 #include <boost/beast/core/buffer_traits.hpp>
14 #include <boost/beast/core/detail/buffers_ref.hpp>
15 #include <boost/beast/http/error.hpp>
16 #include <boost/beast/http/status.hpp>
17 #include <boost/beast/core/detail/config.hpp>
18 #include <boost/assert.hpp>
19 #include <ostream>
20
21 namespace boost {
22 namespace beast {
23 namespace http {
24
25 template<
26 bool isRequest, class Body, class Fields>
27 void
28 serializer<isRequest, Body, Fields>::
29 fwrinit(std::true_type)
30 {
31 fwr_.emplace(m_, m_.version(), m_.method());
32 }
33
34 template<
35 bool isRequest, class Body, class Fields>
36 void
37 serializer<isRequest, Body, Fields>::
38 fwrinit(std::false_type)
39 {
40 fwr_.emplace(m_, m_.version(), m_.result_int());
41 }
42
43 template<
44 bool isRequest, class Body, class Fields>
45 template<std::size_t I, class Visit>
46 inline
47 void
48 serializer<isRequest, Body, Fields>::
49 do_visit(error_code& ec, Visit& visit)
50 {
51 pv_.template emplace<I>(limit_, v_.template get<I>());
52 visit(ec, beast::detail::make_buffers_ref(
53 pv_.template get<I>()));
54 }
55
56 //------------------------------------------------------------------------------
57
58 template<
59 bool isRequest, class Body, class Fields>
60 serializer<isRequest, Body, Fields>::
61 serializer(value_type& m)
62 : m_(m)
63 , wr_(m_.base(), m_.body())
64 {
65 }
66
67 template<
68 bool isRequest, class Body, class Fields>
69 template<class Visit>
70 void
71 serializer<isRequest, Body, Fields>::
72 next(error_code& ec, Visit&& visit)
73 {
74 switch(s_)
75 {
76 case do_construct:
77 {
78 fwrinit(std::integral_constant<bool,
79 isRequest>{});
80 if(m_.chunked())
81 goto go_init_c;
82 s_ = do_init;
83 BOOST_FALLTHROUGH;
84 }
85
86 case do_init:
87 {
88 wr_.init(ec);
89 if(ec)
90 return;
91 if(split_)
92 goto go_header_only;
93 auto result = wr_.get(ec);
94 if(ec == error::need_more)
95 goto go_header_only;
96 if(ec)
97 return;
98 if(! result)
99 goto go_header_only;
100 more_ = result->second;
101 v_.template emplace<2>(
102 boost::in_place_init,
103 fwr_->get(),
104 result->first);
105 s_ = do_header;
106 BOOST_FALLTHROUGH;
107 }
108
109 case do_header:
110 do_visit<2>(ec, visit);
111 break;
112
113 go_header_only:
114 v_.template emplace<1>(fwr_->get());
115 s_ = do_header_only;
116 BOOST_FALLTHROUGH;
117 case do_header_only:
118 do_visit<1>(ec, visit);
119 break;
120
121 case do_body:
122 s_ = do_body + 1;
123 BOOST_FALLTHROUGH;
124
125 case do_body + 1:
126 {
127 auto result = wr_.get(ec);
128 if(ec)
129 return;
130 if(! result)
131 goto go_complete;
132 more_ = result->second;
133 v_.template emplace<3>(result->first);
134 s_ = do_body + 2;
135 BOOST_FALLTHROUGH;
136 }
137
138 case do_body + 2:
139 do_visit<3>(ec, visit);
140 break;
141
142 //----------------------------------------------------------------------
143
144 go_init_c:
145 s_ = do_init_c;
146 BOOST_FALLTHROUGH;
147 case do_init_c:
148 {
149 wr_.init(ec);
150 if(ec)
151 return;
152 if(split_)
153 goto go_header_only_c;
154 auto result = wr_.get(ec);
155 if(ec == error::need_more)
156 goto go_header_only_c;
157 if(ec)
158 return;
159 if(! result)
160 goto go_header_only_c;
161 more_ = result->second;
162 if(! more_)
163 {
164 // do it all in one buffer
165 v_.template emplace<7>(
166 boost::in_place_init,
167 fwr_->get(),
168 buffer_bytes(result->first),
169 net::const_buffer{nullptr, 0},
170 chunk_crlf{},
171 result->first,
172 chunk_crlf{},
173 detail::chunk_last(),
174 net::const_buffer{nullptr, 0},
175 chunk_crlf{});
176 goto go_all_c;
177 }
178 v_.template emplace<4>(
179 boost::in_place_init,
180 fwr_->get(),
181 buffer_bytes(result->first),
182 net::const_buffer{nullptr, 0},
183 chunk_crlf{},
184 result->first,
185 chunk_crlf{});
186 s_ = do_header_c;
187 BOOST_FALLTHROUGH;
188 }
189
190 case do_header_c:
191 do_visit<4>(ec, visit);
192 break;
193
194 go_header_only_c:
195 v_.template emplace<1>(fwr_->get());
196 s_ = do_header_only_c;
197 BOOST_FALLTHROUGH;
198
199 case do_header_only_c:
200 do_visit<1>(ec, visit);
201 break;
202
203 case do_body_c:
204 s_ = do_body_c + 1;
205 BOOST_FALLTHROUGH;
206
207 case do_body_c + 1:
208 {
209 auto result = wr_.get(ec);
210 if(ec)
211 return;
212 if(! result)
213 goto go_final_c;
214 more_ = result->second;
215 if(! more_)
216 {
217 // do it all in one buffer
218 v_.template emplace<6>(
219 boost::in_place_init,
220 buffer_bytes(result->first),
221 net::const_buffer{nullptr, 0},
222 chunk_crlf{},
223 result->first,
224 chunk_crlf{},
225 detail::chunk_last(),
226 net::const_buffer{nullptr, 0},
227 chunk_crlf{});
228 goto go_body_final_c;
229 }
230 v_.template emplace<5>(
231 boost::in_place_init,
232 buffer_bytes(result->first),
233 net::const_buffer{nullptr, 0},
234 chunk_crlf{},
235 result->first,
236 chunk_crlf{});
237 s_ = do_body_c + 2;
238 BOOST_FALLTHROUGH;
239 }
240
241 case do_body_c + 2:
242 do_visit<5>(ec, visit);
243 break;
244
245 go_body_final_c:
246 s_ = do_body_final_c;
247 BOOST_FALLTHROUGH;
248 case do_body_final_c:
249 do_visit<6>(ec, visit);
250 break;
251
252 go_all_c:
253 s_ = do_all_c;
254 BOOST_FALLTHROUGH;
255 case do_all_c:
256 do_visit<7>(ec, visit);
257 break;
258
259 go_final_c:
260 case do_final_c:
261 v_.template emplace<8>(
262 boost::in_place_init,
263 detail::chunk_last(),
264 net::const_buffer{nullptr, 0},
265 chunk_crlf{});
266 s_ = do_final_c + 1;
267 BOOST_FALLTHROUGH;
268
269 case do_final_c + 1:
270 do_visit<8>(ec, visit);
271 break;
272
273 //----------------------------------------------------------------------
274
275 default:
276 case do_complete:
277 BOOST_ASSERT(false);
278 break;
279
280 go_complete:
281 s_ = do_complete;
282 break;
283 }
284 }
285
286 template<
287 bool isRequest, class Body, class Fields>
288 void
289 serializer<isRequest, Body, Fields>::
290 consume(std::size_t n)
291 {
292 switch(s_)
293 {
294 case do_header:
295 BOOST_ASSERT(
296 n <= buffer_bytes(v_.template get<2>()));
297 v_.template get<2>().consume(n);
298 if(buffer_bytes(v_.template get<2>()) > 0)
299 break;
300 header_done_ = true;
301 v_.reset();
302 if(! more_)
303 goto go_complete;
304 s_ = do_body + 1;
305 break;
306
307 case do_header_only:
308 BOOST_ASSERT(
309 n <= buffer_bytes(v_.template get<1>()));
310 v_.template get<1>().consume(n);
311 if(buffer_bytes(v_.template get<1>()) > 0)
312 break;
313 fwr_ = boost::none;
314 header_done_ = true;
315 if(! split_)
316 goto go_complete;
317 s_ = do_body;
318 break;
319
320 case do_body + 2:
321 {
322 BOOST_ASSERT(
323 n <= buffer_bytes(v_.template get<3>()));
324 v_.template get<3>().consume(n);
325 if(buffer_bytes(v_.template get<3>()) > 0)
326 break;
327 v_.reset();
328 if(! more_)
329 goto go_complete;
330 s_ = do_body + 1;
331 break;
332 }
333
334 //----------------------------------------------------------------------
335
336 case do_header_c:
337 BOOST_ASSERT(
338 n <= buffer_bytes(v_.template get<4>()));
339 v_.template get<4>().consume(n);
340 if(buffer_bytes(v_.template get<4>()) > 0)
341 break;
342 header_done_ = true;
343 v_.reset();
344 if(more_)
345 s_ = do_body_c + 1;
346 else
347 s_ = do_final_c;
348 break;
349
350 case do_header_only_c:
351 {
352 BOOST_ASSERT(
353 n <= buffer_bytes(v_.template get<1>()));
354 v_.template get<1>().consume(n);
355 if(buffer_bytes(v_.template get<1>()) > 0)
356 break;
357 fwr_ = boost::none;
358 header_done_ = true;
359 if(! split_)
360 {
361 s_ = do_final_c;
362 break;
363 }
364 s_ = do_body_c;
365 break;
366 }
367
368 case do_body_c + 2:
369 BOOST_ASSERT(
370 n <= buffer_bytes(v_.template get<5>()));
371 v_.template get<5>().consume(n);
372 if(buffer_bytes(v_.template get<5>()) > 0)
373 break;
374 v_.reset();
375 if(more_)
376 s_ = do_body_c + 1;
377 else
378 s_ = do_final_c;
379 break;
380
381 case do_body_final_c:
382 {
383 BOOST_ASSERT(
384 n <= buffer_bytes(v_.template get<6>()));
385 v_.template get<6>().consume(n);
386 if(buffer_bytes(v_.template get<6>()) > 0)
387 break;
388 v_.reset();
389 s_ = do_complete;
390 break;
391 }
392
393 case do_all_c:
394 {
395 BOOST_ASSERT(
396 n <= buffer_bytes(v_.template get<7>()));
397 v_.template get<7>().consume(n);
398 if(buffer_bytes(v_.template get<7>()) > 0)
399 break;
400 header_done_ = true;
401 v_.reset();
402 s_ = do_complete;
403 break;
404 }
405
406 case do_final_c + 1:
407 BOOST_ASSERT(buffer_bytes(v_.template get<8>()));
408 v_.template get<8>().consume(n);
409 if(buffer_bytes(v_.template get<8>()) > 0)
410 break;
411 v_.reset();
412 goto go_complete;
413
414 //----------------------------------------------------------------------
415
416 default:
417 BOOST_ASSERT(false);
418 case do_complete:
419 break;
420
421 go_complete:
422 s_ = do_complete;
423 break;
424 }
425 }
426
427 } // http
428 } // beast
429 } // boost
430
431 #endif