Refactor type_traits (API Change):

fix #373

* concepts.hpp is renamed to type_traits.hpp

* Body reader and writer concepts are renamed
This commit is contained in:
Vinnie Falco
2017-07-20 08:12:17 -07:00
parent 3664329ea7
commit 75b0571e83
32 changed files with 435 additions and 462 deletions
+2 -2
View File
@@ -12,10 +12,10 @@
namespace beast {
/// The type of string_view used by the library
/// The type of string view used by the library
using string_view = boost::string_ref;
/// The type of basic_string_view used by the library
/// The type of basic string view used by the library
template<class CharT, class Traits>
using basic_string_view =
boost::basic_string_ref<CharT, Traits>;
+5 -5
View File
@@ -8,7 +8,7 @@
#ifndef BEAST_HTTP_BUFFER_BODY_HPP
#define BEAST_HTTP_BUFFER_BODY_HPP
#include <beast/http/concepts.hpp>
#include <beast/http/type_traits.hpp>
#include <beast/http/error.hpp>
#include <beast/http/message.hpp>
#include <boost/optional.hpp>
@@ -68,10 +68,10 @@ struct buffer_body
std::pair<boost::optional<ConstBufferSequence>, bool>;
#if BEAST_DOXYGEN
/// The algorithm used when serializing this body
using writer = implementation_defined;
/// The algorithm to obtain buffers representing the body
using reader = implementation_defined;
#else
class writer
class reader
{
bool toggle_ = false;
value_type const& body_;
@@ -84,7 +84,7 @@ struct buffer_body
template<bool isRequest, class Fields>
explicit
writer(message<isRequest, buffer_body,
reader(message<isRequest, buffer_body,
Fields> const& msg)
: body_(msg.body)
{
-183
View File
@@ -1,183 +0,0 @@
//
// Copyright (c) 2013-2017 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)
//
#ifndef BEAST_HTTP_CONCEPTS_HPP
#define BEAST_HTTP_CONCEPTS_HPP
#include <beast/config.hpp>
#include <beast/core/error.hpp>
#include <beast/core/string_view.hpp>
#include <beast/core/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/optional.hpp>
#include <type_traits>
#include <utility>
namespace beast {
namespace http {
template<bool, class, class>
struct message;
namespace detail {
struct fields_model
{
string_view method() const;
string_view reason() const;
string_view target() const;
};
struct write_function
{
template<class ConstBufferSequence>
void
operator()(ConstBufferSequence const&);
};
template<class T, class = beast::detail::void_t<>>
struct has_value_type : std::false_type {};
template<class T>
struct has_value_type<T, beast::detail::void_t<
typename T::value_type
> > : std::true_type {};
template<class T, class = beast::detail::void_t<>>
struct has_content_length : std::false_type {};
template<class T>
struct has_content_length<T, beast::detail::void_t<decltype(
std::declval<T>().content_length()
)> > : std::true_type
{
static_assert(std::is_convertible<
decltype(std::declval<T>().content_length()),
std::uint64_t>::value,
"Writer::content_length requirements not met");
};
} // detail
/// Determine if `T` meets the requirements of @b Body.
template<class T>
#if BEAST_DOXYGEN
struct is_Body : std::integral_constant<bool, ...>{};
#else
using is_Body = detail::has_value_type<T>;
#endif
/** Determine if a @b Body has a nested type `reader`.
@tparam T The type to check, which must meet the
requirements of @b Body.
*/
#if BEAST_DOXYGEN
template<class T>
struct has_reader : std::integral_constant<bool, ...>{};
#else
template<class T, class = beast::detail::void_t<>>
struct has_reader : std::false_type {};
template<class T>
struct has_reader<T, beast::detail::void_t<
typename T::reader
> > : std::true_type {};
#endif
/** Determine if a @b Body has a nested type `writer`.
@tparam T The type to check, which must meet the
requirements of @b Body.
*/
#if BEAST_DOXYGEN
template<class T>
struct has_writer : std::integral_constant<bool, ...>{};
#else
template<class T, class = beast::detail::void_t<>>
struct has_writer : std::false_type {};
template<class T>
struct has_writer<T, beast::detail::void_t<
typename T::writer
> > : std::true_type {};
#endif
/** Determine if `T` meets the requirements of @b Reader for `M`.
@tparam T The type to test.
@tparam M The message type to test with, which must be of
type `message`.
*/
#if BEAST_DOXYGEN
template<class T, class M>
struct is_Reader : std::integral_constant<bool, ...> {};
#else
template<class T, class M, class = beast::detail::void_t<>>
struct is_Reader : std::true_type {};
template<class T, class M>
struct is_Reader<T, M, beast::detail::void_t<decltype(
std::declval<typename T::mutable_buffers_type>(),
std::declval<T>().init(
std::declval<boost::optional<std::uint64_t>>()),
std::declval<T>().prepare(
std::declval<std::size_t>()),
std::declval<T>().commit(
std::declval<std::size_t>()),
std::declval<T>().finish()
)> > : std::integral_constant<bool,
is_mutable_buffer_sequence<
typename T::mutable_buffers_type>::value &&
std::is_convertible<decltype(
std::declval<T>().prepare(
std::declval<std::size_t>())),
typename T::mutable_buffers_type
>::value>
{
static_assert(std::is_same<
typename M::body_type::reader, T>::value,
"Mismatched reader and message");
};
#endif
/** Determine if a @b Body type has a writer which meets requirements.
@tparam T The body type to test.
*/
#if BEAST_DOXYGEN
template<class T>
struct is_Writer : std::integral_constant<bool, ...> {};
#else
template<class T, class = void>
struct is_Writer : std::false_type {};
template<class T>
struct is_Writer<T, beast::detail::void_t<
typename T::writer,
typename T::writer::const_buffers_type,
decltype(
std::declval<typename T::writer&>().init(std::declval<error_code&>()),
std::declval<boost::optional<std::pair<
typename T::writer::const_buffers_type, bool>>&>() =
std::declval<typename T::writer>().get(std::declval<error_code&>()),
(void)0)>> : std::integral_constant<bool,
is_const_buffer_sequence<
typename T::writer::const_buffers_type>::value &&
std::is_constructible<typename T::writer,
message<true, T, detail::fields_model> const& >::value
>
{
};
#endif
} // http
} // beast
#endif
+8 -8
View File
@@ -29,10 +29,10 @@ struct basic_dynamic_body
using value_type = DynamicBuffer;
#if BEAST_DOXYGEN
/// The algorithm used when parsing this body.
using reader = implementation_defined;
/// The algorithm used store buffers in this body
using writer = implementation_defined;
#else
class reader
class writer
{
value_type& body_;
@@ -44,7 +44,7 @@ struct basic_dynamic_body
template<bool isRequest, class Fields>
explicit
reader(message<isRequest,
writer(message<isRequest,
basic_dynamic_body, Fields>& msg)
: body_(msg.body)
{
@@ -80,10 +80,10 @@ struct basic_dynamic_body
#endif
#if BEAST_DOXYGEN
/// The algorithm used when serializing this body.
using writer = implementation_defined;
/// The algorithm to obtain buffers representing the body
using reader = implementation_defined;
#else
class writer
class reader
{
DynamicBuffer const& body_;
@@ -95,7 +95,7 @@ struct basic_dynamic_body
template<bool isRequest, class Fields>
explicit
writer(message<
reader(message<
isRequest, basic_dynamic_body, Fields> const& m)
: body_(m.body)
{
+4 -4
View File
@@ -29,10 +29,10 @@ struct empty_body
};
#if BEAST_DOXYGEN
/// The algorithm used when serializing this body.
using writer = implementation_defined;
/// The algorithm to obtain buffers representing the body
using reader = implementation_defined;
#else
struct writer
struct reader
{
using is_deferred = std::false_type;
@@ -41,7 +41,7 @@ struct empty_body
template<bool isRequest, class Fields>
explicit
writer(message<
reader(message<
isRequest, empty_body, Fields> const&)
{
}
+4 -7
View File
@@ -8,7 +8,7 @@
#ifndef BEAST_HTTP_IMPL_ASYNC_READ_IPP_HPP
#define BEAST_HTTP_IMPL_ASYNC_READ_IPP_HPP
#include <beast/http/concepts.hpp>
#include <beast/http/type_traits.hpp>
#include <beast/http/error.hpp>
#include <beast/http/message_parser.hpp>
#include <beast/http/read.hpp>
@@ -714,13 +714,10 @@ async_read(
"AsyncReadStream requirements not met");
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_reader<Body>::value,
"Body has no reader");
static_assert(is_Reader<typename Body::reader,
message<isRequest, Body, Fields>>::value,
"Reader requirements not met");
static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met");
async_completion<ReadHandler,
void(error_code)> init{handler};
detail::read_message_op<AsyncReadStream, DynamicBuffer,
+6 -8
View File
@@ -10,7 +10,7 @@
#include <beast/core/error.hpp>
#include <beast/core/string_view.hpp>
#include <beast/http/concepts.hpp>
#include <beast/http/type_traits.hpp>
#include <beast/http/rfc7230.hpp>
#include <beast/core/detail/ci_char_traits.hpp>
#include <beast/core/detail/type_traits.hpp>
@@ -130,7 +130,7 @@ prepare_content_length(prepare_info& pi,
message<isRequest, Body, Fields> const& msg,
std::true_type)
{
typename Body::writer w(msg);
typename Body::reader w{msg};
// VFALCO This is a design problem!
error_code ec;
w.init(ec);
@@ -159,15 +159,13 @@ prepare(message<isRequest, Body, Fields>& msg,
Options&&... options)
{
// VFALCO TODO
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_writer<Body>::value,
"Body has no writer");
static_assert(is_Writer<Body>::value,
"Writer requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met");
detail::prepare_info pi;
detail::prepare_content_length(pi, msg,
detail::has_content_length<typename Body::writer>{});
detail::has_content_length<typename Body::reader>{});
detail::prepare_options(pi, msg,
std::forward<Options>(options)...);
+7 -13
View File
@@ -8,7 +8,7 @@
#ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
#define BEAST_HTTP_IMPL_READ_IPP_HPP
#include <beast/http/concepts.hpp>
#include <beast/http/type_traits.hpp>
#include <beast/http/error.hpp>
#include <beast/http/message_parser.hpp>
#include <beast/http/read.hpp>
@@ -291,13 +291,10 @@ read(
"SyncReadStream requirements not met");
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_reader<Body>::value,
"Body has no reader");
static_assert(is_Reader<typename Body::reader,
message<isRequest, Body, Fields>>::value,
"Reader requirements not met");
static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met");
error_code ec;
beast::http::read(stream, buffer, msg, ec);
if(ec)
@@ -319,13 +316,10 @@ read(
"SyncReadStream requirements not met");
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_reader<Body>::value,
"Body has no reader");
static_assert(is_Reader<typename Body::reader,
message<isRequest, Body, Fields>>::value,
"Reader requirements not met");
static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met");
message_parser<isRequest, Body, Fields> p;
beast::http::read(stream, buffer, p, ec);
if(ec)
+50 -64
View File
@@ -8,7 +8,7 @@
#ifndef BEAST_HTTP_IMPL_WRITE_IPP
#define BEAST_HTTP_IMPL_WRITE_IPP
#include <beast/http/concepts.hpp>
#include <beast/http/type_traits.hpp>
#include <beast/http/error.hpp>
#include <beast/core/buffer_cat.hpp>
#include <beast/core/buffer_prefix.hpp>
@@ -183,12 +183,12 @@ operator()(error_code ec,
{
if(w_.split_)
goto go_header_only;
w_.wr_.emplace(w_.m_);
w_.wr_->init(ec);
w_.rd_.emplace(w_.m_);
w_.rd_->init(ec);
if(ec)
return s_.get_io_service().post(
bind_handler(std::move(*this), ec, 0));
auto result = w_.wr_->get(ec);
auto result = w_.rd_->get(ec);
if(ec)
{
// Can't use need_more when ! is_deferred
@@ -248,9 +248,9 @@ operator()(error_code ec,
w_.header_done_ = true;
if(! is_deferred::value)
goto go_complete;
BOOST_ASSERT(! w_.wr_);
w_.wr_.emplace(w_.m_);
w_.wr_->init(ec);
BOOST_ASSERT(! w_.rd_);
w_.rd_.emplace(w_.m_);
w_.rd_->init(ec);
if(ec)
goto upcall;
w_.s_ = do_body;
@@ -258,7 +258,7 @@ operator()(error_code ec,
case do_body:
{
auto result = w_.wr_->get(ec);
auto result = w_.rd_->get(ec);
if(ec)
return s_.get_io_service().post(
bind_handler(std::move(*this), ec, 0));
@@ -303,12 +303,12 @@ operator()(error_code ec,
{
if(w_.split_)
goto go_header_only_c;
w_.wr_.emplace(w_.m_);
w_.wr_->init(ec);
w_.rd_.emplace(w_.m_);
w_.rd_->init(ec);
if(ec)
return s_.get_io_service().post(
bind_handler(std::move(*this), ec, 0));
auto result = w_.wr_->get(ec);
auto result = w_.rd_->get(ec);
if(ec)
{
// Can't use need_more when ! is_deferred
@@ -382,9 +382,9 @@ operator()(error_code ec,
w_.s_ = do_final_c;
break;
}
BOOST_ASSERT(! w_.wr_);
w_.wr_.emplace(w_.m_);
w_.wr_->init(ec);
BOOST_ASSERT(! w_.rd_);
w_.rd_.emplace(w_.m_);
w_.rd_->init(ec);
if(ec)
goto upcall;
w_.s_ = do_body_c;
@@ -392,7 +392,7 @@ operator()(error_code ec,
case do_body_c:
{
auto result = w_.wr_->get(ec);
auto result = w_.rd_->get(ec);
if(ec)
return s_.get_io_service().post(
bind_handler(std::move(*this),
@@ -528,12 +528,10 @@ write_some(SyncWriteStream& stream)
static_assert(
is_sync_write_stream<SyncWriteStream>::value,
"SyncWriteStream requirements not met");
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_writer<Body>::value,
"Body::writer requirements not met");
static_assert(is_Writer<Body>::value,
"Writer requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met");
error_code ec;
write_some(stream, ec);
if(ec)
@@ -551,12 +549,10 @@ write_some(SyncWriteStream& stream, error_code &ec)
static_assert(
is_sync_write_stream<SyncWriteStream>::value,
"SyncWriteStream requirements not met");
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_writer<Body>::value,
"Body::writer requirements not met");
static_assert(is_Writer<Body>::value,
"Writer requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met");
using boost::asio::buffer_size;
switch(s_)
@@ -565,11 +561,11 @@ write_some(SyncWriteStream& stream, error_code &ec)
{
if(split_)
goto go_header_only;
wr_.emplace(m_);
wr_->init(ec);
rd_.emplace(m_);
rd_->init(ec);
if(ec)
return;
auto result = wr_->get(ec);
auto result = rd_->get(ec);
if(ec)
{
// Can't use need_more when ! is_deferred
@@ -624,9 +620,9 @@ write_some(SyncWriteStream& stream, error_code &ec)
header_done_ = true;
if(! is_deferred::value)
goto go_complete;
BOOST_ASSERT(! wr_);
wr_.emplace(m_);
wr_->init(ec);
BOOST_ASSERT(! rd_);
rd_.emplace(m_);
rd_->init(ec);
if(ec)
return;
s_ = do_body;
@@ -635,7 +631,7 @@ write_some(SyncWriteStream& stream, error_code &ec)
case do_body:
{
auto result = wr_->get(ec);
auto result = rd_->get(ec);
if(ec)
return;
if(! result)
@@ -670,11 +666,11 @@ write_some(SyncWriteStream& stream, error_code &ec)
{
if(split_)
goto go_header_only_c;
wr_.emplace(m_);
wr_->init(ec);
rd_.emplace(m_);
rd_->init(ec);
if(ec)
return;
auto result = wr_->get(ec);
auto result = rd_->get(ec);
if(ec)
{
// Can't use need_more when ! is_deferred
@@ -742,9 +738,9 @@ write_some(SyncWriteStream& stream, error_code &ec)
s_ = do_final_c;
break;
}
BOOST_ASSERT(! wr_);
wr_.emplace(m_);
wr_->init(ec);
BOOST_ASSERT(! rd_);
rd_.emplace(m_);
rd_->init(ec);
if(ec)
return;
s_ = do_body_c;
@@ -753,7 +749,7 @@ write_some(SyncWriteStream& stream, error_code &ec)
case do_body_c:
{
auto result = wr_->get(ec);
auto result = rd_->get(ec);
if(ec)
return;
if(! result)
@@ -856,12 +852,10 @@ async_write_some(AsyncWriteStream& stream,
{
static_assert(is_async_write_stream<AsyncWriteStream>::value,
"AsyncWriteStream requirements not met");
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_writer<Body>::value,
"Body::writer requirements not met");
static_assert(is_Writer<Body>::value,
"Writer requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met");
async_completion<WriteHandler,
void(error_code)> init{handler};
async_op<AsyncWriteStream, handler_type<
@@ -984,12 +978,10 @@ write(SyncWriteStream& stream,
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
"SyncWriteStream requirements not met");
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_writer<Body>::value,
"Body has no writer");
static_assert(is_Writer<Body>::value,
"Writer requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met");
error_code ec;
write(stream, msg, ec);
if(ec)
@@ -1005,12 +997,10 @@ write(SyncWriteStream& stream,
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
"SyncWriteStream requirements not met");
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_writer<Body>::value,
"Body has no writer");
static_assert(is_Writer<Body>::value,
"Writer requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met");
auto ws = make_write_stream(msg);
for(;;)
{
@@ -1034,12 +1024,10 @@ async_write(AsyncWriteStream& stream,
static_assert(
is_async_write_stream<AsyncWriteStream>::value,
"AsyncWriteStream requirements not met");
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_writer<Body>::value,
"Body has no writer");
static_assert(is_Writer<Body>::value,
"Writer requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met");
async_completion<WriteHandler,
void(error_code)> init{handler};
detail::write_op<AsyncWriteStream, handler_type<
@@ -1068,12 +1056,10 @@ std::ostream&
operator<<(std::ostream& os,
message<isRequest, Body, Fields> const& msg)
{
static_assert(is_Body<Body>::value,
static_assert(is_body<Body>::value,
"Body requirements not met");
static_assert(has_writer<Body>::value,
"Body has no writer");
static_assert(is_Writer<Body>::value,
"Writer requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met");
beast::detail::sync_ostream oss{os};
error_code ec;
write(oss, msg, ec);
+21 -21
View File
@@ -37,16 +37,16 @@ namespace http {
template<bool isRequest, class Body, class Fields>
class message_parser
: public basic_parser<isRequest,
Body::reader::is_direct,
Body::writer::is_direct,
message_parser<isRequest, Body, Fields>>
{
using base_type = basic_parser<isRequest, true,
message_parser<isRequest, Body, Fields>>;
using reader_type = typename Body::reader;
using writer_type = typename Body::writer;
message<isRequest, Body, Fields> m_;
boost::optional<typename Body::reader> r_;
boost::optional<writer_type> wr_;
public:
/// The type of message returned by the parser
@@ -54,7 +54,7 @@ public:
/// The type of buffer sequence representing the body
using mutable_buffers_type =
typename reader_type::mutable_buffers_type;
typename writer_type::mutable_buffers_type;
/// Constructor (default)
message_parser() = default;
@@ -152,7 +152,7 @@ public:
private:
friend class basic_parser<
isRequest, Body::reader::is_direct,
isRequest, Body::writer::is_direct,
message_parser>;
void
@@ -192,22 +192,22 @@ private:
void
on_body()
{
r_.emplace(m_);
r_->init();
wr_.emplace(m_);
wr_->init();
}
void
on_body(std::uint64_t content_length)
{
r_.emplace(m_);
r_->init(content_length);
wr_.emplace(m_);
wr_->init(content_length);
}
void
on_body(error_code& ec)
{
r_.emplace(m_);
r_->init(ec);
wr_.emplace(m_);
wr_->init(ec);
if(ec)
return;
}
@@ -216,8 +216,8 @@ private:
on_body(std::uint64_t content_length,
error_code& ec)
{
r_.emplace(m_);
r_->init(content_length, ec);
wr_.emplace(m_);
wr_->init(content_length, ec);
if(ec)
return;
}
@@ -226,20 +226,20 @@ private:
on_data(string_view const& s,
error_code& ec)
{
BOOST_STATIC_ASSERT(! Body::reader::is_direct);
r_->write(s, ec);
BOOST_STATIC_ASSERT(! Body::writer::is_direct);
wr_->write(s, ec);
}
mutable_buffers_type
on_prepare(std::size_t n)
{
return r_->prepare(n);
return wr_->prepare(n);
}
void
on_commit(std::size_t n)
{
r_->commit(n);
wr_->commit(n);
}
void
@@ -252,24 +252,24 @@ private:
void
on_complete(error_code& ec)
{
if(r_)
if(wr_)
do_on_complete(ec,
std::integral_constant<bool,
Body::reader::is_direct>{});
Body::writer::is_direct>{});
}
void
do_on_complete(
error_code& ec, std::true_type)
{
r_->finish();
wr_->finish();
}
void
do_on_complete(
error_code& ec, std::false_type)
{
r_->finish(ec);
wr_->finish(ec);
if(ec)
return;
}
+8 -8
View File
@@ -31,10 +31,10 @@ struct string_body
using value_type = std::string;
#if BEAST_DOXYGEN
/// The algorithm used when parsing this body.
using reader = implementation_defined;
/// The algorithm used store buffers in this body
using writer = implementation_defined;
#else
class reader
class writer
{
value_type& body_;
std::size_t len_ = 0;
@@ -47,7 +47,7 @@ struct string_body
template<bool isRequest, class Fields>
explicit
reader(message<isRequest,
writer(message<isRequest,
string_body, Fields>& m)
: body_(m.body)
{
@@ -93,10 +93,10 @@ struct string_body
#endif
#if BEAST_DOXYGEN
/// The algorithm used when serializing this body.
using writer = implementation_defined;
/// The algorithm to obtain buffers representing the body
using reader = implementation_defined;
#else
class writer
class reader
{
value_type const& body_;
@@ -108,7 +108,7 @@ struct string_body
template<bool isRequest, class Fields>
explicit
writer(message<
reader(message<
isRequest, string_body, Fields> const& msg)
: body_(msg.body)
{
+146
View File
@@ -0,0 +1,146 @@
//
// Copyright (c) 2013-2017 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)
//
#ifndef BEAST_HTTP_TYPE_TRAITS_HPP
#define BEAST_HTTP_TYPE_TRAITS_HPP
#include <beast/config.hpp>
#include <beast/core/error.hpp>
#include <beast/core/string_view.hpp>
#include <beast/core/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/optional.hpp>
#include <type_traits>
#include <utility>
namespace beast {
namespace http {
template<bool, class, class>
struct message;
namespace detail {
struct fields_model
{
string_view method() const;
string_view reason() const;
string_view target() const;
};
template<class T, class = beast::detail::void_t<>>
struct has_value_type : std::false_type {};
template<class T>
struct has_value_type<T, beast::detail::void_t<
typename T::value_type
> > : std::true_type {};
template<class T, class = beast::detail::void_t<>>
struct has_content_length : std::false_type {};
template<class T>
struct has_content_length<T, beast::detail::void_t<decltype(
std::declval<T>().content_length()
)> > : std::true_type
{
static_assert(std::is_convertible<
decltype(std::declval<T>().content_length()),
std::uint64_t>::value,
"Writer::content_length requirements not met");
};
} // detail
/// Determine if `T` meets the requirements of @b Body.
template<class T>
#if BEAST_DOXYGEN
struct is_body : std::integral_constant<bool, ...>{};
#else
using is_body = detail::has_value_type<T>;
#endif
/** Determine if a @b Body type has a reader.
This metafunction is equivalent to `std::true_type` if:
@li @b T has a nested type named `reader`
@li The nested type meets the requirements of @b BodyReader.
@tparam T The body type to test.
*/
#if BEAST_DOXYGEN
template<class T>
struct is_body_reader : std::integral_constant<bool, ...> {};
#else
template<class T, class = void>
struct is_body_reader : std::false_type {};
template<class T>
struct is_body_reader<T, beast::detail::void_t<
typename T::reader,
typename T::reader::const_buffers_type,
decltype(
std::declval<typename T::reader&>().init(std::declval<error_code&>()),
std::declval<boost::optional<std::pair<
typename T::reader::const_buffers_type, bool>>&>() =
std::declval<typename T::reader>().get(std::declval<error_code&>()),
(void)0)>> : std::integral_constant<bool,
is_const_buffer_sequence<
typename T::reader::const_buffers_type>::value &&
std::is_constructible<typename T::reader,
message<true, T, detail::fields_model> const& >::value
>
{
};
#endif
/** Determine if a @b Body type has a writer.
This metafunction is equivalent to `std::true_type` if:
@li @b T has a nested type named `writer`
@li The nested type meets the requirements of @b BodyWriter.
@tparam T The body type to test.
*/
#if BEAST_DOXYGEN
template<class T>
struct is_body_writer : std::integral_constant<bool, ...> {};
#else
template<class T, class = beast::detail::void_t<>>
struct is_body_writer : std::true_type {};
template<class T>
struct is_body_writer<T, beast::detail::void_t<decltype(
std::declval<typename T::writer::mutable_buffers_type>(),
std::declval<T::writer>().init(
std::declval<boost::optional<std::uint64_t>>()),
std::declval<T::writer>().prepare(
std::declval<std::size_t>()),
std::declval<T::writer>().commit(
std::declval<std::size_t>()),
std::declval<T::writer>().finish()
)> > : std::integral_constant<bool,
is_mutable_buffer_sequence<
typename T::writer::mutable_buffers_type>::value &&
std::is_convertible<decltype(
std::declval<T::writer>().prepare(
std::declval<std::size_t>())),
typename T::writer::mutable_buffers_type
>::value>
{
};
#endif
} // http
} // beast
#endif
+8 -6
View File
@@ -190,27 +190,29 @@ class serializer
using buffer_type =
basic_multi_buffer<Allocator>;
using reader = typename Body::reader;
using is_deferred =
typename Body::writer::is_deferred;
typename reader::is_deferred;
using cb0_t = consuming_buffers<buffers_view<
typename buffer_type::const_buffers_type, // header
typename Body::writer::const_buffers_type>>;// body
typename reader::const_buffers_type>>; // body
using cb1_t = consuming_buffers<
typename Body::writer::const_buffers_type>; // body
typename reader::const_buffers_type>; // body
using ch0_t = consuming_buffers<buffers_view<
typename buffer_type::const_buffers_type, // header
detail::chunk_header, // chunk-header
boost::asio::const_buffers_1, // chunk-ext+\r\n
typename Body::writer::const_buffers_type, // body
typename reader::const_buffers_type, // body
boost::asio::const_buffers_1>>; // crlf
using ch1_t = consuming_buffers<buffers_view<
detail::chunk_header, // chunk-header
boost::asio::const_buffers_1, // chunk-ext+\r\n
typename Body::writer::const_buffers_type, // body
typename reader::const_buffers_type, // body
boost::asio::const_buffers_1>>; // crlf
using ch2_t = consuming_buffers<buffers_view<
@@ -222,7 +224,7 @@ class serializer
Decorator d_;
std::size_t limit_ =
(std::numeric_limits<std::size_t>::max)();
boost::optional<typename Body::writer> wr_;
boost::optional<reader> rd_;
buffer_type b_;
boost::variant<boost::blank,
cb0_t, cb1_t, ch0_t, ch1_t, ch2_t> v_;