]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/beast/http/impl/write.ipp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / boost / beast / http / impl / write.ipp
CommitLineData
b32b8144
FG
1//
2// Copyright (c) 2016-2017 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_WRITE_IPP
11#define BOOST_BEAST_HTTP_IMPL_WRITE_IPP
12
13#include <boost/beast/http/type_traits.hpp>
14#include <boost/beast/core/bind_handler.hpp>
15#include <boost/beast/core/ostream.hpp>
16#include <boost/beast/core/handler_ptr.hpp>
17#include <boost/beast/core/type_traits.hpp>
18#include <boost/beast/core/detail/config.hpp>
19#include <boost/asio/associated_allocator.hpp>
20#include <boost/asio/associated_executor.hpp>
21#include <boost/asio/handler_continuation_hook.hpp>
11fdf7f2 22#include <boost/asio/handler_invoke_hook.hpp>
b32b8144
FG
23#include <boost/asio/post.hpp>
24#include <boost/asio/write.hpp>
25#include <boost/optional.hpp>
26#include <boost/throw_exception.hpp>
27#include <ostream>
28#include <sstream>
29
30namespace boost {
31namespace beast {
32namespace http {
33namespace detail {
34
35template<
36 class Stream, class Handler,
37 bool isRequest, class Body, class Fields>
38class write_some_op
39{
40 Stream& s_;
41 serializer<isRequest,Body, Fields>& sr_;
42 Handler h_;
43
44 class lambda
45 {
46 write_some_op& op_;
47
48 public:
49 bool invoked = false;
50
51 explicit
52 lambda(write_some_op& op)
53 : op_(op)
54 {
55 }
56
57 template<class ConstBufferSequence>
58 void
59 operator()(error_code& ec,
60 ConstBufferSequence const& buffers)
61 {
62 invoked = true;
63 ec.assign(0, ec.category());
64 return op_.s_.async_write_some(
65 buffers, std::move(op_));
66 }
67 };
68
69public:
70 write_some_op(write_some_op&&) = default;
11fdf7f2 71 write_some_op(write_some_op const&) = delete;
b32b8144
FG
72
73 template<class DeducedHandler>
74 write_some_op(DeducedHandler&& h, Stream& s,
75 serializer<isRequest, Body, Fields>& sr)
76 : s_(s)
77 , sr_(sr)
78 , h_(std::forward<DeducedHandler>(h))
79 {
80 }
81
82 using allocator_type =
83 boost::asio::associated_allocator_t<Handler>;
84
85 allocator_type
86 get_allocator() const noexcept
87 {
11fdf7f2 88 return (boost::asio::get_associated_allocator)(h_);
b32b8144
FG
89 }
90
91 using executor_type = boost::asio::associated_executor_t<
92 Handler, decltype(std::declval<Stream&>().get_executor())>;
93
94 executor_type
95 get_executor() const noexcept
96 {
11fdf7f2 97 return (boost::asio::get_associated_executor)(
b32b8144
FG
98 h_, s_.get_executor());
99 }
100
101 void
102 operator()();
103
104 void
105 operator()(
106 error_code ec,
107 std::size_t bytes_transferred);
108
109 friend
110 bool asio_handler_is_continuation(write_some_op* op)
111 {
112 using boost::asio::asio_handler_is_continuation;
113 return asio_handler_is_continuation(
114 std::addressof(op->h_));
115 }
11fdf7f2
TL
116
117 template<class Function>
118 friend
119 void asio_handler_invoke(Function&& f, write_some_op* op)
120 {
121 using boost::asio::asio_handler_invoke;
122 asio_handler_invoke(f, std::addressof(op->h_));
123 }
b32b8144
FG
124};
125
126template<
127 class Stream, class Handler,
128 bool isRequest, class Body, class Fields>
129void
130write_some_op<
131 Stream, Handler, isRequest, Body, Fields>::
132operator()()
133{
134 error_code ec;
135 if(! sr_.is_done())
136 {
137 lambda f{*this};
138 sr_.next(ec, f);
139 if(ec)
140 {
141 BOOST_ASSERT(! f.invoked);
142 return boost::asio::post(
143 s_.get_executor(),
144 bind_handler(std::move(*this), ec, 0));
145 }
146 if(f.invoked)
147 {
148 // *this has been moved from,
149 // cannot access members here.
150 return;
151 }
152 // What else could it be?
153 BOOST_ASSERT(sr_.is_done());
154 }
155 return boost::asio::post(
156 s_.get_executor(),
157 bind_handler(std::move(*this), ec, 0));
158}
159
160template<
161 class Stream, class Handler,
162 bool isRequest, class Body, class Fields>
163void
164write_some_op<
165 Stream, Handler, isRequest, Body, Fields>::
166operator()(
167 error_code ec, std::size_t bytes_transferred)
168{
169 if(! ec)
170 sr_.consume(bytes_transferred);
171 h_(ec, bytes_transferred);
172}
173
174//------------------------------------------------------------------------------
175
176struct serializer_is_header_done
177{
178 template<
179 bool isRequest, class Body, class Fields>
180 bool
181 operator()(
182 serializer<isRequest, Body, Fields>& sr) const
183 {
184 return sr.is_header_done();
185 }
186};
187
188struct serializer_is_done
189{
190 template<
191 bool isRequest, class Body, class Fields>
192 bool
193 operator()(
194 serializer<isRequest, Body, Fields>& sr) const
195 {
196 return sr.is_done();
197 }
198};
199
200//------------------------------------------------------------------------------
201
202template<
203 class Stream, class Handler, class Predicate,
204 bool isRequest, class Body, class Fields>
205class write_op
206{
207 int state_ = 0;
208 Stream& s_;
209 serializer<isRequest, Body, Fields>& sr_;
210 std::size_t bytes_transferred_ = 0;
211 Handler h_;
212
213public:
214 write_op(write_op&&) = default;
11fdf7f2 215 write_op(write_op const&) = delete;
b32b8144
FG
216
217 template<class DeducedHandler>
218 write_op(DeducedHandler&& h, Stream& s,
219 serializer<isRequest, Body, Fields>& sr)
220 : s_(s)
221 , sr_(sr)
222 , h_(std::forward<DeducedHandler>(h))
223 {
224 }
225
226 using allocator_type =
227 boost::asio::associated_allocator_t<Handler>;
228
229 allocator_type
230 get_allocator() const noexcept
231 {
11fdf7f2 232 return (boost::asio::get_associated_allocator)(h_);
b32b8144
FG
233 }
234
235 using executor_type = boost::asio::associated_executor_t<
236 Handler, decltype(std::declval<Stream&>().get_executor())>;
237
238 executor_type
239 get_executor() const noexcept
240 {
11fdf7f2 241 return (boost::asio::get_associated_executor)(
b32b8144
FG
242 h_, s_.get_executor());
243 }
244
245 void
246 operator()(
247 error_code ec = {},
248 std::size_t bytes_transferred = 0);
249
250 friend
251 bool asio_handler_is_continuation(write_op* op)
252 {
253 using boost::asio::asio_handler_is_continuation;
254 return op->state_ >= 3 ||
255 asio_handler_is_continuation(
256 std::addressof(op->h_));
257 }
11fdf7f2
TL
258
259 template<class Function>
260 friend
261 void asio_handler_invoke(Function&& f, write_op* op)
262 {
263 using boost::asio::asio_handler_invoke;
264 asio_handler_invoke(f, std::addressof(op->h_));
265 }
b32b8144
FG
266};
267
268template<
269 class Stream, class Handler, class Predicate,
270 bool isRequest, class Body, class Fields>
271void
272write_op<Stream, Handler, Predicate,
273 isRequest, Body, Fields>::
274operator()(
275 error_code ec, std::size_t bytes_transferred)
276{
277 if(ec)
278 goto upcall;
279 switch(state_)
280 {
281 case 0:
282 {
283 if(Predicate{}(sr_))
284 {
285 state_ = 1;
286 return boost::asio::post(
287 s_.get_executor(),
288 bind_handler(std::move(*this), ec, 0));
289 }
290 state_ = 2;
291 return beast::http::async_write_some(
292 s_, sr_, std::move(*this));
293 }
294
295 case 1:
296 goto upcall;
297
298 case 2:
299 state_ = 3;
11fdf7f2 300 BOOST_FALLTHROUGH;
b32b8144
FG
301
302 case 3:
303 {
304 bytes_transferred_ += bytes_transferred;
305 if(Predicate{}(sr_))
306 goto upcall;
307 return beast::http::async_write_some(
308 s_, sr_, std::move(*this));
309 }
310 }
311upcall:
312 h_(ec, bytes_transferred_);
313}
314
315//------------------------------------------------------------------------------
316
317template<class Stream, class Handler,
318 bool isRequest, class Body, class Fields>
319class write_msg_op
320{
321 struct data
322 {
323 Stream& s;
324 serializer<isRequest, Body, Fields> sr;
325
11fdf7f2 326 data(Handler const&, Stream& s_, message<
b32b8144
FG
327 isRequest, Body, Fields>& m_)
328 : s(s_)
329 , sr(m_)
330 {
331 }
332 };
333
334 handler_ptr<data, Handler> d_;
335
336public:
337 write_msg_op(write_msg_op&&) = default;
11fdf7f2 338 write_msg_op(write_msg_op const&) = delete;
b32b8144
FG
339
340 template<class DeducedHandler, class... Args>
341 write_msg_op(DeducedHandler&& h, Stream& s, Args&&... args)
342 : d_(std::forward<DeducedHandler>(h),
343 s, std::forward<Args>(args)...)
344 {
345 }
346
347 using allocator_type =
348 boost::asio::associated_allocator_t<Handler>;
349
350 allocator_type
351 get_allocator() const noexcept
352 {
11fdf7f2 353 return (boost::asio::get_associated_allocator)(d_.handler());
b32b8144
FG
354 }
355
356 using executor_type = boost::asio::associated_executor_t<
357 Handler, decltype(std::declval<Stream&>().get_executor())>;
358
359 executor_type
360 get_executor() const noexcept
361 {
11fdf7f2 362 return (boost::asio::get_associated_executor)(
b32b8144
FG
363 d_.handler(), d_->s.get_executor());
364 }
365
366 void
367 operator()();
368
369 void
370 operator()(
371 error_code ec, std::size_t bytes_transferred);
372
373 friend
374 bool asio_handler_is_continuation(write_msg_op* op)
375 {
376 using boost::asio::asio_handler_is_continuation;
377 return asio_handler_is_continuation(
378 std::addressof(op->d_.handler()));
379 }
11fdf7f2
TL
380
381 template<class Function>
382 friend
383 void asio_handler_invoke(Function&& f, write_msg_op* op)
384 {
385 using boost::asio::asio_handler_invoke;
386 asio_handler_invoke(f, std::addressof(op->d_.handler()));
387 }
b32b8144
FG
388};
389
390template<class Stream, class Handler,
391 bool isRequest, class Body, class Fields>
392void
393write_msg_op<
394 Stream, Handler, isRequest, Body, Fields>::
395operator()()
396{
397 auto& d = *d_;
398 return async_write(d.s, d.sr, std::move(*this));
399}
400
401template<class Stream, class Handler,
402 bool isRequest, class Body, class Fields>
403void
404write_msg_op<
405 Stream, Handler, isRequest, Body, Fields>::
406operator()(error_code ec, std::size_t bytes_transferred)
407{
408 d_.invoke(ec, bytes_transferred);
409}
410
411//------------------------------------------------------------------------------
412
413template<class Stream>
414class write_some_lambda
415{
416 Stream& stream_;
417
418public:
419 bool invoked = false;
420 std::size_t bytes_transferred = 0;
421
422 explicit
423 write_some_lambda(Stream& stream)
424 : stream_(stream)
425 {
426 }
427
428 template<class ConstBufferSequence>
429 void
430 operator()(error_code& ec,
431 ConstBufferSequence const& buffers)
432 {
433 invoked = true;
434 bytes_transferred =
435 stream_.write_some(buffers, ec);
436 }
437};
438
439template<class Stream>
440class write_lambda
441{
442 Stream& stream_;
443
444public:
445 bool invoked = false;
446 std::size_t bytes_transferred = 0;
447
448 explicit
449 write_lambda(Stream& stream)
450 : stream_(stream)
451 {
452 }
453
454 template<class ConstBufferSequence>
455 void
456 operator()(error_code& ec,
457 ConstBufferSequence const& buffers)
458 {
459 invoked = true;
460 bytes_transferred = boost::asio::write(
461 stream_, buffers, ec);
462 }
463};
464
465template<
466 class SyncWriteStream,
467 bool isRequest, class Body, class Fields>
468std::size_t
11fdf7f2 469write_some_impl(
b32b8144
FG
470 SyncWriteStream& stream,
471 serializer<isRequest, Body, Fields>& sr,
472 error_code& ec)
473{
474 if(! sr.is_done())
475 {
476 write_some_lambda<SyncWriteStream> f{stream};
477 sr.next(ec, f);
478 if(ec)
479 return f.bytes_transferred;
480 if(f.invoked)
481 sr.consume(f.bytes_transferred);
482 return f.bytes_transferred;
483 }
484 ec.assign(0, ec.category());
485 return 0;
486}
487
488template<
489 class AsyncWriteStream,
490 bool isRequest, class Body, class Fields,
491 class WriteHandler>
492BOOST_ASIO_INITFN_RESULT_TYPE(
493 WriteHandler, void(error_code, std::size_t))
11fdf7f2 494async_write_some_impl(
b32b8144
FG
495 AsyncWriteStream& stream,
496 serializer<isRequest, Body, Fields>& sr,
497 WriteHandler&& handler)
498{
11fdf7f2
TL
499 BOOST_BEAST_HANDLER_INIT(
500 WriteHandler, void(error_code, std::size_t));
b32b8144
FG
501 detail::write_some_op<
502 AsyncWriteStream,
503 BOOST_ASIO_HANDLER_TYPE(WriteHandler,
504 void(error_code, std::size_t)),
505 isRequest, Body, Fields>{
11fdf7f2 506 std::move(init.completion_handler), stream, sr}();
b32b8144
FG
507 return init.result.get();
508}
509
510} // detail
511
512//------------------------------------------------------------------------------
513
514template<
515 class SyncWriteStream,
516 bool isRequest, class Body, class Fields>
517std::size_t
518write_some(
519 SyncWriteStream& stream,
520 serializer<isRequest, Body, Fields>& sr)
521{
522 static_assert(is_sync_write_stream<SyncWriteStream>::value,
523 "SyncWriteStream requirements not met");
524 static_assert(is_body<Body>::value,
525 "Body requirements not met");
526 static_assert(is_body_writer<Body>::value,
527 "BodyWriter requirements not met");
528 error_code ec;
529 auto const bytes_transferred =
530 write_some(stream, sr, ec);
531 if(ec)
532 BOOST_THROW_EXCEPTION(system_error{ec});
533 return bytes_transferred;
534}
535
536template<
537 class SyncWriteStream,
538 bool isRequest, class Body, class Fields>
539std::size_t
540write_some(
541 SyncWriteStream& stream,
542 serializer<isRequest, Body, Fields>& sr,
543 error_code& ec)
544{
545 static_assert(is_sync_write_stream<SyncWriteStream>::value,
546 "SyncWriteStream requirements not met");
547 static_assert(is_body<Body>::value,
548 "Body requirements not met");
549 static_assert(is_body_writer<Body>::value,
550 "BodyWriter requirements not met");
11fdf7f2 551 return detail::write_some_impl(stream, sr, ec);
b32b8144
FG
552}
553
554template<
555 class AsyncWriteStream,
556 bool isRequest, class Body, class Fields,
557 class WriteHandler>
558BOOST_ASIO_INITFN_RESULT_TYPE(
559 WriteHandler, void(error_code, std::size_t))
560async_write_some(
561 AsyncWriteStream& stream,
562 serializer<isRequest, Body, Fields>& sr,
563 WriteHandler&& handler)
564{
565 static_assert(is_async_write_stream<
566 AsyncWriteStream>::value,
567 "AsyncWriteStream requirements not met");
568 static_assert(is_body<Body>::value,
569 "Body requirements not met");
570 static_assert(is_body_writer<Body>::value,
571 "BodyWriter requirements not met");
11fdf7f2 572 return detail::async_write_some_impl(stream, sr,
b32b8144
FG
573 std::forward<WriteHandler>(handler));
574}
575
576//------------------------------------------------------------------------------
577
578template<
579 class SyncWriteStream,
580 bool isRequest, class Body, class Fields>
581std::size_t
582write_header(SyncWriteStream& stream,
583 serializer<isRequest, Body, Fields>& sr)
584{
585 static_assert(is_sync_write_stream<SyncWriteStream>::value,
586 "SyncWriteStream requirements not met");
587 static_assert(is_body<Body>::value,
588 "Body requirements not met");
589 static_assert(is_body_writer<Body>::value,
590 "BodyWriter requirements not met");
591 error_code ec;
592 auto const bytes_transferred =
593 write_header(stream, sr, ec);
594 if(ec)
595 BOOST_THROW_EXCEPTION(system_error{ec});
596 return bytes_transferred;
597}
598
599template<
600 class SyncWriteStream,
601 bool isRequest, class Body, class Fields>
602std::size_t
603write_header(
604 SyncWriteStream& stream,
605 serializer<isRequest, Body, Fields>& sr,
606 error_code& ec)
607{
608 static_assert(is_sync_write_stream<SyncWriteStream>::value,
609 "SyncWriteStream requirements not met");
610 static_assert(is_body<Body>::value,
611 "Body requirements not met");
612 static_assert(is_body_writer<Body>::value,
613 "BodyWriter requirements not met");
614 sr.split(true);
615 std::size_t bytes_transferred = 0;
616 if(! sr.is_header_done())
617 {
618 detail::write_lambda<SyncWriteStream> f{stream};
619 do
620 {
621 sr.next(ec, f);
622 bytes_transferred += f.bytes_transferred;
623 if(ec)
624 return bytes_transferred;
625 BOOST_ASSERT(f.invoked);
626 sr.consume(f.bytes_transferred);
627 }
628 while(! sr.is_header_done());
629 }
630 else
631 {
632 ec.assign(0, ec.category());
633 }
634 return bytes_transferred;
635}
636
637template<
638 class AsyncWriteStream,
639 bool isRequest, class Body, class Fields,
640 class WriteHandler>
641BOOST_ASIO_INITFN_RESULT_TYPE(
642 WriteHandler, void(error_code, std::size_t))
643async_write_header(
644 AsyncWriteStream& stream,
645 serializer<isRequest, Body, Fields>& sr,
646 WriteHandler&& handler)
647{
648 static_assert(is_async_write_stream<
649 AsyncWriteStream>::value,
650 "AsyncWriteStream requirements not met");
651 static_assert(is_body<Body>::value,
652 "Body requirements not met");
653 static_assert(is_body_writer<Body>::value,
654 "BodyWriter requirements not met");
655 sr.split(true);
11fdf7f2
TL
656 BOOST_BEAST_HANDLER_INIT(
657 WriteHandler, void(error_code, std::size_t));
b32b8144
FG
658 detail::write_op<
659 AsyncWriteStream,
660 BOOST_ASIO_HANDLER_TYPE(WriteHandler,
661 void(error_code, std::size_t)),
662 detail::serializer_is_header_done,
663 isRequest, Body, Fields>{
11fdf7f2 664 std::move(init.completion_handler), stream, sr}();
b32b8144
FG
665 return init.result.get();
666}
667
668//------------------------------------------------------------------------------
669
670template<
671 class SyncWriteStream,
672 bool isRequest, class Body, class Fields>
673std::size_t
674write(
675 SyncWriteStream& stream,
676 serializer<isRequest, Body, Fields>& sr)
677{
678 static_assert(is_sync_write_stream<SyncWriteStream>::value,
679 "SyncWriteStream requirements not met");
680 error_code ec;
681 auto const bytes_transferred =
682 write(stream, sr, ec);
683 if(ec)
684 BOOST_THROW_EXCEPTION(system_error{ec});
685 return bytes_transferred;
686}
687
688template<
689 class SyncWriteStream,
690 bool isRequest, class Body, class Fields>
691std::size_t
692write(
693 SyncWriteStream& stream,
694 serializer<isRequest, Body, Fields>& sr,
695 error_code& ec)
696{
697 static_assert(is_sync_write_stream<SyncWriteStream>::value,
698 "SyncWriteStream requirements not met");
699 std::size_t bytes_transferred = 0;
700 sr.split(false);
701 for(;;)
702 {
703 bytes_transferred +=
704 write_some(stream, sr, ec);
705 if(ec)
706 return bytes_transferred;
707 if(sr.is_done())
708 break;
709 }
710 return bytes_transferred;
711}
712
713template<
714 class AsyncWriteStream,
715 bool isRequest, class Body, class Fields,
716 class WriteHandler>
717BOOST_ASIO_INITFN_RESULT_TYPE(
718 WriteHandler, void(error_code, std::size_t))
719async_write(
720 AsyncWriteStream& stream,
721 serializer<isRequest, Body, Fields>& sr,
722 WriteHandler&& handler)
723{
724 static_assert(is_async_write_stream<
725 AsyncWriteStream>::value,
726 "AsyncWriteStream requirements not met");
727 static_assert(is_body<Body>::value,
728 "Body requirements not met");
729 static_assert(is_body_writer<Body>::value,
730 "BodyWriter requirements not met");
731 sr.split(false);
11fdf7f2
TL
732 BOOST_BEAST_HANDLER_INIT(
733 WriteHandler, void(error_code, std::size_t));
b32b8144
FG
734 detail::write_op<
735 AsyncWriteStream,
736 BOOST_ASIO_HANDLER_TYPE(WriteHandler,
737 void(error_code, std::size_t)),
738 detail::serializer_is_done,
739 isRequest, Body, Fields>{
11fdf7f2 740 std::move(init.completion_handler), stream, sr}();
b32b8144
FG
741 return init.result.get();
742}
743
744//------------------------------------------------------------------------------
745
746template<
747 class SyncWriteStream,
748 bool isRequest, class Body, class Fields>
749std::size_t
750write(
751 SyncWriteStream& stream,
752 message<isRequest, Body, Fields> const& msg)
753{
754 static_assert(is_sync_write_stream<SyncWriteStream>::value,
755 "SyncWriteStream requirements not met");
756 static_assert(is_body<Body>::value,
757 "Body requirements not met");
758 static_assert(is_body_writer<Body>::value,
759 "BodyWriter requirements not met");
760 error_code ec;
761 auto const bytes_transferred =
762 write(stream, msg, ec);
763 if(ec)
764 BOOST_THROW_EXCEPTION(system_error{ec});
765 return bytes_transferred;
766}
767
768template<
769 class SyncWriteStream,
770 bool isRequest, class Body, class Fields>
771std::size_t
772write(
773 SyncWriteStream& stream,
774 message<isRequest, Body, Fields> const& msg,
775 error_code& ec)
776{
777 static_assert(is_sync_write_stream<SyncWriteStream>::value,
778 "SyncWriteStream requirements not met");
779 static_assert(is_body<Body>::value,
780 "Body requirements not met");
781 static_assert(is_body_writer<Body>::value,
782 "BodyWriter requirements not met");
783 serializer<isRequest, Body, Fields> sr{msg};
784 return write(stream, sr, ec);
785}
786
787template<
788 class AsyncWriteStream,
789 bool isRequest, class Body, class Fields,
790 class WriteHandler>
791BOOST_ASIO_INITFN_RESULT_TYPE(
792 WriteHandler, void(error_code, std::size_t))
793async_write(
794 AsyncWriteStream& stream,
795 message<isRequest, Body, Fields>& msg,
796 WriteHandler&& handler)
797{
798 static_assert(
799 is_async_write_stream<AsyncWriteStream>::value,
800 "AsyncWriteStream requirements not met");
801 static_assert(is_body<Body>::value,
802 "Body requirements not met");
803 static_assert(is_body_writer<Body>::value,
804 "BodyWriter requirements not met");
11fdf7f2
TL
805 BOOST_BEAST_HANDLER_INIT(
806 WriteHandler, void(error_code, std::size_t));
b32b8144
FG
807 detail::write_msg_op<
808 AsyncWriteStream,
809 BOOST_ASIO_HANDLER_TYPE(WriteHandler,
810 void(error_code, std::size_t)),
811 isRequest, Body, Fields>{
11fdf7f2 812 std::move(init.completion_handler), stream, msg}();
b32b8144
FG
813 return init.result.get();
814}
815
816//------------------------------------------------------------------------------
817
818namespace detail {
819
820template<class Serializer>
821class write_ostream_lambda
822{
823 std::ostream& os_;
824 Serializer& sr_;
825
826public:
827 write_ostream_lambda(std::ostream& os,
828 Serializer& sr)
829 : os_(os)
830 , sr_(sr)
831 {
832 }
833
834 template<class ConstBufferSequence>
835 void
836 operator()(error_code& ec,
837 ConstBufferSequence const& buffers) const
838 {
839 ec.assign(0, ec.category());
840 if(os_.fail())
841 return;
842 std::size_t bytes_transferred = 0;
843 for(auto b : buffers_range(buffers))
844 {
845 os_.write(reinterpret_cast<char const*>(
846 b.data()), b.size());
847 if(os_.fail())
848 return;
849 bytes_transferred += b.size();
850 }
851 sr_.consume(bytes_transferred);
852 }
853};
854
855} // detail
856
857template<class Fields>
858std::ostream&
859operator<<(std::ostream& os,
860 header<true, Fields> const& h)
861{
862 typename Fields::writer fr{
863 h, h.version(), h.method()};
864 return os << buffers(fr.get());
865}
866
867template<class Fields>
868std::ostream&
869operator<<(std::ostream& os,
870 header<false, Fields> const& h)
871{
872 typename Fields::writer fr{
873 h, h.version(), h.result_int()};
874 return os << buffers(fr.get());
875}
876
877template<bool isRequest, class Body, class Fields>
878std::ostream&
879operator<<(std::ostream& os,
880 message<isRequest, Body, Fields> const& msg)
881{
882 static_assert(is_body<Body>::value,
883 "Body requirements not met");
884 static_assert(is_body_writer<Body>::value,
885 "BodyWriter requirements not met");
886 serializer<isRequest, Body, Fields> sr{msg};
887 error_code ec;
888 detail::write_ostream_lambda<decltype(sr)> f{os, sr};
889 do
890 {
891 sr.next(ec, f);
892 if(os.fail())
893 break;
894 if(ec)
895 {
896 os.setstate(std::ios::failbit);
897 break;
898 }
899 }
900 while(! sr.is_done());
901 return os;
902}
903
904} // http
905} // beast
906} // boost
907
908#endif