Imported Upstream version 1.72.0
[platform/upstream/boost.git] / 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