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-05-28 09:05:29 -07:00
parent 3664329ea7
commit 75b0571e83
32 changed files with 435 additions and 462 deletions

View File

@ -6,6 +6,7 @@ API Changes:
* Remove HTTP header aliases
* Refactor HTTP serialization
* Refactor type traits
--------------------------------------------------------------------------------

View File

@ -13,10 +13,10 @@ the algorithms used during parsing and serialization.
In this table:
* `X` is a type meeting the requirements of [*`Body`].
* `X` is a type meeting the requirements of [*Body].
[table Body requirements
[[operation] [type] [semantics, pre/post-conditions]]
[[expression] [type] [semantics, pre/post-conditions]]
[
[`X::value_type`]
[]
@ -26,22 +26,34 @@ In this table:
will be not movable or not copyable.
]
]
[
[`X::reader`]
[]
[
If present, a type meeting the requirements of
[link beast.ref.Reader [*`Reader`]].
Provides an implementation to parse the body.
]
]
[
[`X::writer`]
[]
[
If present, a type meeting the requirements of
[link beast.ref.Writer [*`Writer`]].
Provides an implementation to serialize the body.
If present, indicates that the body can hold a message body
parsing result. The type must meet the requirements of
[link beast.ref.BodyWriter [*BodyWriter]]. The implementation
constructs an object of this type to obtain buffers into which
parsed body octets are placed.
]
]
[
[`X::reader`]
[]
[
If present, indicates that the body is serializable.
The type must meet the requirements of
[link beast.ref.BodyReader [*BodyReader]]. The implementation
constructs an object of this type to obtain buffers representing
the message body for serialization.
]
]
[
[`is_body<X>`]
[`std::true_type`]
[
An alias for `std::true_type` for `X`, otherwise an alias
for `std::false_type`.
]
]
]

View File

@ -5,44 +5,53 @@
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:Writer Writer requirements]
[section:BodyReader BodyReader requirements]
A [*Writer] provides an online algorithm to obtain a sequence of zero
A [*BodyReader] provides an online algorithm to obtain a sequence of zero
or more buffers from a body during serialization. The implementation creates
an instance of this type when needed, and calls into it zero or more times to
retrieve buffers with body octets. The interface of [*Writer] is intended to
allow serialization in these scenarios:
an instance of this type when needed, and calls into it one or more times to
retrieve buffers holding body octets. The interface of [*BodyReader] is
intended to obtain buffers for these scenarios:
* A body that does not entirely fit in memory.
* A body produced incrementally from coroutine output.
* A body represented by zero or more buffers already in memory.
* A body as a series of buffers when the content size is not known ahead of time.
* Body data generated on demand from other threads.
* A body whose size is not known ahead of time.
* Body data generated dynamically from other threads.
* Body data computed algorithmically.
In this table:
* `X` denotes a type meeting the requirements of [*Writer].
* `X` denotes a type meeting the requirements of [*BodyReader].
* `B` denotes a __Body__ where
`std::is_same<X, B::reader>::value == true`.
* `a` denotes a value of type `X`.
* `m` denotes a value of type `message const&` where
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
* `ec` is a value of type [link beast.ref.error_code `error_code&`].
* `B<T>` is the type `boost::optional<std::pair<T, bool>>`.
* `R<T>` is the type `boost::optional<std::pair<T, bool>>`.
[table Writer requirements
[[operation] [type] [semantics, pre/post-conditions]]
[table BodyReader requirements
[[expression] [type] [semantics, pre/post-conditions]]
[
[`X::const_buffers_type`]
[]
[
A nested type which meets the requirements of __ConstBufferSequence__.
A type which meets the requirements of __ConstBufferSequence__.
This is the type of buffer returned by `X::get`.
]
]
[
[`X::is_deferred`]
[]
[
]
]
[
[`X(m);`]
[]
@ -53,7 +62,7 @@ In this table:
]
[
[`a.init(ec)`]
[`void`]
[]
[
Called immediately after construction. If the function sets an
error code in `ec`, the serialization is aborted and the error
@ -77,7 +86,7 @@ In this table:
]
[
[`a.get(ec)`]
[`B<X::const_buffers_type>`]
[`R<X::const_buffers_type>`]
[
Called repeatedly after `init` succeeds. This function returns
`boost::none` if all buffers representing the body have been
@ -92,23 +101,24 @@ In this table:
]
]
[
[`http::is_Writer<X>`]
[`is_body_reader<B>`]
[`std::true_type`]
[
An alias for `std::true_type` for `X`, otherwise an
alias for `std::false_type`.
An alias for `std::true_type` for `B`, otherwise an alias
for `std::false_type`.
]
]
]
[note
Definitions for required `Writer` member functions should be declared
inline so the generated code can become part of the implementation.
Definitions for required [*BodyReader] member functions should
be declared inline so the generated code can become part of the
implementation.
]
Exemplar:
```
struct writer
struct reader
{
public:
/** Controls when the implementation requests buffers.
@ -124,22 +134,19 @@ public:
*/
using const_buffers_type = boost::asio::const_buffers_1;
/** Construct the writer.
The msg object is guaranteed to exist for the lifetime of the writer.
/** Construct the reader.
@param msg The message whose body is to be written.
*/
template<bool isRequest, class Body, class Headers>
explicit
writer(message<isRequest, Body, Headers> const& msg);
reader(message<isRequest, Body, Headers> const& msg);
/** Initialize the writer.
/** Initialization.
Called once immediately after construction.
The writer can perform initialization which may fail.
@param ec Contains the error code if any errors occur.
@param ec Set to the error, if any occurred.
*/
void
init(error_code& ec);
@ -147,9 +154,9 @@ public:
/** Returns the content length.
If this member is present, the implementation will set the
Content-Length field accordingly. If absent, the implementation will
use chunk-encoding or terminate the connection to indicate the end
of the message.
Content-Length field accordingly. If absent, the implementation
will use chunk-encoding or terminate the connection to indicate
the end of the message.
*/
std::uint64_t
content_length();
@ -170,7 +177,6 @@ public:
@li If `ec` contains an error code, the return value is ignored.
*/
template<class WriteFunction>
boost::optional<std::pair<const_buffers_type, bool>>
get(error_code& ec);
};

View File

@ -5,25 +5,25 @@
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:Reader Reader requirements]
[section:BodyWriter BodyWriter requirements]
Parsers provided by the implementation will construct the corresponding
`reader` object during parsing. This customization point allows the
Body to determine the strategy for storing incoming message body data.
Readers come in two flavors, direct and indirect:
When HTTP messages are parsed, the implementation constructs a
[*BodyWriter] object to provide the means for transferring parsed body
octets into the message container. These body writers come in two flavors,
direct and indirect:
Direct readers provide a buffer to callers, in which body data is placed.
This type of reader is used when the bytes corresponding to the body data
Direct writers provide a buffer to callers, into which body data is placed.
This type of writer is used when the bytes corresponding to the body data
are stored without transformation. The parse algorithm performs stream or
socket reads directly into the reader-provided buffer, hence the name
socket reads directly into the buffer provided by the writer, hence the name
"direct." This model avoids an unnecessary buffer copy. An example of
a [*Body] type with a direct reader is
a __Body__ type with a direct writer is
[link beast.ref.http__string_body `string_body`].
Indirect readers are passed body data in a buffer managed by the parser
algorithm. This reader is appropriate when the body data is transformed
Indirect writers are passed body data in a buffer managed by the parsing
algorithm. This writer is appropriate when the body data is transformed
or not otherwised stored verbatim. Some examples of when an indirect
reader is appropriate:
writer is appropriate:
* When bytes corresponding to the body are written to a file
as they are parsed.
@ -33,7 +33,10 @@ reader is appropriate:
In the tables below:
* `X` denotes a type meeting the requirements of [*`Reader`].
* `X` denotes a type meeting the requirements of [*Writer].
* `B` denotes a __Body__ where
`std::is_same<X, B::writer>::value == true`.
* `a` denotes a value of type `X`.
@ -41,31 +44,28 @@ In the tables below:
* `v` is a value convertible to `std::uint64_t` without loss of precision.
* `s` is a value of type `boost::string_ref`.
* `s` is a value of type [link beast.ref.string_view `string_view`].
* `ec` is a value of type [link beast.ref.error_code `error_code&`].
* `m` denotes a value of type `message&` where
`std::is_same<decltype(m.body), Body::value_type>::value == true`.
[table Direct Reader requirements
[[operation] [type] [semantics, pre/post-conditions]]
[table Direct Writer requirements
[[expression] [type] [semantics, pre/post-conditions]]
[
[`X::is_direct`]
[`bool`]
[
This static constant must be set to `true` to indicate that
the reader is a direct reader.
This static constant must be set to `true` to indicate this
is a direct writer.
]
]
[
[`X::mutable_buffers_type`]
[]
[
This member type must be present, and meet the requirements
of [*MutableBufferSequence]. It represents the type of
the writable buffers returned by the reader, in which
bytes representing the body are stored by the implementation.
A type which meets the requirements of __MutableBufferSequence__.
]
]
[
@ -85,7 +85,7 @@ In the tables below:
[]
[
This function is called once before any bytes corresponding
to the body are presented to the reader, for messages whose
to the body are presented to the writer, for messages whose
body is determined by the end-of-file marker on a stream,
or for messages where the chunked Transfer-Encoding is
specified.
@ -96,14 +96,14 @@ In the tables below:
[]
[
This function is called once before any bytes corresponding
to the body are presented to the reader, for messages where
to the body are presented to the writer, for messages where
the Content-Length is specified. The value of `v` will be
set to the number of bytes indicated by the content length.
]
]
[
[`a.prepare(n)`]
[`mutable_buffers_type`]
[`X::mutable_buffers_type`]
[
The implementation calls this function to obtain a mutable
buffer sequence of up to `n` bytes in size in which to place
@ -116,7 +116,7 @@ In the tables below:
[]
[
The implementation calls this function to indicate to the
reader that `n` bytes of data have been successfully placed
writer that `n` bytes of data have been successfully placed
into the buffer obtained through a prior call to `prepare`.
The value of `n` will be less than or equal to the size of
the buffer returned in the previous call to `prepare`.
@ -130,16 +130,24 @@ In the tables below:
to the body have been written to the buffers and committed.
]
]
[
[`is_body_writer<B>`]
[`std::true_type`]
[
An alias for `std::true_type` for `B`, otherwise an alias
for `std::false_type`.
]
]
]
[table Indirect Reader requirements
[[operation] [type] [semantics, pre/post-conditions]]
[table Indirect Writer requirements
[[expression] [type] [semantics, pre/post-conditions]]
[
[`X::is_direct`]
[`bool`]
[
This static constant must be set to `false` to indicate that
the reader is an indirect reader.
This static constant must be set to `false` to indicate this
is an indirect writer.
]
]
[
@ -159,7 +167,7 @@ In the tables below:
[]
[
This function is called once before any bytes corresponding
to the body are presented to the reader, for messages whose
to the body are presented to the writer, for messages whose
body is determined by the end-of-file market on a stream,
or for messages where the chunked Transfer-Encoding is
specified.
@ -173,7 +181,7 @@ In the tables below:
[]
[
This function is called once before any bytes corresponding
to the body are presented to the reader, for messages where
to the body are presented to the writer, for messages where
the Content-Length is specified. The value of `v` will be
set to the number of bytes indicated by the content length.
If `ec` is set before returning, parsing will stop
@ -201,9 +209,17 @@ In the tables below:
and the error will be returned to the caller.
]
]
[
[`is_body_writer<B>`]
[`std::true_type`]
[
An alias for `std::true_type` for `B`, otherwise an alias
for `std::false_type`.
]
]
]
[note
Definitions for required `Reader` member functions should be declared
Definitions for required [*Writer] member functions should be declared
inline so the generated code can become part of the implementation.
]

View File

@ -41,7 +41,7 @@ In the table below:
* `U` denotes a type meeting the requirements for __MutableBufferSequence__.
[table DynamicBuffer requirements
[[operation] [type] [semantics, pre/post-conditions]]
[[expression] [type] [semantics, pre/post-conditions]]
[
[`X::const_buffers_type`]
[`T`]

View File

@ -7,16 +7,16 @@
[section:Field Field requirements]
A [*`Field`] represents a single HTTP header field/value pair.
A [*Field] represents a single HTTP header field/value pair.
In this table:
* `X` denotes a type meeting the requirements of [*`Field`].
* `X` denotes a type meeting the requirements of [*Field].
* `a` denotes a value of type `X`.
[table Field requirements
[[operation][type][semantics, pre/post-conditions]]
[[expression][type][semantics, pre/post-conditions]]
[
[`a.name()`]
[`boost::string_ref`]

View File

@ -18,7 +18,7 @@ In this table:
* `c` is a value of type `X const`.
[table FieldSequence requirements
[[operation][type][semantics, pre/post-conditions]]
[[expression][type][semantics, pre/post-conditions]]
[
[`X::value_type`]
[]

View File

@ -12,21 +12,21 @@ asynchronous I/O. They are based on concepts from `boost::asio`.
[heading:Stream Stream]
A type modeling [*`Stream`] meets either or both of the following requirements:
A type modeling [*Stream] meets either or both of the following requirements:
* [*`AsyncStream`]
* [*`SyncStream`]
* [*AsyncStream]
* [*SyncStream]
[heading:AsyncStream AsyncStream]
A type modeling [*`AsyncStream`] meets the following requirements:
A type modeling [*AsyncStream] meets the following requirements:
* __AsyncReadStream__
* __AsyncWriteStream__
[heading:SyncStream SyncStream]
A type modeling [*`SyncStream`] meets the following requirements:
A type modeling [*SyncStream] meets the following requirements:
* __SyncReadStream__
* __SyncWriteStream__

View File

@ -111,7 +111,7 @@ If it needs to access the other fields, it can do so using tag dispatch
with an object of type `std::integral_constant<bool, isRequest>`.
Often, in non-trivial HTTP applications, we want to read the HTTP header
and examine its contents before choosing a top for [*Body]. To accomplish
and examine its contents before choosing a type for [*Body]. To accomplish
this, there needs to be a way to model the header portion of a message.
And we'd like to do this in a way that allows functions which take the
header as a parameter, to also accept a type representing the whole

View File

@ -213,17 +213,18 @@ shows the customization points available to user-defined body types:
* [*`value_type`]: Determines the type of the
[link beast.ref.http__message.body `message::body`] member. If this
type defines default construction, move, copy, or swap, then message objects
declared with this [*`Body`] will have those operations defined.
declared with this [*Body] will have those operations defined.
* [*`reader`]: An optional nested type meeting the requirements of
[link beast.ref.Reader [*`Reader`]]. If present, this defines the algorithm
used for parsing bodies of this type.
* [*`body_writer`]: An optional nested type meeting the requirements of
[link beast.ref.BodyWriter [*BodyWriter]]. If present, this defines the
algorithm used to transfer parsed octets into buffers representing the
body.
* [*`writer`]: An optional nested type meeting the requirements of
[link beast.ref.Writer [*`Writer`]]. If present, this defines the algorithm
used for serializing bodies of this type.
* [*`body_reader`]: An optional nested type meeting the requirements of
[link beast.ref.BodyReader [*BodyReader]]. If present, this defines
the algorithm used to obtain buffers representing a body of this type.
The examples included with this library provide a Body implementation that
The examples included with this library provide a [*Body] implementation that
serializing message bodies that come from a file.
[endsect]

View File

@ -43,10 +43,9 @@
[def __SyncReadStream__ [@http://www.boost.org/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]]
[def __SyncWriteStream__ [@http://www.boost.org/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]]
[def __Body__ [link beast.ref.Body [*`Body`]]]
[def __Body__ [link beast.ref.Body [*Body]]]
[def __DynamicBuffer__ [link beast.ref.DynamicBuffer [*DynamicBuffer]]]
[def __FieldSequence__ [link beast.ref.FieldSequence [*FieldSequence]]]
[def __Parser__ [link beast.ref.Parser [*`Parser`]]]
[def __basic_fields__ [link beast.ref.http__basic_fields `basic_fields`]]
[def __fields__ [link beast.ref.http__fields `fields`]]
@ -113,13 +112,13 @@ provides implementations of the HTTP and WebSocket protocols.
[section:ref Reference]
[xinclude quickref.xml]
[include concept/Body.qbk]
[include concept/BodyReader.qbk]
[include concept/BodyWriter.qbk]
[include concept/BufferSequence.qbk]
[include concept/DynamicBuffer.qbk]
[include concept/Field.qbk]
[include concept/FieldSequence.qbk]
[include concept/Reader.qbk]
[include concept/Streams.qbk]
[include concept/Writer.qbk]
[include reference.qbk]
[endsect]

View File

@ -74,11 +74,9 @@
</simplelist>
<bridgehead renderas="sect3">Type Traits</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.http__is_Body">is_Body</link></member>
<member><link linkend="beast.ref.http__is_Reader">is_Reader</link></member>
<member><link linkend="beast.ref.http__is_Writer">is_Writer</link></member>
<member><link linkend="beast.ref.http__has_reader">has_reader</link></member>
<member><link linkend="beast.ref.http__has_writer">has_writer</link></member>
<member><link linkend="beast.ref.http__is_body">is_body</link></member>
<member><link linkend="beast.ref.http__is_body_writer">is_body_writer</link></member>
<member><link linkend="beast.ref.http__is_body_reader">is_body_reader</link></member>
</simplelist>
</entry>
<entry valign="top">
@ -90,10 +88,10 @@
<bridgehead renderas="sect3">Concepts</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.Body">Body</link></member>
<member><link linkend="beast.ref.BodyReader">BodyReader</link></member>
<member><link linkend="beast.ref.BodyWriter">BodyWriter</link></member>
<member><link linkend="beast.ref.Field">Field</link></member>
<member><link linkend="beast.ref.FieldSequence">FieldSequence</link></member>
<member><link linkend="beast.ref.Reader">Reader</link></member>
<member><link linkend="beast.ref.Writer">Writer</link></member>
</simplelist>
</entry>
<entry valign="top">

View File

@ -584,7 +584,7 @@ the fragments:
Because calls to read data may return a variable amount of bytes, the
interface to calls that read data require an object that meets the requirements
of [link beast.ref.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on
of __DynamicBuffer__. This concept is modeled on
[@http://www.boost.org/doc/html/boost_asio/reference/basic_streambuf.html `boost::asio::basic_streambuf`].
The implementation does not perform queueing or buffering of messages. If

View File

@ -24,7 +24,7 @@ struct file_body
{
using value_type = std::string;
class writer
class reader
{
std::uint64_t size_ = 0;
std::uint64_t offset_ = 0;
@ -39,18 +39,18 @@ struct file_body
using const_buffers_type =
boost::asio::const_buffers_1;
writer(writer&&) = default;
writer(writer const&) = delete;
writer& operator=(writer const&) = delete;
reader(reader&&) = default;
reader(reader const&) = delete;
reader& operator=(reader const&) = delete;
template<bool isRequest, class Fields>
writer(message<isRequest,
reader(message<isRequest,
file_body, Fields> const& m)
: path_(m.body)
{
}
~writer()
~reader()
{
if(file_)
fclose(file_);

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>;

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)
{

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

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)
{

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&)
{
}

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,

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)...);

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)

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);

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;
}

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)
{

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

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_;

View File

@ -43,7 +43,6 @@ unit-test http-tests :
../extras/beast/unit_test/main.cpp
http/basic_parser.cpp
http/buffer_body.cpp
http/concepts.cpp
http/design.cpp
http/dynamic_body.cpp
http/error.cpp
@ -54,6 +53,7 @@ unit-test http-tests :
http/read.cpp
http/rfc7230.cpp
http/string_body.cpp
http/type_traits.cpp
http/write.cpp
;

View File

@ -12,7 +12,6 @@ add_executable (http-tests
../../extras/beast/unit_test/main.cpp
basic_parser.cpp
buffer_body.cpp
concepts.cpp
design.cpp
dynamic_body.cpp
empty_body.cpp
@ -24,6 +23,7 @@ add_executable (http-tests
read.cpp
rfc7230.cpp
string_body.cpp
type_traits.cpp
write.cpp
)

View File

@ -203,7 +203,7 @@ public:
{
using value_type = std::string;
class reader
class writer
{
value_type& body_;
std::size_t len_ = 0;
@ -216,7 +216,7 @@ public:
template<bool isRequest, class Fields>
explicit
reader(message<isRequest, direct_body, Fields>& m)
writer(message<isRequest, direct_body, Fields>& m)
: body_(m.body)
{
}
@ -315,7 +315,7 @@ public:
{
using value_type = std::string;
class reader
class writer
{
value_type& body_;
@ -327,7 +327,7 @@ public:
template<bool isRequest, class Fields>
explicit
reader(message<isRequest, indirect_body, Fields>& m)
writer(message<isRequest, indirect_body, Fields>& m)
: body_(m.body)
{
}

View File

@ -6,16 +6,16 @@
//
// Test that header file is self-contained.
#include <beast/http/concepts.hpp>
#include <beast/http/type_traits.hpp>
#include <beast/http/empty_body.hpp>
namespace beast {
namespace http {
BOOST_STATIC_ASSERT(! is_Writer<int>::value);
BOOST_STATIC_ASSERT(! is_body_reader<int>::value);
BOOST_STATIC_ASSERT(is_Writer<empty_body>::value);
BOOST_STATIC_ASSERT(is_body_reader<empty_body>::value);
} // http
} // beast

View File

@ -37,7 +37,7 @@ public:
{
using value_type = std::string;
class writer
class reader
{
value_type const& body_;
@ -49,7 +49,7 @@ public:
template<bool isRequest, class Allocator>
explicit
writer(message<isRequest, unsized_body, Allocator> const& msg)
reader(message<isRequest, unsized_body, Allocator> const& msg)
: body_(msg.body)
{
}
@ -82,7 +82,7 @@ public:
bool mutable read = false;
};
class writer
class reader
{
int step_ = 0;
value_type const& body_;
@ -96,7 +96,7 @@ public:
template<bool isRequest, class Fields>
explicit
writer(message<isRequest, test_body,
reader(message<isRequest, test_body,
Fields> const& msg)
: body_(msg.body)
{
@ -196,11 +196,11 @@ public:
struct fail_body
{
class writer;
class reader;
class value_type
{
friend class writer;
friend class reader;
std::string s_;
test::fail_counter& fc_;
@ -220,7 +220,7 @@ public:
}
};
class writer
class reader
{
std::size_t n_ = 0;
value_type const& body_;
@ -233,7 +233,7 @@ public:
template<bool isRequest, class Allocator>
explicit
writer(message<isRequest, fail_body, Allocator> const& msg)
reader(message<isRequest, fail_body, Allocator> const& msg)
: body_(msg.body)
{
}