Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:31

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_HTTP_IMPL_WRITE_HPP
0011 #define BOOST_BEAST_HTTP_IMPL_WRITE_HPP
0012 
0013 #include <boost/beast/http/type_traits.hpp>
0014 #include <boost/beast/core/async_base.hpp>
0015 #include <boost/beast/core/bind_handler.hpp>
0016 #include <boost/beast/core/buffers_range.hpp>
0017 #include <boost/beast/core/make_printable.hpp>
0018 #include <boost/beast/core/stream_traits.hpp>
0019 #include <boost/beast/core/detail/is_invocable.hpp>
0020 #include <boost/asio/coroutine.hpp>
0021 #include <boost/asio/dispatch.hpp>
0022 #include <boost/asio/write.hpp>
0023 #include <boost/optional.hpp>
0024 #include <boost/throw_exception.hpp>
0025 #include <ostream>
0026 #include <sstream>
0027 
0028 namespace boost {
0029 namespace beast {
0030 namespace http {
0031 namespace detail {
0032 
0033 template<
0034     class Handler,
0035     class Stream,
0036     bool isRequest, class Body, class Fields>
0037 class write_some_op
0038     : public beast::async_base<
0039         Handler, beast::executor_type<Stream>>
0040 {
0041     Stream& s_;
0042     serializer<isRequest,Body, Fields>& sr_;
0043 
0044     class lambda
0045     {
0046         write_some_op& op_;
0047 
0048     public:
0049         bool invoked = false;
0050 
0051         explicit
0052         lambda(write_some_op& op)
0053             : op_(op)
0054         {
0055         }
0056 
0057         template<class ConstBufferSequence>
0058         void
0059         operator()(
0060             error_code& ec,
0061             ConstBufferSequence const& buffers)
0062         {
0063             BOOST_ASIO_HANDLER_LOCATION((
0064                 __FILE__, __LINE__,
0065                 "http::async_write_some"));
0066 
0067             invoked = true;
0068             ec = {};
0069             op_.s_.async_write_some(
0070                 buffers, std::move(op_));
0071         }
0072     };
0073 
0074 public:
0075     template<class Handler_>
0076     write_some_op(
0077         Handler_&& h,
0078         Stream& s,
0079         serializer<isRequest, Body, Fields>& sr)
0080         : async_base<
0081             Handler, beast::executor_type<Stream>>(
0082                  std::forward<Handler_>(h), s.get_executor())
0083         , s_(s)
0084         , sr_(sr)
0085     {
0086         (*this)();
0087     }
0088 
0089     void
0090     operator()()
0091     {
0092         error_code ec;
0093         if(! sr_.is_done())
0094         {
0095             lambda f{*this};
0096             sr_.next(ec, f);
0097             if(ec)
0098             {
0099                 BOOST_ASSERT(! f.invoked);
0100 
0101                 BOOST_ASIO_HANDLER_LOCATION((
0102                     __FILE__, __LINE__,
0103                     "http::async_write_some"));
0104 
0105                 auto ex = asio::get_associated_immediate_executor(*this, s_.get_executor());
0106                 return net::dispatch(
0107                     ex,
0108                     beast::bind_front_handler(
0109                         std::move(*this), ec, 0));
0110             }
0111             if(f.invoked)
0112             {
0113                 // *this is now moved-from,
0114                 return;
0115             }
0116             // What else could it be?
0117             BOOST_ASSERT(sr_.is_done());
0118         }
0119 
0120         BOOST_ASIO_HANDLER_LOCATION((
0121             __FILE__, __LINE__,
0122             "http::async_write_some"));
0123 
0124         const auto ex = this->get_immediate_executor();
0125         return net::dispatch(
0126             ex,
0127             beast::bind_front_handler(
0128                 std::move(*this), ec, 0));
0129     }
0130 
0131     void
0132     operator()(
0133         error_code ec,
0134         std::size_t bytes_transferred)
0135     {
0136         if(! ec)
0137             sr_.consume(bytes_transferred);
0138         this->complete_now(ec, bytes_transferred);
0139     }
0140 };
0141 
0142 //------------------------------------------------------------------------------
0143 
0144 struct serializer_is_header_done
0145 {
0146     template<
0147         bool isRequest, class Body, class Fields>
0148     bool
0149     operator()(
0150         serializer<isRequest, Body, Fields>& sr) const
0151     {
0152         return sr.is_header_done();
0153     }
0154 };
0155 
0156 struct serializer_is_done
0157 {
0158     template<
0159         bool isRequest, class Body, class Fields>
0160     bool
0161     operator()(
0162         serializer<isRequest, Body, Fields>& sr) const
0163     {
0164         return sr.is_done();
0165     }
0166 };
0167 
0168 //------------------------------------------------------------------------------
0169 
0170 template<
0171     class Handler,
0172     class Stream,
0173     class Predicate,
0174     bool isRequest, class Body, class Fields>
0175 class write_op
0176     : public beast::async_base<
0177         Handler, beast::executor_type<Stream>>
0178     , public asio::coroutine
0179 {
0180     Stream& s_;
0181     serializer<isRequest, Body, Fields>& sr_;
0182     std::size_t bytes_transferred_ = 0;
0183     net::cancellation_state st_{this->
0184         beast::async_base<Handler, beast::executor_type<Stream>>
0185             ::get_cancellation_slot()};
0186 
0187 public:
0188     using cancellation_slot_type = net::cancellation_slot;
0189     cancellation_slot_type get_cancellation_slot() const noexcept
0190     {
0191         return st_.slot();
0192     }
0193 
0194 
0195     template<class Handler_>
0196     write_op(
0197         Handler_&& h,
0198         Stream& s,
0199         serializer<isRequest, Body, Fields>& sr)
0200         : async_base<
0201             Handler, beast::executor_type<Stream>>(
0202                 std::forward<Handler_>(h), s.get_executor())
0203         , s_(s)
0204         , sr_(sr)
0205     {
0206         (*this)();
0207     }
0208 
0209     void
0210     operator()(
0211         error_code ec = {},
0212         std::size_t bytes_transferred = 0)
0213     {
0214         BOOST_ASIO_CORO_REENTER(*this)
0215         {
0216             if(Predicate{}(sr_))
0217             {
0218                 BOOST_ASIO_CORO_YIELD
0219                 {
0220                     BOOST_ASIO_HANDLER_LOCATION((
0221                         __FILE__, __LINE__,
0222                         "http::async_write"));
0223 
0224                     const auto ex = this->get_immediate_executor();
0225                     net::dispatch(
0226                         ex,
0227                         std::move(*this));
0228                 }
0229                 goto upcall;
0230             }
0231             for(;;)
0232             {
0233                 BOOST_ASIO_CORO_YIELD
0234                 {
0235                     BOOST_ASIO_HANDLER_LOCATION((
0236                         __FILE__, __LINE__,
0237                         "http::async_write"));
0238 
0239                     beast::http::async_write_some(
0240                         s_, sr_, std::move(*this));
0241                 }
0242                 bytes_transferred_ += bytes_transferred;
0243                 if (!ec && st_.cancelled() != net::cancellation_type::none)
0244                 {
0245                     BOOST_BEAST_ASSIGN_EC(ec, net::error::operation_aborted);
0246                 }
0247                 if(ec)
0248                     goto upcall;
0249                 if(Predicate{}(sr_))
0250                     break;
0251             }
0252         upcall:
0253             this->complete_now(ec, bytes_transferred_);
0254         }
0255     }
0256 };
0257 
0258 //------------------------------------------------------------------------------
0259 
0260 template<
0261     class Handler,
0262     class Stream,
0263     bool isRequest, class Body, class Fields>
0264 class write_msg_op
0265     : public beast::stable_async_base<
0266         Handler, beast::executor_type<Stream>>
0267 {
0268     Stream& s_;
0269     serializer<isRequest, Body, Fields>& sr_;
0270 
0271 public:
0272     template<
0273         class Handler_,
0274         class... Args>
0275     write_msg_op(
0276         Handler_&& h,
0277         Stream& s,
0278         Args&&... args)
0279         : stable_async_base<
0280             Handler, beast::executor_type<Stream>>(
0281                 std::forward<Handler_>(h), s.get_executor())
0282         , s_(s)
0283         , sr_(beast::allocate_stable<
0284             serializer<isRequest, Body, Fields>>(
0285                 *this, std::forward<Args>(args)...))
0286     {
0287         (*this)();
0288     }
0289 
0290     void
0291     operator()()
0292     {
0293         BOOST_ASIO_HANDLER_LOCATION((
0294             __FILE__, __LINE__,
0295             "http::async_write(msg)"));
0296 
0297         async_write(s_, sr_, std::move(*this));
0298     }
0299 
0300     void
0301     operator()(
0302         error_code ec, std::size_t bytes_transferred)
0303     {
0304         this->complete_now(ec, bytes_transferred);
0305     }
0306 };
0307 
0308 struct run_write_some_op
0309 {
0310     template<
0311         class WriteHandler,
0312         class Stream,
0313         bool isRequest, class Body, class Fields>
0314     void
0315     operator()(
0316         WriteHandler&& h,
0317         Stream* s,
0318         serializer<isRequest, Body, Fields>* sr)
0319     {
0320         // If you get an error on the following line it means
0321         // that your handler does not meet the documented type
0322         // requirements for the handler.
0323 
0324         static_assert(
0325             beast::detail::is_invocable<WriteHandler,
0326             void(error_code, std::size_t)>::value,
0327             "WriteHandler type requirements not met");
0328 
0329         write_some_op<
0330             typename std::decay<WriteHandler>::type,
0331             Stream,
0332             isRequest, Body, Fields>(
0333                 std::forward<WriteHandler>(h), *s, *sr);
0334     }
0335 };
0336 
0337 struct run_write_op
0338 {
0339     template<
0340         class WriteHandler,
0341         class Stream,
0342         class Predicate,
0343         bool isRequest, class Body, class Fields>
0344     void
0345     operator()(
0346         WriteHandler&& h,
0347         Stream* s,
0348         Predicate const&,
0349         serializer<isRequest, Body, Fields>* sr)
0350     {
0351         // If you get an error on the following line it means
0352         // that your handler does not meet the documented type
0353         // requirements for the handler.
0354 
0355         static_assert(
0356             beast::detail::is_invocable<WriteHandler,
0357             void(error_code, std::size_t)>::value,
0358             "WriteHandler type requirements not met");
0359 
0360         write_op<
0361             typename std::decay<WriteHandler>::type,
0362             Stream,
0363             Predicate,
0364             isRequest, Body, Fields>(
0365                 std::forward<WriteHandler>(h), *s, *sr);
0366     }
0367 };
0368 
0369 struct run_write_msg_op
0370 {
0371     template<
0372         class WriteHandler,
0373         class Stream,
0374         bool isRequest, class Body, class Fields,
0375         class... Args>
0376     void
0377     operator()(
0378         WriteHandler&& h,
0379         Stream* s,
0380         message<isRequest, Body, Fields>* m,
0381         std::false_type,
0382         Args&&... args)
0383     {
0384         // If you get an error on the following line it means
0385         // that your handler does not meet the documented type
0386         // requirements for the handler.
0387 
0388         static_assert(
0389             beast::detail::is_invocable<WriteHandler,
0390             void(error_code, std::size_t)>::value,
0391             "WriteHandler type requirements not met");
0392 
0393         write_msg_op<
0394             typename std::decay<WriteHandler>::type,
0395             Stream,
0396             isRequest, Body, Fields>(
0397                 std::forward<WriteHandler>(h), *s, *m,
0398                 std::forward<Args>(args)...);
0399     }
0400 
0401     template<
0402         class WriteHandler,
0403         class Stream,
0404         bool isRequest, class Body, class Fields,
0405         class... Args>
0406     void
0407     operator()(
0408         WriteHandler&& h,
0409         Stream* s,
0410         message<isRequest, Body, Fields> const* m,
0411         std::true_type,
0412         Args&&... args)
0413     {
0414         // If you get an error on the following line it means
0415         // that your handler does not meet the documented type
0416         // requirements for the handler.
0417 
0418         static_assert(
0419             beast::detail::is_invocable<WriteHandler,
0420             void(error_code, std::size_t)>::value,
0421             "WriteHandler type requirements not met");
0422 
0423         write_msg_op<
0424             typename std::decay<WriteHandler>::type,
0425             Stream,
0426             isRequest, Body, Fields>(
0427                 std::forward<WriteHandler>(h), *s, *m,
0428                 std::forward<Args>(args)...);
0429     }
0430 };
0431 
0432 //------------------------------------------------------------------------------
0433 
0434 template<class Stream>
0435 class write_some_lambda
0436 {
0437     Stream& stream_;
0438 
0439 public:
0440     bool invoked = false;
0441     std::size_t bytes_transferred = 0;
0442 
0443     explicit
0444     write_some_lambda(Stream& stream)
0445         : stream_(stream)
0446     {
0447     }
0448 
0449     template<class ConstBufferSequence>
0450     void
0451     operator()(error_code& ec,
0452         ConstBufferSequence const& buffers)
0453     {
0454         invoked = true;
0455         bytes_transferred =
0456             stream_.write_some(buffers, ec);
0457     }
0458 };
0459 
0460 template<class Stream>
0461 class write_lambda
0462 {
0463     Stream& stream_;
0464 
0465 public:
0466     bool invoked = false;
0467     std::size_t bytes_transferred = 0;
0468 
0469     explicit
0470     write_lambda(Stream& stream)
0471         : stream_(stream)
0472     {
0473     }
0474 
0475     template<class ConstBufferSequence>
0476     void
0477     operator()(error_code& ec,
0478         ConstBufferSequence const& buffers)
0479     {
0480         invoked = true;
0481         bytes_transferred = net::write(
0482             stream_, buffers, ec);
0483     }
0484 };
0485 
0486 template<
0487     class SyncWriteStream,
0488     bool isRequest, class Body, class Fields>
0489 std::size_t
0490 write_some_impl(
0491     SyncWriteStream& stream,
0492     serializer<isRequest, Body, Fields>& sr,
0493     error_code& ec)
0494 {
0495     if(! sr.is_done())
0496     {
0497         write_some_lambda<SyncWriteStream> f{stream};
0498         sr.next(ec, f);
0499         if(ec)
0500             return f.bytes_transferred;
0501         if(f.invoked)
0502             sr.consume(f.bytes_transferred);
0503         return f.bytes_transferred;
0504     }
0505     ec = {};
0506     return 0;
0507 }
0508 
0509 template<
0510     class AsyncWriteStream,
0511     bool isRequest, class Body, class Fields,
0512     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0513 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0514 async_write_some_impl(
0515     AsyncWriteStream& stream,
0516     serializer<isRequest, Body, Fields>& sr,
0517     WriteHandler&& handler)
0518 {
0519     return net::async_initiate<
0520         WriteHandler,
0521         void(error_code, std::size_t)>(
0522             run_write_some_op{},
0523             handler,
0524             &stream,
0525             &sr);
0526 }
0527 
0528 } // detail
0529 
0530 //------------------------------------------------------------------------------
0531 
0532 template<
0533     class SyncWriteStream,
0534     bool isRequest, class Body, class Fields>
0535 std::size_t
0536 write_some(
0537     SyncWriteStream& stream,
0538     serializer<isRequest, Body, Fields>& sr)
0539 {
0540     static_assert(is_sync_write_stream<SyncWriteStream>::value,
0541         "SyncWriteStream type requirements not met");
0542     static_assert(is_body<Body>::value,
0543         "Body type requirements not met");
0544     static_assert(is_body_writer<Body>::value,
0545         "BodyWriter type requirements not met");
0546     error_code ec;
0547     auto const bytes_transferred =
0548         write_some(stream, sr, ec);
0549     if(ec)
0550         BOOST_THROW_EXCEPTION(system_error{ec});
0551     return bytes_transferred;
0552 }
0553 
0554 template<
0555     class SyncWriteStream,
0556     bool isRequest, class Body, class Fields>
0557 std::size_t
0558 write_some(
0559     SyncWriteStream& stream,
0560     serializer<isRequest, Body, Fields>& sr,
0561     error_code& ec)
0562 {
0563     static_assert(is_sync_write_stream<SyncWriteStream>::value,
0564         "SyncWriteStream type requirements not met");
0565     static_assert(is_body<Body>::value,
0566         "Body type requirements not met");
0567     static_assert(is_body_writer<Body>::value,
0568         "BodyWriter type requirements not met");
0569     return detail::write_some_impl(stream, sr, ec);
0570 }
0571 
0572 template<
0573     class AsyncWriteStream,
0574     bool isRequest, class Body, class Fields,
0575     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0576 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0577 async_write_some(
0578     AsyncWriteStream& stream,
0579     serializer<isRequest, Body, Fields>& sr,
0580     WriteHandler&& handler)
0581 {
0582     static_assert(is_async_write_stream<
0583             AsyncWriteStream>::value,
0584         "AsyncWriteStream type requirements not met");
0585     static_assert(is_body<Body>::value,
0586         "Body type requirements not met");
0587     static_assert(is_body_writer<Body>::value,
0588         "BodyWriter type requirements not met");
0589     return detail::async_write_some_impl(stream, sr,
0590         std::forward<WriteHandler>(handler));
0591 }
0592 
0593 //------------------------------------------------------------------------------
0594 
0595 template<
0596     class SyncWriteStream,
0597     bool isRequest, class Body, class Fields>
0598 std::size_t
0599 write_header(SyncWriteStream& stream,
0600     serializer<isRequest, Body, Fields>& sr)
0601 {
0602     static_assert(is_sync_write_stream<SyncWriteStream>::value,
0603         "SyncWriteStream type requirements not met");
0604     static_assert(is_body<Body>::value,
0605         "Body type requirements not met");
0606     static_assert(is_body_writer<Body>::value,
0607         "BodyWriter type requirements not met");
0608     error_code ec;
0609     auto const bytes_transferred =
0610         write_header(stream, sr, ec);
0611     if(ec)
0612         BOOST_THROW_EXCEPTION(system_error{ec});
0613     return bytes_transferred;
0614 }
0615 
0616 template<
0617     class SyncWriteStream,
0618     bool isRequest, class Body, class Fields>
0619 std::size_t
0620 write_header(
0621     SyncWriteStream& stream,
0622     serializer<isRequest, Body, Fields>& sr,
0623     error_code& ec)
0624 {
0625     static_assert(is_sync_write_stream<SyncWriteStream>::value,
0626         "SyncWriteStream type requirements not met");
0627     static_assert(is_body<Body>::value,
0628         "Body type requirements not met");
0629     static_assert(is_body_writer<Body>::value,
0630         "BodyWriter type requirements not met");
0631     sr.split(true);
0632     std::size_t bytes_transferred = 0;
0633     if(! sr.is_header_done())
0634     {
0635         detail::write_lambda<SyncWriteStream> f{stream};
0636         do
0637         {
0638             sr.next(ec, f);
0639             bytes_transferred += f.bytes_transferred;
0640             if(ec)
0641                 return bytes_transferred;
0642             BOOST_ASSERT(f.invoked);
0643             sr.consume(f.bytes_transferred);
0644         }
0645         while(! sr.is_header_done());
0646     }
0647     else
0648     {
0649         ec = {};
0650     }
0651     return bytes_transferred;
0652 }
0653 
0654 template<
0655     class AsyncWriteStream,
0656     bool isRequest, class Body, class Fields,
0657     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0658 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0659 async_write_header(
0660     AsyncWriteStream& stream,
0661     serializer<isRequest, Body, Fields>& sr,
0662     WriteHandler&& handler)
0663 {
0664     static_assert(is_async_write_stream<
0665             AsyncWriteStream>::value,
0666         "AsyncWriteStream type requirements not met");
0667     static_assert(is_body<Body>::value,
0668         "Body type requirements not met");
0669     static_assert(is_body_writer<Body>::value,
0670         "BodyWriter type requirements not met");
0671     sr.split(true);
0672     return net::async_initiate<
0673         WriteHandler,
0674         void(error_code, std::size_t)>(
0675             detail::run_write_op{},
0676             handler,
0677             &stream,
0678             detail::serializer_is_header_done{},
0679             &sr);
0680 }
0681 
0682 //------------------------------------------------------------------------------
0683 
0684 template<
0685     class SyncWriteStream,
0686     bool isRequest, class Body, class Fields>
0687 std::size_t
0688 write(
0689     SyncWriteStream& stream,
0690     serializer<isRequest, Body, Fields>& sr)
0691 {
0692     static_assert(is_sync_write_stream<SyncWriteStream>::value,
0693         "SyncWriteStream type requirements not met");
0694     error_code ec;
0695     auto const bytes_transferred =
0696         write(stream, sr, ec);
0697     if(ec)
0698         BOOST_THROW_EXCEPTION(system_error{ec});
0699     return bytes_transferred;
0700 }
0701 
0702 template<
0703     class SyncWriteStream,
0704     bool isRequest, class Body, class Fields>
0705 std::size_t
0706 write(
0707     SyncWriteStream& stream,
0708     serializer<isRequest, Body, Fields>& sr,
0709     error_code& ec)
0710 {
0711     static_assert(is_sync_write_stream<SyncWriteStream>::value,
0712         "SyncWriteStream type requirements not met");
0713     std::size_t bytes_transferred = 0;
0714     sr.split(false);
0715     for(;;)
0716     {
0717         bytes_transferred +=
0718             write_some(stream, sr, ec);
0719         if(ec)
0720             return bytes_transferred;
0721         if(sr.is_done())
0722             break;
0723     }
0724     return bytes_transferred;
0725 }
0726 
0727 template<
0728     class AsyncWriteStream,
0729     bool isRequest, class Body, class Fields,
0730     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0731 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0732 async_write(
0733     AsyncWriteStream& stream,
0734     serializer<isRequest, Body, Fields>& sr,
0735     WriteHandler&& handler)
0736 {
0737     static_assert(is_async_write_stream<
0738             AsyncWriteStream>::value,
0739         "AsyncWriteStream type requirements not met");
0740     static_assert(is_body<Body>::value,
0741         "Body type requirements not met");
0742     static_assert(is_body_writer<Body>::value,
0743         "BodyWriter type requirements not met");
0744     sr.split(false);
0745     return net::async_initiate<
0746         WriteHandler,
0747         void(error_code, std::size_t)>(
0748             detail::run_write_op{},
0749             handler,
0750             &stream,
0751             detail::serializer_is_done{},
0752             &sr);
0753 }
0754 
0755 //------------------------------------------------------------------------------
0756 
0757 template<
0758     class SyncWriteStream,
0759     bool isRequest, class Body, class Fields>
0760 typename std::enable_if<
0761     is_mutable_body_writer<Body>::value,
0762     std::size_t>::type
0763 write(
0764     SyncWriteStream& stream,
0765     message<isRequest, Body, Fields>& msg)
0766 {
0767     static_assert(is_sync_write_stream<SyncWriteStream>::value,
0768         "SyncWriteStream type requirements not met");
0769     static_assert(is_body<Body>::value,
0770         "Body type requirements not met");
0771     static_assert(is_body_writer<Body>::value,
0772         "BodyWriter type requirements not met");
0773     error_code ec;
0774     auto const bytes_transferred =
0775         write(stream, msg, ec);
0776     if(ec)
0777         BOOST_THROW_EXCEPTION(system_error{ec});
0778     return bytes_transferred;
0779 }
0780 
0781 template<
0782     class SyncWriteStream,
0783     bool isRequest, class Body, class Fields>
0784 typename std::enable_if<
0785     ! is_mutable_body_writer<Body>::value,
0786     std::size_t>::type
0787 write(
0788     SyncWriteStream& stream,
0789     message<isRequest, Body, Fields> const& msg)
0790 {
0791     static_assert(is_sync_write_stream<SyncWriteStream>::value,
0792         "SyncWriteStream type requirements not met");
0793     static_assert(is_body<Body>::value,
0794         "Body type requirements not met");
0795     static_assert(is_body_writer<Body>::value,
0796         "BodyWriter type requirements not met");
0797     error_code ec;
0798     auto const bytes_transferred =
0799         write(stream, msg, ec);
0800     if(ec)
0801         BOOST_THROW_EXCEPTION(system_error{ec});
0802     return bytes_transferred;
0803 }
0804 
0805 template<
0806     class SyncWriteStream,
0807     bool isRequest, class Body, class Fields>
0808 typename std::enable_if<
0809     is_mutable_body_writer<Body>::value,
0810     std::size_t>::type
0811 write(
0812     SyncWriteStream& stream,
0813     message<isRequest, Body, Fields>& msg,
0814     error_code& ec)
0815 {
0816     static_assert(is_sync_write_stream<SyncWriteStream>::value,
0817         "SyncWriteStream type requirements not met");
0818     static_assert(is_body<Body>::value,
0819         "Body type requirements not met");
0820     static_assert(is_body_writer<Body>::value,
0821         "BodyWriter type requirements not met");
0822     serializer<isRequest, Body, Fields> sr{msg};
0823     return write(stream, sr, ec);
0824 }
0825 
0826 template<
0827     class SyncWriteStream,
0828     bool isRequest, class Body, class Fields>
0829 typename std::enable_if<
0830     ! is_mutable_body_writer<Body>::value,
0831     std::size_t>::type
0832 write(
0833     SyncWriteStream& stream,
0834     message<isRequest, Body, Fields> const& msg,
0835     error_code& ec)
0836 {
0837     static_assert(is_sync_write_stream<SyncWriteStream>::value,
0838         "SyncWriteStream type requirements not met");
0839     static_assert(is_body<Body>::value,
0840         "Body type requirements not met");
0841     static_assert(is_body_writer<Body>::value,
0842         "BodyWriter type requirements not met");
0843     serializer<isRequest, Body, Fields> sr{msg};
0844     return write(stream, sr, ec);
0845 }
0846 
0847 template<
0848     class AsyncWriteStream,
0849     bool isRequest, class Body, class Fields,
0850     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0851 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0852 async_write(
0853     AsyncWriteStream& stream,
0854     message<isRequest, Body, Fields>& msg,
0855     WriteHandler&& handler,
0856     typename std::enable_if<
0857         is_mutable_body_writer<Body>::value>::type*)
0858 {
0859     static_assert(
0860         is_async_write_stream<AsyncWriteStream>::value,
0861         "AsyncWriteStream type requirements not met");
0862     static_assert(is_body<Body>::value,
0863         "Body type requirements not met");
0864     static_assert(is_body_writer<Body>::value,
0865         "BodyWriter type requirements not met");
0866     return net::async_initiate<
0867         WriteHandler,
0868         void(error_code, std::size_t)>(
0869             detail::run_write_msg_op{},
0870             handler,
0871             &stream,
0872             &msg,
0873             std::false_type{});
0874 }
0875 
0876 template<
0877     class AsyncWriteStream,
0878     bool isRequest, class Body, class Fields,
0879     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0880 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0881 async_write(
0882     AsyncWriteStream& stream,
0883     message<isRequest, Body, Fields> const& msg,
0884     WriteHandler&& handler,
0885     typename std::enable_if<
0886         ! is_mutable_body_writer<Body>::value>::type*)
0887 {
0888     static_assert(
0889         is_async_write_stream<AsyncWriteStream>::value,
0890         "AsyncWriteStream type requirements not met");
0891     static_assert(is_body<Body>::value,
0892         "Body type requirements not met");
0893     static_assert(is_body_writer<Body>::value,
0894         "BodyWriter type requirements not met");
0895     return net::async_initiate<
0896         WriteHandler,
0897         void(error_code, std::size_t)>(
0898             detail::run_write_msg_op{},
0899             handler,
0900             &stream,
0901             &msg,
0902             std::true_type{});
0903 }
0904 
0905 //------------------------------------------------------------------------------
0906 
0907 namespace detail {
0908 
0909 template<class Serializer>
0910 class write_ostream_lambda
0911 {
0912     std::ostream& os_;
0913     Serializer& sr_;
0914 
0915 public:
0916     write_ostream_lambda(std::ostream& os,
0917             Serializer& sr)
0918         : os_(os)
0919         , sr_(sr)
0920     {
0921     }
0922 
0923     template<class ConstBufferSequence>
0924     void
0925     operator()(error_code& ec,
0926         ConstBufferSequence const& buffers) const
0927     {
0928         ec = {};
0929         if(os_.fail())
0930             return;
0931         std::size_t bytes_transferred = 0;
0932         for(auto b : beast::buffers_range_ref(buffers))
0933         {
0934             os_.write(static_cast<char const*>(
0935                 b.data()), b.size());
0936             if(os_.fail())
0937                 return;
0938             bytes_transferred += b.size();
0939         }
0940         sr_.consume(bytes_transferred);
0941     }
0942 };
0943 
0944 } // detail
0945 
0946 template<class Fields>
0947 std::ostream&
0948 operator<<(std::ostream& os,
0949     header<true, Fields> const& h)
0950 {
0951     typename Fields::writer fr{
0952         h, h.version(), h.method()};
0953     return os << beast::make_printable(fr.get());
0954 }
0955 
0956 template<class Fields>
0957 std::ostream&
0958 operator<<(std::ostream& os,
0959     header<false, Fields> const& h)
0960 {
0961     typename Fields::writer fr{
0962         h, h.version(), h.result_int()};
0963     return os << beast::make_printable(fr.get());
0964 }
0965 
0966 template<bool isRequest, class Body, class Fields>
0967 std::ostream&
0968 operator<<(std::ostream& os,
0969     message<isRequest, Body, Fields> const& msg)
0970 {
0971     static_assert(is_body<Body>::value,
0972         "Body type requirements not met");
0973     static_assert(is_body_writer<Body>::value,
0974         "BodyWriter type requirements not met");
0975     serializer<isRequest, Body, Fields> sr{msg};
0976     error_code ec;
0977     detail::write_ostream_lambda<decltype(sr)> f{os, sr};
0978     do
0979     {
0980         sr.next(ec, f);
0981         if(os.fail())
0982             break;
0983         if(ec)
0984         {
0985             os.setstate(std::ios::failbit);
0986             break;
0987         }
0988     }
0989     while(! sr.is_done());
0990     return os;
0991 }
0992 
0993 } // http
0994 } // beast
0995 } // boost
0996 
0997 #endif