// // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP #define BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP #include #include #include #include #include #include #include namespace boost { namespace beast { template struct flat_stream::ops { template class write_op : public async_base> { public: template< class ConstBufferSequence, class Handler_> write_op( Handler_&& h, flat_stream& s, ConstBufferSequence const& b) : async_base>( std::forward(h), s.get_executor()) { auto const result = flatten(b, max_size); if(result.flatten) { s.buffer_.clear(); s.buffer_.commit(net::buffer_copy( s.buffer_.prepare(result.size), b, result.size)); s.stream_.async_write_some( s.buffer_.data(), std::move(*this)); } else { s.buffer_.clear(); s.buffer_.shrink_to_fit(); s.stream_.async_write_some( beast::buffers_prefix( result.size, b), std::move(*this)); } } void operator()( boost::system::error_code ec, std::size_t bytes_transferred) { this->complete_now(ec, bytes_transferred); } }; struct run_write_op { template void operator()( WriteHandler&& h, flat_stream* s, Buffers const& b) { // If you get an error on the following line it means // that your handler does not meet the documented type // requirements for the handler. static_assert( beast::detail::is_invocable::value, "WriteHandler type requirements not met"); write_op< typename std::decay::type>( std::forward(h), *s, b); } }; }; //------------------------------------------------------------------------------ template template flat_stream:: flat_stream(Args&&... args) : stream_(std::forward(args)...) { } template template std::size_t flat_stream:: read_some(MutableBufferSequence const& buffers) { static_assert(boost::beast::is_sync_read_stream::value, "SyncReadStream type requirements not met"); static_assert(net::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence type requirements not met"); error_code ec; auto n = read_some(buffers, ec); if(ec) BOOST_THROW_EXCEPTION(boost::system::system_error{ec}); return n; } template template std::size_t flat_stream:: read_some(MutableBufferSequence const& buffers, error_code& ec) { static_assert(boost::beast::is_sync_read_stream::value, "SyncReadStream type requirements not met"); static_assert(net::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence type requirements not met"); return stream_.read_some(buffers, ec); } template template< class MutableBufferSequence, class ReadHandler> BOOST_BEAST_ASYNC_RESULT2(ReadHandler) flat_stream:: async_read_some( MutableBufferSequence const& buffers, ReadHandler&& handler) { static_assert(boost::beast::is_async_read_stream::value, "AsyncReadStream type requirements not met"); static_assert(net::is_mutable_buffer_sequence< MutableBufferSequence >::value, "MutableBufferSequence type requirements not met"); return stream_.async_read_some( buffers, std::forward(handler)); } template template std::size_t flat_stream:: write_some(ConstBufferSequence const& buffers) { static_assert(boost::beast::is_sync_write_stream::value, "SyncWriteStream type requirements not met"); static_assert(net::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence type requirements not met"); error_code ec; auto n = write_some(buffers, ec); if(ec) BOOST_THROW_EXCEPTION(boost::system::system_error{ec}); return n; } template template std::size_t flat_stream:: stack_write_some( std::size_t size, ConstBufferSequence const& buffers, error_code& ec) { static_buffer b; b.commit(net::buffer_copy( b.prepare(size), buffers)); return stream_.write_some(b.data(), ec); } template template std::size_t flat_stream:: write_some(ConstBufferSequence const& buffers, error_code& ec) { static_assert(boost::beast::is_sync_write_stream::value, "SyncWriteStream type requirements not met"); static_assert(net::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence type requirements not met"); auto const result = flatten(buffers, max_size); if(result.flatten) { if(result.size <= max_stack) return stack_write_some(result.size, buffers, ec); buffer_.clear(); buffer_.commit(net::buffer_copy( buffer_.prepare(result.size), buffers)); return stream_.write_some(buffer_.data(), ec); } buffer_.clear(); buffer_.shrink_to_fit(); return stream_.write_some( boost::beast::buffers_prefix(result.size, buffers), ec); } template template< class ConstBufferSequence, class WriteHandler> BOOST_BEAST_ASYNC_RESULT2(WriteHandler) flat_stream:: async_write_some( ConstBufferSequence const& buffers, WriteHandler&& handler) { static_assert(boost::beast::is_async_write_stream::value, "AsyncWriteStream type requirements not met"); static_assert(net::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence type requirements not met"); return net::async_initiate< WriteHandler, void(error_code, std::size_t)>( typename ops::run_write_op{}, handler, this, buffers); } template void teardown( boost::beast::role_type role, flat_stream& s, error_code& ec) { using boost::beast::websocket::teardown; teardown(role, s.next_layer(), ec); } template void async_teardown( boost::beast::role_type role, flat_stream& s, TeardownHandler&& handler) { using boost::beast::websocket::async_teardown; async_teardown(role, s.next_layer(), std::move(handler)); } } // beast } // boost #endif