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