Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-15 08:28:59

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