Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:24:14

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