mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 21:34:46 +02:00
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:
@@ -6,6 +6,7 @@ API Changes:
|
|||||||
|
|
||||||
* Remove HTTP header aliases
|
* Remove HTTP header aliases
|
||||||
* Refactor HTTP serialization
|
* Refactor HTTP serialization
|
||||||
|
* Refactor type traits
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -13,10 +13,10 @@ the algorithms used during parsing and serialization.
|
|||||||
|
|
||||||
In this table:
|
In this table:
|
||||||
|
|
||||||
* `X` is a type meeting the requirements of [*`Body`].
|
* `X` is a type meeting the requirements of [*Body].
|
||||||
|
|
||||||
[table Body requirements
|
[table Body requirements
|
||||||
[[operation] [type] [semantics, pre/post-conditions]]
|
[[expression] [type] [semantics, pre/post-conditions]]
|
||||||
[
|
[
|
||||||
[`X::value_type`]
|
[`X::value_type`]
|
||||||
[]
|
[]
|
||||||
@@ -26,22 +26,34 @@ In this table:
|
|||||||
will be not movable or not copyable.
|
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`]
|
[`X::writer`]
|
||||||
[]
|
[]
|
||||||
[
|
[
|
||||||
If present, a type meeting the requirements of
|
If present, indicates that the body can hold a message body
|
||||||
[link beast.ref.Writer [*`Writer`]].
|
parsing result. The type must meet the requirements of
|
||||||
Provides an implementation to serialize the body.
|
[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`.
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
@@ -5,44 +5,53 @@
|
|||||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
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
|
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
|
an instance of this type when needed, and calls into it one or more times to
|
||||||
retrieve buffers with body octets. The interface of [*Writer] is intended to
|
retrieve buffers holding body octets. The interface of [*BodyReader] is
|
||||||
allow serialization in these scenarios:
|
intended to obtain buffers for these scenarios:
|
||||||
|
|
||||||
* A body that does not entirely fit in memory.
|
* A body that does not entirely fit in memory.
|
||||||
* A body produced incrementally from coroutine output.
|
* A body produced incrementally from coroutine output.
|
||||||
* A body represented by zero or more buffers already in memory.
|
* 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.
|
* A body whose size is not known ahead of time.
|
||||||
* Body data generated on demand from other threads.
|
* Body data generated dynamically from other threads.
|
||||||
* Body data computed algorithmically.
|
* Body data computed algorithmically.
|
||||||
|
|
||||||
In this table:
|
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`.
|
* `a` denotes a value of type `X`.
|
||||||
|
|
||||||
* `m` denotes a value of type `message const&` where
|
* `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&`].
|
* `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
|
[table BodyReader requirements
|
||||||
[[operation] [type] [semantics, pre/post-conditions]]
|
[[expression] [type] [semantics, pre/post-conditions]]
|
||||||
[
|
[
|
||||||
[`X::const_buffers_type`]
|
[`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`.
|
This is the type of buffer returned by `X::get`.
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
[
|
||||||
|
[`X::is_deferred`]
|
||||||
|
[]
|
||||||
|
[
|
||||||
|
]
|
||||||
|
]
|
||||||
[
|
[
|
||||||
[`X(m);`]
|
[`X(m);`]
|
||||||
[]
|
[]
|
||||||
@@ -53,7 +62,7 @@ In this table:
|
|||||||
]
|
]
|
||||||
[
|
[
|
||||||
[`a.init(ec)`]
|
[`a.init(ec)`]
|
||||||
[`void`]
|
[]
|
||||||
[
|
[
|
||||||
Called immediately after construction. If the function sets an
|
Called immediately after construction. If the function sets an
|
||||||
error code in `ec`, the serialization is aborted and the error
|
error code in `ec`, the serialization is aborted and the error
|
||||||
@@ -77,7 +86,7 @@ In this table:
|
|||||||
]
|
]
|
||||||
[
|
[
|
||||||
[`a.get(ec)`]
|
[`a.get(ec)`]
|
||||||
[`B<X::const_buffers_type>`]
|
[`R<X::const_buffers_type>`]
|
||||||
[
|
[
|
||||||
Called repeatedly after `init` succeeds. This function returns
|
Called repeatedly after `init` succeeds. This function returns
|
||||||
`boost::none` if all buffers representing the body have been
|
`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`]
|
[`std::true_type`]
|
||||||
[
|
[
|
||||||
An alias for `std::true_type` for `X`, otherwise an
|
An alias for `std::true_type` for `B`, otherwise an alias
|
||||||
alias for `std::false_type`.
|
for `std::false_type`.
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
[note
|
[note
|
||||||
Definitions for required `Writer` member functions should be declared
|
Definitions for required [*BodyReader] member functions should
|
||||||
inline so the generated code can become part of the implementation.
|
be declared inline so the generated code can become part of the
|
||||||
|
implementation.
|
||||||
]
|
]
|
||||||
|
|
||||||
Exemplar:
|
Exemplar:
|
||||||
```
|
```
|
||||||
struct writer
|
struct reader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/** Controls when the implementation requests buffers.
|
/** Controls when the implementation requests buffers.
|
||||||
@@ -124,22 +134,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
using const_buffers_type = boost::asio::const_buffers_1;
|
using const_buffers_type = boost::asio::const_buffers_1;
|
||||||
|
|
||||||
/** Construct the writer.
|
/** Construct the reader.
|
||||||
|
|
||||||
The msg object is guaranteed to exist for the lifetime of the writer.
|
|
||||||
|
|
||||||
@param msg The message whose body is to be written.
|
@param msg The message whose body is to be written.
|
||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, Body, Headers> const& msg);
|
reader(message<isRequest, Body, Headers> const& msg);
|
||||||
|
|
||||||
/** Initialize the writer.
|
/** Initialization.
|
||||||
|
|
||||||
Called once immediately after construction.
|
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
|
void
|
||||||
init(error_code& ec);
|
init(error_code& ec);
|
||||||
@@ -147,9 +154,9 @@ public:
|
|||||||
/** Returns the content length.
|
/** Returns the content length.
|
||||||
|
|
||||||
If this member is present, the implementation will set the
|
If this member is present, the implementation will set the
|
||||||
Content-Length field accordingly. If absent, the implementation will
|
Content-Length field accordingly. If absent, the implementation
|
||||||
use chunk-encoding or terminate the connection to indicate the end
|
will use chunk-encoding or terminate the connection to indicate
|
||||||
of the message.
|
the end of the message.
|
||||||
*/
|
*/
|
||||||
std::uint64_t
|
std::uint64_t
|
||||||
content_length();
|
content_length();
|
||||||
@@ -170,7 +177,6 @@ public:
|
|||||||
|
|
||||||
@li If `ec` contains an error code, the return value is ignored.
|
@li If `ec` contains an error code, the return value is ignored.
|
||||||
*/
|
*/
|
||||||
template<class WriteFunction>
|
|
||||||
boost::optional<std::pair<const_buffers_type, bool>>
|
boost::optional<std::pair<const_buffers_type, bool>>
|
||||||
get(error_code& ec);
|
get(error_code& ec);
|
||||||
};
|
};
|
@@ -5,25 +5,25 @@
|
|||||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
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
|
When HTTP messages are parsed, the implementation constructs a
|
||||||
`reader` object during parsing. This customization point allows the
|
[*BodyWriter] object to provide the means for transferring parsed body
|
||||||
Body to determine the strategy for storing incoming message body data.
|
octets into the message container. These body writers come in two flavors,
|
||||||
Readers come in two flavors, direct and indirect:
|
direct and indirect:
|
||||||
|
|
||||||
Direct readers provide a buffer to callers, in which body data is placed.
|
Direct writers provide a buffer to callers, into which body data is placed.
|
||||||
This type of reader is used when the bytes corresponding to the body data
|
This type of writer is used when the bytes corresponding to the body data
|
||||||
are stored without transformation. The parse algorithm performs stream or
|
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
|
"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`].
|
[link beast.ref.http__string_body `string_body`].
|
||||||
|
|
||||||
Indirect readers are passed body data in a buffer managed by the parser
|
Indirect writers are passed body data in a buffer managed by the parsing
|
||||||
algorithm. This reader is appropriate when the body data is transformed
|
algorithm. This writer is appropriate when the body data is transformed
|
||||||
or not otherwised stored verbatim. Some examples of when an indirect
|
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
|
* When bytes corresponding to the body are written to a file
|
||||||
as they are parsed.
|
as they are parsed.
|
||||||
@@ -33,7 +33,10 @@ reader is appropriate:
|
|||||||
|
|
||||||
In the tables below:
|
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`.
|
* `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.
|
* `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&`].
|
* `ec` is a value of type [link beast.ref.error_code `error_code&`].
|
||||||
|
|
||||||
* `m` denotes a value of type `message&` where
|
* `m` denotes a value of type `message&` where
|
||||||
`std::is_same<decltype(m.body), Body::value_type>::value == true`.
|
`std::is_same<decltype(m.body), Body::value_type>::value == true`.
|
||||||
|
|
||||||
[table Direct Reader requirements
|
[table Direct Writer requirements
|
||||||
[[operation] [type] [semantics, pre/post-conditions]]
|
[[expression] [type] [semantics, pre/post-conditions]]
|
||||||
[
|
[
|
||||||
[`X::is_direct`]
|
[`X::is_direct`]
|
||||||
[`bool`]
|
[`bool`]
|
||||||
[
|
[
|
||||||
This static constant must be set to `true` to indicate that
|
This static constant must be set to `true` to indicate this
|
||||||
the reader is a direct reader.
|
is a direct writer.
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
[`X::mutable_buffers_type`]
|
[`X::mutable_buffers_type`]
|
||||||
[]
|
[]
|
||||||
[
|
[
|
||||||
This member type must be present, and meet the requirements
|
A type which meets the requirements of __MutableBufferSequence__.
|
||||||
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.
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
@@ -85,7 +85,7 @@ In the tables below:
|
|||||||
[]
|
[]
|
||||||
[
|
[
|
||||||
This function is called once before any bytes corresponding
|
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,
|
body is determined by the end-of-file marker on a stream,
|
||||||
or for messages where the chunked Transfer-Encoding is
|
or for messages where the chunked Transfer-Encoding is
|
||||||
specified.
|
specified.
|
||||||
@@ -96,14 +96,14 @@ In the tables below:
|
|||||||
[]
|
[]
|
||||||
[
|
[
|
||||||
This function is called once before any bytes corresponding
|
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
|
the Content-Length is specified. The value of `v` will be
|
||||||
set to the number of bytes indicated by the content length.
|
set to the number of bytes indicated by the content length.
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
[`a.prepare(n)`]
|
[`a.prepare(n)`]
|
||||||
[`mutable_buffers_type`]
|
[`X::mutable_buffers_type`]
|
||||||
[
|
[
|
||||||
The implementation calls this function to obtain a mutable
|
The implementation calls this function to obtain a mutable
|
||||||
buffer sequence of up to `n` bytes in size in which to place
|
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
|
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`.
|
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 value of `n` will be less than or equal to the size of
|
||||||
the buffer returned in the previous call to `prepare`.
|
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.
|
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
|
[table Indirect Writer requirements
|
||||||
[[operation] [type] [semantics, pre/post-conditions]]
|
[[expression] [type] [semantics, pre/post-conditions]]
|
||||||
[
|
[
|
||||||
[`X::is_direct`]
|
[`X::is_direct`]
|
||||||
[`bool`]
|
[`bool`]
|
||||||
[
|
[
|
||||||
This static constant must be set to `false` to indicate that
|
This static constant must be set to `false` to indicate this
|
||||||
the reader is an indirect reader.
|
is an indirect writer.
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
@@ -159,7 +167,7 @@ In the tables below:
|
|||||||
[]
|
[]
|
||||||
[
|
[
|
||||||
This function is called once before any bytes corresponding
|
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,
|
body is determined by the end-of-file market on a stream,
|
||||||
or for messages where the chunked Transfer-Encoding is
|
or for messages where the chunked Transfer-Encoding is
|
||||||
specified.
|
specified.
|
||||||
@@ -173,7 +181,7 @@ In the tables below:
|
|||||||
[]
|
[]
|
||||||
[
|
[
|
||||||
This function is called once before any bytes corresponding
|
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
|
the Content-Length is specified. The value of `v` will be
|
||||||
set to the number of bytes indicated by the content length.
|
set to the number of bytes indicated by the content length.
|
||||||
If `ec` is set before returning, parsing will stop
|
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.
|
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
|
[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.
|
inline so the generated code can become part of the implementation.
|
||||||
]
|
]
|
||||||
|
|
@@ -41,7 +41,7 @@ In the table below:
|
|||||||
* `U` denotes a type meeting the requirements for __MutableBufferSequence__.
|
* `U` denotes a type meeting the requirements for __MutableBufferSequence__.
|
||||||
|
|
||||||
[table DynamicBuffer requirements
|
[table DynamicBuffer requirements
|
||||||
[[operation] [type] [semantics, pre/post-conditions]]
|
[[expression] [type] [semantics, pre/post-conditions]]
|
||||||
[
|
[
|
||||||
[`X::const_buffers_type`]
|
[`X::const_buffers_type`]
|
||||||
[`T`]
|
[`T`]
|
||||||
|
@@ -7,16 +7,16 @@
|
|||||||
|
|
||||||
[section:Field Field requirements]
|
[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:
|
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`.
|
* `a` denotes a value of type `X`.
|
||||||
|
|
||||||
[table Field requirements
|
[table Field requirements
|
||||||
|
|
||||||
[[operation][type][semantics, pre/post-conditions]]
|
[[expression][type][semantics, pre/post-conditions]]
|
||||||
[
|
[
|
||||||
[`a.name()`]
|
[`a.name()`]
|
||||||
[`boost::string_ref`]
|
[`boost::string_ref`]
|
||||||
|
@@ -18,7 +18,7 @@ In this table:
|
|||||||
* `c` is a value of type `X const`.
|
* `c` is a value of type `X const`.
|
||||||
|
|
||||||
[table FieldSequence requirements
|
[table FieldSequence requirements
|
||||||
[[operation][type][semantics, pre/post-conditions]]
|
[[expression][type][semantics, pre/post-conditions]]
|
||||||
[
|
[
|
||||||
[`X::value_type`]
|
[`X::value_type`]
|
||||||
[]
|
[]
|
||||||
|
@@ -12,21 +12,21 @@ asynchronous I/O. They are based on concepts from `boost::asio`.
|
|||||||
|
|
||||||
[heading:Stream Stream]
|
[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`]
|
* [*AsyncStream]
|
||||||
* [*`SyncStream`]
|
* [*SyncStream]
|
||||||
|
|
||||||
[heading:AsyncStream AsyncStream]
|
[heading:AsyncStream AsyncStream]
|
||||||
|
|
||||||
A type modeling [*`AsyncStream`] meets the following requirements:
|
A type modeling [*AsyncStream] meets the following requirements:
|
||||||
|
|
||||||
* __AsyncReadStream__
|
* __AsyncReadStream__
|
||||||
* __AsyncWriteStream__
|
* __AsyncWriteStream__
|
||||||
|
|
||||||
[heading:SyncStream SyncStream]
|
[heading:SyncStream SyncStream]
|
||||||
|
|
||||||
A type modeling [*`SyncStream`] meets the following requirements:
|
A type modeling [*SyncStream] meets the following requirements:
|
||||||
|
|
||||||
* __SyncReadStream__
|
* __SyncReadStream__
|
||||||
* __SyncWriteStream__
|
* __SyncWriteStream__
|
||||||
|
@@ -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>`.
|
with an object of type `std::integral_constant<bool, isRequest>`.
|
||||||
|
|
||||||
Often, in non-trivial HTTP applications, we want to read the HTTP header
|
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.
|
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
|
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
|
header as a parameter, to also accept a type representing the whole
|
||||||
|
17
doc/http.qbk
17
doc/http.qbk
@@ -213,17 +213,18 @@ shows the customization points available to user-defined body types:
|
|||||||
* [*`value_type`]: Determines the type of the
|
* [*`value_type`]: Determines the type of the
|
||||||
[link beast.ref.http__message.body `message::body`] member. If this
|
[link beast.ref.http__message.body `message::body`] member. If this
|
||||||
type defines default construction, move, copy, or swap, then message objects
|
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
|
* [*`body_writer`]: An optional nested type meeting the requirements of
|
||||||
[link beast.ref.Reader [*`Reader`]]. If present, this defines the algorithm
|
[link beast.ref.BodyWriter [*BodyWriter]]. If present, this defines the
|
||||||
used for parsing bodies of this type.
|
algorithm used to transfer parsed octets into buffers representing the
|
||||||
|
body.
|
||||||
|
|
||||||
* [*`writer`]: An optional nested type meeting the requirements of
|
* [*`body_reader`]: An optional nested type meeting the requirements of
|
||||||
[link beast.ref.Writer [*`Writer`]]. If present, this defines the algorithm
|
[link beast.ref.BodyReader [*BodyReader]]. If present, this defines
|
||||||
used for serializing bodies of this type.
|
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.
|
serializing message bodies that come from a file.
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
@@ -43,10 +43,9 @@
|
|||||||
[def __SyncReadStream__ [@http://www.boost.org/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]]
|
[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 __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 __DynamicBuffer__ [link beast.ref.DynamicBuffer [*DynamicBuffer]]]
|
||||||
[def __FieldSequence__ [link beast.ref.FieldSequence [*FieldSequence]]]
|
[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 __basic_fields__ [link beast.ref.http__basic_fields `basic_fields`]]
|
||||||
[def __fields__ [link beast.ref.http__fields `fields`]]
|
[def __fields__ [link beast.ref.http__fields `fields`]]
|
||||||
@@ -113,13 +112,13 @@ provides implementations of the HTTP and WebSocket protocols.
|
|||||||
[section:ref Reference]
|
[section:ref Reference]
|
||||||
[xinclude quickref.xml]
|
[xinclude quickref.xml]
|
||||||
[include concept/Body.qbk]
|
[include concept/Body.qbk]
|
||||||
|
[include concept/BodyReader.qbk]
|
||||||
|
[include concept/BodyWriter.qbk]
|
||||||
[include concept/BufferSequence.qbk]
|
[include concept/BufferSequence.qbk]
|
||||||
[include concept/DynamicBuffer.qbk]
|
[include concept/DynamicBuffer.qbk]
|
||||||
[include concept/Field.qbk]
|
[include concept/Field.qbk]
|
||||||
[include concept/FieldSequence.qbk]
|
[include concept/FieldSequence.qbk]
|
||||||
[include concept/Reader.qbk]
|
|
||||||
[include concept/Streams.qbk]
|
[include concept/Streams.qbk]
|
||||||
[include concept/Writer.qbk]
|
|
||||||
[include reference.qbk]
|
[include reference.qbk]
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
@@ -74,11 +74,9 @@
|
|||||||
</simplelist>
|
</simplelist>
|
||||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.http__is_Body">is_Body</link></member>
|
<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_body_writer">is_body_writer</link></member>
|
||||||
<member><link linkend="beast.ref.http__is_Writer">is_Writer</link></member>
|
<member><link linkend="beast.ref.http__is_body_reader">is_body_reader</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>
|
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
@@ -90,10 +88,10 @@
|
|||||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.Body">Body</link></member>
|
<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.Field">Field</link></member>
|
||||||
<member><link linkend="beast.ref.FieldSequence">FieldSequence</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>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
|
@@ -584,7 +584,7 @@ the fragments:
|
|||||||
|
|
||||||
Because calls to read data may return a variable amount of bytes, the
|
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
|
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`].
|
[@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
|
The implementation does not perform queueing or buffering of messages. If
|
||||||
|
@@ -24,7 +24,7 @@ struct file_body
|
|||||||
{
|
{
|
||||||
using value_type = std::string;
|
using value_type = std::string;
|
||||||
|
|
||||||
class writer
|
class reader
|
||||||
{
|
{
|
||||||
std::uint64_t size_ = 0;
|
std::uint64_t size_ = 0;
|
||||||
std::uint64_t offset_ = 0;
|
std::uint64_t offset_ = 0;
|
||||||
@@ -39,18 +39,18 @@ struct file_body
|
|||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::const_buffers_1;
|
boost::asio::const_buffers_1;
|
||||||
|
|
||||||
writer(writer&&) = default;
|
reader(reader&&) = default;
|
||||||
writer(writer const&) = delete;
|
reader(reader const&) = delete;
|
||||||
writer& operator=(writer const&) = delete;
|
reader& operator=(reader const&) = delete;
|
||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
writer(message<isRequest,
|
reader(message<isRequest,
|
||||||
file_body, Fields> const& m)
|
file_body, Fields> const& m)
|
||||||
: path_(m.body)
|
: path_(m.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~writer()
|
~reader()
|
||||||
{
|
{
|
||||||
if(file_)
|
if(file_)
|
||||||
fclose(file_);
|
fclose(file_);
|
||||||
|
@@ -12,10 +12,10 @@
|
|||||||
|
|
||||||
namespace beast {
|
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;
|
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>
|
template<class CharT, class Traits>
|
||||||
using basic_string_view =
|
using basic_string_view =
|
||||||
boost::basic_string_ref<CharT, Traits>;
|
boost::basic_string_ref<CharT, Traits>;
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_BUFFER_BODY_HPP
|
#ifndef BEAST_HTTP_BUFFER_BODY_HPP
|
||||||
#define 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/error.hpp>
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
@@ -68,10 +68,10 @@ struct buffer_body
|
|||||||
std::pair<boost::optional<ConstBufferSequence>, bool>;
|
std::pair<boost::optional<ConstBufferSequence>, bool>;
|
||||||
|
|
||||||
#if BEAST_DOXYGEN
|
#if BEAST_DOXYGEN
|
||||||
/// The algorithm used when serializing this body
|
/// The algorithm to obtain buffers representing the body
|
||||||
using writer = implementation_defined;
|
using reader = implementation_defined;
|
||||||
#else
|
#else
|
||||||
class writer
|
class reader
|
||||||
{
|
{
|
||||||
bool toggle_ = false;
|
bool toggle_ = false;
|
||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
@@ -84,7 +84,7 @@ struct buffer_body
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, buffer_body,
|
reader(message<isRequest, buffer_body,
|
||||||
Fields> const& msg)
|
Fields> const& msg)
|
||||||
: body_(msg.body)
|
: body_(msg.body)
|
||||||
{
|
{
|
||||||
|
@@ -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
|
|
@@ -29,10 +29,10 @@ struct basic_dynamic_body
|
|||||||
using value_type = DynamicBuffer;
|
using value_type = DynamicBuffer;
|
||||||
|
|
||||||
#if BEAST_DOXYGEN
|
#if BEAST_DOXYGEN
|
||||||
/// The algorithm used when parsing this body.
|
/// The algorithm used store buffers in this body
|
||||||
using reader = implementation_defined;
|
using writer = implementation_defined;
|
||||||
#else
|
#else
|
||||||
class reader
|
class writer
|
||||||
{
|
{
|
||||||
value_type& body_;
|
value_type& body_;
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ struct basic_dynamic_body
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest,
|
writer(message<isRequest,
|
||||||
basic_dynamic_body, Fields>& msg)
|
basic_dynamic_body, Fields>& msg)
|
||||||
: body_(msg.body)
|
: body_(msg.body)
|
||||||
{
|
{
|
||||||
@@ -80,10 +80,10 @@ struct basic_dynamic_body
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BEAST_DOXYGEN
|
#if BEAST_DOXYGEN
|
||||||
/// The algorithm used when serializing this body.
|
/// The algorithm to obtain buffers representing the body
|
||||||
using writer = implementation_defined;
|
using reader = implementation_defined;
|
||||||
#else
|
#else
|
||||||
class writer
|
class reader
|
||||||
{
|
{
|
||||||
DynamicBuffer const& body_;
|
DynamicBuffer const& body_;
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ struct basic_dynamic_body
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<
|
reader(message<
|
||||||
isRequest, basic_dynamic_body, Fields> const& m)
|
isRequest, basic_dynamic_body, Fields> const& m)
|
||||||
: body_(m.body)
|
: body_(m.body)
|
||||||
{
|
{
|
||||||
|
@@ -29,10 +29,10 @@ struct empty_body
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if BEAST_DOXYGEN
|
#if BEAST_DOXYGEN
|
||||||
/// The algorithm used when serializing this body.
|
/// The algorithm to obtain buffers representing the body
|
||||||
using writer = implementation_defined;
|
using reader = implementation_defined;
|
||||||
#else
|
#else
|
||||||
struct writer
|
struct reader
|
||||||
{
|
{
|
||||||
using is_deferred = std::false_type;
|
using is_deferred = std::false_type;
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ struct empty_body
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<
|
reader(message<
|
||||||
isRequest, empty_body, Fields> const&)
|
isRequest, empty_body, Fields> const&)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_ASYNC_READ_IPP_HPP
|
#ifndef BEAST_HTTP_IMPL_ASYNC_READ_IPP_HPP
|
||||||
#define 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/error.hpp>
|
||||||
#include <beast/http/message_parser.hpp>
|
#include <beast/http/message_parser.hpp>
|
||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
@@ -714,13 +714,10 @@ async_read(
|
|||||||
"AsyncReadStream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_reader<Body>::value,
|
static_assert(is_body_writer<Body>::value,
|
||||||
"Body has no reader");
|
"BodyWriter requirements not met");
|
||||||
static_assert(is_Reader<typename Body::reader,
|
|
||||||
message<isRequest, Body, Fields>>::value,
|
|
||||||
"Reader requirements not met");
|
|
||||||
async_completion<ReadHandler,
|
async_completion<ReadHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
detail::read_message_op<AsyncReadStream, DynamicBuffer,
|
detail::read_message_op<AsyncReadStream, DynamicBuffer,
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#include <beast/core/error.hpp>
|
#include <beast/core/error.hpp>
|
||||||
#include <beast/core/string_view.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/http/rfc7230.hpp>
|
||||||
#include <beast/core/detail/ci_char_traits.hpp>
|
#include <beast/core/detail/ci_char_traits.hpp>
|
||||||
#include <beast/core/detail/type_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,
|
message<isRequest, Body, Fields> const& msg,
|
||||||
std::true_type)
|
std::true_type)
|
||||||
{
|
{
|
||||||
typename Body::writer w(msg);
|
typename Body::reader w{msg};
|
||||||
// VFALCO This is a design problem!
|
// VFALCO This is a design problem!
|
||||||
error_code ec;
|
error_code ec;
|
||||||
w.init(ec);
|
w.init(ec);
|
||||||
@@ -159,15 +159,13 @@ prepare(message<isRequest, Body, Fields>& msg,
|
|||||||
Options&&... options)
|
Options&&... options)
|
||||||
{
|
{
|
||||||
// VFALCO TODO
|
// VFALCO TODO
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_writer<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"Body has no writer");
|
"BodyReader requirements not met");
|
||||||
static_assert(is_Writer<Body>::value,
|
|
||||||
"Writer requirements not met");
|
|
||||||
detail::prepare_info pi;
|
detail::prepare_info pi;
|
||||||
detail::prepare_content_length(pi, msg,
|
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,
|
detail::prepare_options(pi, msg,
|
||||||
std::forward<Options>(options)...);
|
std::forward<Options>(options)...);
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
|
#ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||||
#define 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/error.hpp>
|
||||||
#include <beast/http/message_parser.hpp>
|
#include <beast/http/message_parser.hpp>
|
||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
@@ -291,13 +291,10 @@ read(
|
|||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_reader<Body>::value,
|
static_assert(is_body_writer<Body>::value,
|
||||||
"Body has no reader");
|
"BodyWriter requirements not met");
|
||||||
static_assert(is_Reader<typename Body::reader,
|
|
||||||
message<isRequest, Body, Fields>>::value,
|
|
||||||
"Reader requirements not met");
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
beast::http::read(stream, buffer, msg, ec);
|
beast::http::read(stream, buffer, msg, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
@@ -319,13 +316,10 @@ read(
|
|||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
"DynamicBuffer requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_reader<Body>::value,
|
static_assert(is_body_writer<Body>::value,
|
||||||
"Body has no reader");
|
"BodyWriter requirements not met");
|
||||||
static_assert(is_Reader<typename Body::reader,
|
|
||||||
message<isRequest, Body, Fields>>::value,
|
|
||||||
"Reader requirements not met");
|
|
||||||
message_parser<isRequest, Body, Fields> p;
|
message_parser<isRequest, Body, Fields> p;
|
||||||
beast::http::read(stream, buffer, p, ec);
|
beast::http::read(stream, buffer, p, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_WRITE_IPP
|
#ifndef BEAST_HTTP_IMPL_WRITE_IPP
|
||||||
#define 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/http/error.hpp>
|
||||||
#include <beast/core/buffer_cat.hpp>
|
#include <beast/core/buffer_cat.hpp>
|
||||||
#include <beast/core/buffer_prefix.hpp>
|
#include <beast/core/buffer_prefix.hpp>
|
||||||
@@ -183,12 +183,12 @@ operator()(error_code ec,
|
|||||||
{
|
{
|
||||||
if(w_.split_)
|
if(w_.split_)
|
||||||
goto go_header_only;
|
goto go_header_only;
|
||||||
w_.wr_.emplace(w_.m_);
|
w_.rd_.emplace(w_.m_);
|
||||||
w_.wr_->init(ec);
|
w_.rd_->init(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return s_.get_io_service().post(
|
return s_.get_io_service().post(
|
||||||
bind_handler(std::move(*this), ec, 0));
|
bind_handler(std::move(*this), ec, 0));
|
||||||
auto result = w_.wr_->get(ec);
|
auto result = w_.rd_->get(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
// Can't use need_more when ! is_deferred
|
// Can't use need_more when ! is_deferred
|
||||||
@@ -248,9 +248,9 @@ operator()(error_code ec,
|
|||||||
w_.header_done_ = true;
|
w_.header_done_ = true;
|
||||||
if(! is_deferred::value)
|
if(! is_deferred::value)
|
||||||
goto go_complete;
|
goto go_complete;
|
||||||
BOOST_ASSERT(! w_.wr_);
|
BOOST_ASSERT(! w_.rd_);
|
||||||
w_.wr_.emplace(w_.m_);
|
w_.rd_.emplace(w_.m_);
|
||||||
w_.wr_->init(ec);
|
w_.rd_->init(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
goto upcall;
|
goto upcall;
|
||||||
w_.s_ = do_body;
|
w_.s_ = do_body;
|
||||||
@@ -258,7 +258,7 @@ operator()(error_code ec,
|
|||||||
|
|
||||||
case do_body:
|
case do_body:
|
||||||
{
|
{
|
||||||
auto result = w_.wr_->get(ec);
|
auto result = w_.rd_->get(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return s_.get_io_service().post(
|
return s_.get_io_service().post(
|
||||||
bind_handler(std::move(*this), ec, 0));
|
bind_handler(std::move(*this), ec, 0));
|
||||||
@@ -303,12 +303,12 @@ operator()(error_code ec,
|
|||||||
{
|
{
|
||||||
if(w_.split_)
|
if(w_.split_)
|
||||||
goto go_header_only_c;
|
goto go_header_only_c;
|
||||||
w_.wr_.emplace(w_.m_);
|
w_.rd_.emplace(w_.m_);
|
||||||
w_.wr_->init(ec);
|
w_.rd_->init(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return s_.get_io_service().post(
|
return s_.get_io_service().post(
|
||||||
bind_handler(std::move(*this), ec, 0));
|
bind_handler(std::move(*this), ec, 0));
|
||||||
auto result = w_.wr_->get(ec);
|
auto result = w_.rd_->get(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
// Can't use need_more when ! is_deferred
|
// Can't use need_more when ! is_deferred
|
||||||
@@ -382,9 +382,9 @@ operator()(error_code ec,
|
|||||||
w_.s_ = do_final_c;
|
w_.s_ = do_final_c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(! w_.wr_);
|
BOOST_ASSERT(! w_.rd_);
|
||||||
w_.wr_.emplace(w_.m_);
|
w_.rd_.emplace(w_.m_);
|
||||||
w_.wr_->init(ec);
|
w_.rd_->init(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
goto upcall;
|
goto upcall;
|
||||||
w_.s_ = do_body_c;
|
w_.s_ = do_body_c;
|
||||||
@@ -392,7 +392,7 @@ operator()(error_code ec,
|
|||||||
|
|
||||||
case do_body_c:
|
case do_body_c:
|
||||||
{
|
{
|
||||||
auto result = w_.wr_->get(ec);
|
auto result = w_.rd_->get(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return s_.get_io_service().post(
|
return s_.get_io_service().post(
|
||||||
bind_handler(std::move(*this),
|
bind_handler(std::move(*this),
|
||||||
@@ -528,12 +528,10 @@ write_some(SyncWriteStream& stream)
|
|||||||
static_assert(
|
static_assert(
|
||||||
is_sync_write_stream<SyncWriteStream>::value,
|
is_sync_write_stream<SyncWriteStream>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_writer<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"Body::writer requirements not met");
|
"BodyReader requirements not met");
|
||||||
static_assert(is_Writer<Body>::value,
|
|
||||||
"Writer requirements not met");
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
write_some(stream, ec);
|
write_some(stream, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
@@ -551,12 +549,10 @@ write_some(SyncWriteStream& stream, error_code &ec)
|
|||||||
static_assert(
|
static_assert(
|
||||||
is_sync_write_stream<SyncWriteStream>::value,
|
is_sync_write_stream<SyncWriteStream>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_writer<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"Body::writer requirements not met");
|
"BodyReader requirements not met");
|
||||||
static_assert(is_Writer<Body>::value,
|
|
||||||
"Writer requirements not met");
|
|
||||||
|
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
switch(s_)
|
switch(s_)
|
||||||
@@ -565,11 +561,11 @@ write_some(SyncWriteStream& stream, error_code &ec)
|
|||||||
{
|
{
|
||||||
if(split_)
|
if(split_)
|
||||||
goto go_header_only;
|
goto go_header_only;
|
||||||
wr_.emplace(m_);
|
rd_.emplace(m_);
|
||||||
wr_->init(ec);
|
rd_->init(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
auto result = wr_->get(ec);
|
auto result = rd_->get(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
// Can't use need_more when ! is_deferred
|
// Can't use need_more when ! is_deferred
|
||||||
@@ -624,9 +620,9 @@ write_some(SyncWriteStream& stream, error_code &ec)
|
|||||||
header_done_ = true;
|
header_done_ = true;
|
||||||
if(! is_deferred::value)
|
if(! is_deferred::value)
|
||||||
goto go_complete;
|
goto go_complete;
|
||||||
BOOST_ASSERT(! wr_);
|
BOOST_ASSERT(! rd_);
|
||||||
wr_.emplace(m_);
|
rd_.emplace(m_);
|
||||||
wr_->init(ec);
|
rd_->init(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
s_ = do_body;
|
s_ = do_body;
|
||||||
@@ -635,7 +631,7 @@ write_some(SyncWriteStream& stream, error_code &ec)
|
|||||||
|
|
||||||
case do_body:
|
case do_body:
|
||||||
{
|
{
|
||||||
auto result = wr_->get(ec);
|
auto result = rd_->get(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
if(! result)
|
if(! result)
|
||||||
@@ -670,11 +666,11 @@ write_some(SyncWriteStream& stream, error_code &ec)
|
|||||||
{
|
{
|
||||||
if(split_)
|
if(split_)
|
||||||
goto go_header_only_c;
|
goto go_header_only_c;
|
||||||
wr_.emplace(m_);
|
rd_.emplace(m_);
|
||||||
wr_->init(ec);
|
rd_->init(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
auto result = wr_->get(ec);
|
auto result = rd_->get(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
// Can't use need_more when ! is_deferred
|
// Can't use need_more when ! is_deferred
|
||||||
@@ -742,9 +738,9 @@ write_some(SyncWriteStream& stream, error_code &ec)
|
|||||||
s_ = do_final_c;
|
s_ = do_final_c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(! wr_);
|
BOOST_ASSERT(! rd_);
|
||||||
wr_.emplace(m_);
|
rd_.emplace(m_);
|
||||||
wr_->init(ec);
|
rd_->init(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
s_ = do_body_c;
|
s_ = do_body_c;
|
||||||
@@ -753,7 +749,7 @@ write_some(SyncWriteStream& stream, error_code &ec)
|
|||||||
|
|
||||||
case do_body_c:
|
case do_body_c:
|
||||||
{
|
{
|
||||||
auto result = wr_->get(ec);
|
auto result = rd_->get(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
if(! result)
|
if(! result)
|
||||||
@@ -856,12 +852,10 @@ async_write_some(AsyncWriteStream& stream,
|
|||||||
{
|
{
|
||||||
static_assert(is_async_write_stream<AsyncWriteStream>::value,
|
static_assert(is_async_write_stream<AsyncWriteStream>::value,
|
||||||
"AsyncWriteStream requirements not met");
|
"AsyncWriteStream requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_writer<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"Body::writer requirements not met");
|
"BodyReader requirements not met");
|
||||||
static_assert(is_Writer<Body>::value,
|
|
||||||
"Writer requirements not met");
|
|
||||||
async_completion<WriteHandler,
|
async_completion<WriteHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
async_op<AsyncWriteStream, handler_type<
|
async_op<AsyncWriteStream, handler_type<
|
||||||
@@ -984,12 +978,10 @@ write(SyncWriteStream& stream,
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_writer<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"Body has no writer");
|
"BodyReader requirements not met");
|
||||||
static_assert(is_Writer<Body>::value,
|
|
||||||
"Writer requirements not met");
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
write(stream, msg, ec);
|
write(stream, msg, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
@@ -1005,12 +997,10 @@ write(SyncWriteStream& stream,
|
|||||||
{
|
{
|
||||||
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||||
"SyncWriteStream requirements not met");
|
"SyncWriteStream requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_writer<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"Body has no writer");
|
"BodyReader requirements not met");
|
||||||
static_assert(is_Writer<Body>::value,
|
|
||||||
"Writer requirements not met");
|
|
||||||
auto ws = make_write_stream(msg);
|
auto ws = make_write_stream(msg);
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
@@ -1034,12 +1024,10 @@ async_write(AsyncWriteStream& stream,
|
|||||||
static_assert(
|
static_assert(
|
||||||
is_async_write_stream<AsyncWriteStream>::value,
|
is_async_write_stream<AsyncWriteStream>::value,
|
||||||
"AsyncWriteStream requirements not met");
|
"AsyncWriteStream requirements not met");
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_writer<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"Body has no writer");
|
"BodyReader requirements not met");
|
||||||
static_assert(is_Writer<Body>::value,
|
|
||||||
"Writer requirements not met");
|
|
||||||
async_completion<WriteHandler,
|
async_completion<WriteHandler,
|
||||||
void(error_code)> init{handler};
|
void(error_code)> init{handler};
|
||||||
detail::write_op<AsyncWriteStream, handler_type<
|
detail::write_op<AsyncWriteStream, handler_type<
|
||||||
@@ -1068,12 +1056,10 @@ std::ostream&
|
|||||||
operator<<(std::ostream& os,
|
operator<<(std::ostream& os,
|
||||||
message<isRequest, Body, Fields> const& msg)
|
message<isRequest, Body, Fields> const& msg)
|
||||||
{
|
{
|
||||||
static_assert(is_Body<Body>::value,
|
static_assert(is_body<Body>::value,
|
||||||
"Body requirements not met");
|
"Body requirements not met");
|
||||||
static_assert(has_writer<Body>::value,
|
static_assert(is_body_reader<Body>::value,
|
||||||
"Body has no writer");
|
"BodyReader requirements not met");
|
||||||
static_assert(is_Writer<Body>::value,
|
|
||||||
"Writer requirements not met");
|
|
||||||
beast::detail::sync_ostream oss{os};
|
beast::detail::sync_ostream oss{os};
|
||||||
error_code ec;
|
error_code ec;
|
||||||
write(oss, msg, ec);
|
write(oss, msg, ec);
|
||||||
|
@@ -37,16 +37,16 @@ namespace http {
|
|||||||
template<bool isRequest, class Body, class Fields>
|
template<bool isRequest, class Body, class Fields>
|
||||||
class message_parser
|
class message_parser
|
||||||
: public basic_parser<isRequest,
|
: public basic_parser<isRequest,
|
||||||
Body::reader::is_direct,
|
Body::writer::is_direct,
|
||||||
message_parser<isRequest, Body, Fields>>
|
message_parser<isRequest, Body, Fields>>
|
||||||
{
|
{
|
||||||
using base_type = basic_parser<isRequest, true,
|
using base_type = basic_parser<isRequest, true,
|
||||||
message_parser<isRequest, Body, Fields>>;
|
message_parser<isRequest, Body, Fields>>;
|
||||||
|
|
||||||
using reader_type = typename Body::reader;
|
using writer_type = typename Body::writer;
|
||||||
|
|
||||||
message<isRequest, Body, Fields> m_;
|
message<isRequest, Body, Fields> m_;
|
||||||
boost::optional<typename Body::reader> r_;
|
boost::optional<writer_type> wr_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// The type of message returned by the parser
|
/// The type of message returned by the parser
|
||||||
@@ -54,7 +54,7 @@ public:
|
|||||||
|
|
||||||
/// The type of buffer sequence representing the body
|
/// The type of buffer sequence representing the body
|
||||||
using mutable_buffers_type =
|
using mutable_buffers_type =
|
||||||
typename reader_type::mutable_buffers_type;
|
typename writer_type::mutable_buffers_type;
|
||||||
|
|
||||||
/// Constructor (default)
|
/// Constructor (default)
|
||||||
message_parser() = default;
|
message_parser() = default;
|
||||||
@@ -152,7 +152,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class basic_parser<
|
friend class basic_parser<
|
||||||
isRequest, Body::reader::is_direct,
|
isRequest, Body::writer::is_direct,
|
||||||
message_parser>;
|
message_parser>;
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -192,22 +192,22 @@ private:
|
|||||||
void
|
void
|
||||||
on_body()
|
on_body()
|
||||||
{
|
{
|
||||||
r_.emplace(m_);
|
wr_.emplace(m_);
|
||||||
r_->init();
|
wr_->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_body(std::uint64_t content_length)
|
on_body(std::uint64_t content_length)
|
||||||
{
|
{
|
||||||
r_.emplace(m_);
|
wr_.emplace(m_);
|
||||||
r_->init(content_length);
|
wr_->init(content_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_body(error_code& ec)
|
on_body(error_code& ec)
|
||||||
{
|
{
|
||||||
r_.emplace(m_);
|
wr_.emplace(m_);
|
||||||
r_->init(ec);
|
wr_->init(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -216,8 +216,8 @@ private:
|
|||||||
on_body(std::uint64_t content_length,
|
on_body(std::uint64_t content_length,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
r_.emplace(m_);
|
wr_.emplace(m_);
|
||||||
r_->init(content_length, ec);
|
wr_->init(content_length, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -226,20 +226,20 @@ private:
|
|||||||
on_data(string_view const& s,
|
on_data(string_view const& s,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
BOOST_STATIC_ASSERT(! Body::reader::is_direct);
|
BOOST_STATIC_ASSERT(! Body::writer::is_direct);
|
||||||
r_->write(s, ec);
|
wr_->write(s, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
on_prepare(std::size_t n)
|
on_prepare(std::size_t n)
|
||||||
{
|
{
|
||||||
return r_->prepare(n);
|
return wr_->prepare(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_commit(std::size_t n)
|
on_commit(std::size_t n)
|
||||||
{
|
{
|
||||||
r_->commit(n);
|
wr_->commit(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -252,24 +252,24 @@ private:
|
|||||||
void
|
void
|
||||||
on_complete(error_code& ec)
|
on_complete(error_code& ec)
|
||||||
{
|
{
|
||||||
if(r_)
|
if(wr_)
|
||||||
do_on_complete(ec,
|
do_on_complete(ec,
|
||||||
std::integral_constant<bool,
|
std::integral_constant<bool,
|
||||||
Body::reader::is_direct>{});
|
Body::writer::is_direct>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
do_on_complete(
|
do_on_complete(
|
||||||
error_code& ec, std::true_type)
|
error_code& ec, std::true_type)
|
||||||
{
|
{
|
||||||
r_->finish();
|
wr_->finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
do_on_complete(
|
do_on_complete(
|
||||||
error_code& ec, std::false_type)
|
error_code& ec, std::false_type)
|
||||||
{
|
{
|
||||||
r_->finish(ec);
|
wr_->finish(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -31,10 +31,10 @@ struct string_body
|
|||||||
using value_type = std::string;
|
using value_type = std::string;
|
||||||
|
|
||||||
#if BEAST_DOXYGEN
|
#if BEAST_DOXYGEN
|
||||||
/// The algorithm used when parsing this body.
|
/// The algorithm used store buffers in this body
|
||||||
using reader = implementation_defined;
|
using writer = implementation_defined;
|
||||||
#else
|
#else
|
||||||
class reader
|
class writer
|
||||||
{
|
{
|
||||||
value_type& body_;
|
value_type& body_;
|
||||||
std::size_t len_ = 0;
|
std::size_t len_ = 0;
|
||||||
@@ -47,7 +47,7 @@ struct string_body
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest,
|
writer(message<isRequest,
|
||||||
string_body, Fields>& m)
|
string_body, Fields>& m)
|
||||||
: body_(m.body)
|
: body_(m.body)
|
||||||
{
|
{
|
||||||
@@ -93,10 +93,10 @@ struct string_body
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BEAST_DOXYGEN
|
#if BEAST_DOXYGEN
|
||||||
/// The algorithm used when serializing this body.
|
/// The algorithm to obtain buffers representing the body
|
||||||
using writer = implementation_defined;
|
using reader = implementation_defined;
|
||||||
#else
|
#else
|
||||||
class writer
|
class reader
|
||||||
{
|
{
|
||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ struct string_body
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<
|
reader(message<
|
||||||
isRequest, string_body, Fields> const& msg)
|
isRequest, string_body, Fields> const& msg)
|
||||||
: body_(msg.body)
|
: body_(msg.body)
|
||||||
{
|
{
|
||||||
|
146
include/beast/http/type_traits.hpp
Normal file
146
include/beast/http/type_traits.hpp
Normal 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
|
@@ -190,27 +190,29 @@ class serializer
|
|||||||
using buffer_type =
|
using buffer_type =
|
||||||
basic_multi_buffer<Allocator>;
|
basic_multi_buffer<Allocator>;
|
||||||
|
|
||||||
|
using reader = typename Body::reader;
|
||||||
|
|
||||||
using is_deferred =
|
using is_deferred =
|
||||||
typename Body::writer::is_deferred;
|
typename reader::is_deferred;
|
||||||
|
|
||||||
using cb0_t = consuming_buffers<buffers_view<
|
using cb0_t = consuming_buffers<buffers_view<
|
||||||
typename buffer_type::const_buffers_type, // header
|
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<
|
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<
|
using ch0_t = consuming_buffers<buffers_view<
|
||||||
typename buffer_type::const_buffers_type, // header
|
typename buffer_type::const_buffers_type, // header
|
||||||
detail::chunk_header, // chunk-header
|
detail::chunk_header, // chunk-header
|
||||||
boost::asio::const_buffers_1, // chunk-ext+\r\n
|
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
|
boost::asio::const_buffers_1>>; // crlf
|
||||||
|
|
||||||
using ch1_t = consuming_buffers<buffers_view<
|
using ch1_t = consuming_buffers<buffers_view<
|
||||||
detail::chunk_header, // chunk-header
|
detail::chunk_header, // chunk-header
|
||||||
boost::asio::const_buffers_1, // chunk-ext+\r\n
|
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
|
boost::asio::const_buffers_1>>; // crlf
|
||||||
|
|
||||||
using ch2_t = consuming_buffers<buffers_view<
|
using ch2_t = consuming_buffers<buffers_view<
|
||||||
@@ -222,7 +224,7 @@ class serializer
|
|||||||
Decorator d_;
|
Decorator d_;
|
||||||
std::size_t limit_ =
|
std::size_t limit_ =
|
||||||
(std::numeric_limits<std::size_t>::max)();
|
(std::numeric_limits<std::size_t>::max)();
|
||||||
boost::optional<typename Body::writer> wr_;
|
boost::optional<reader> rd_;
|
||||||
buffer_type b_;
|
buffer_type b_;
|
||||||
boost::variant<boost::blank,
|
boost::variant<boost::blank,
|
||||||
cb0_t, cb1_t, ch0_t, ch1_t, ch2_t> v_;
|
cb0_t, cb1_t, ch0_t, ch1_t, ch2_t> v_;
|
||||||
|
@@ -43,7 +43,6 @@ unit-test http-tests :
|
|||||||
../extras/beast/unit_test/main.cpp
|
../extras/beast/unit_test/main.cpp
|
||||||
http/basic_parser.cpp
|
http/basic_parser.cpp
|
||||||
http/buffer_body.cpp
|
http/buffer_body.cpp
|
||||||
http/concepts.cpp
|
|
||||||
http/design.cpp
|
http/design.cpp
|
||||||
http/dynamic_body.cpp
|
http/dynamic_body.cpp
|
||||||
http/error.cpp
|
http/error.cpp
|
||||||
@@ -54,6 +53,7 @@ unit-test http-tests :
|
|||||||
http/read.cpp
|
http/read.cpp
|
||||||
http/rfc7230.cpp
|
http/rfc7230.cpp
|
||||||
http/string_body.cpp
|
http/string_body.cpp
|
||||||
|
http/type_traits.cpp
|
||||||
http/write.cpp
|
http/write.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@@ -12,7 +12,6 @@ add_executable (http-tests
|
|||||||
../../extras/beast/unit_test/main.cpp
|
../../extras/beast/unit_test/main.cpp
|
||||||
basic_parser.cpp
|
basic_parser.cpp
|
||||||
buffer_body.cpp
|
buffer_body.cpp
|
||||||
concepts.cpp
|
|
||||||
design.cpp
|
design.cpp
|
||||||
dynamic_body.cpp
|
dynamic_body.cpp
|
||||||
empty_body.cpp
|
empty_body.cpp
|
||||||
@@ -24,6 +23,7 @@ add_executable (http-tests
|
|||||||
read.cpp
|
read.cpp
|
||||||
rfc7230.cpp
|
rfc7230.cpp
|
||||||
string_body.cpp
|
string_body.cpp
|
||||||
|
type_traits.cpp
|
||||||
write.cpp
|
write.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -203,7 +203,7 @@ public:
|
|||||||
{
|
{
|
||||||
using value_type = std::string;
|
using value_type = std::string;
|
||||||
|
|
||||||
class reader
|
class writer
|
||||||
{
|
{
|
||||||
value_type& body_;
|
value_type& body_;
|
||||||
std::size_t len_ = 0;
|
std::size_t len_ = 0;
|
||||||
@@ -216,7 +216,7 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest, direct_body, Fields>& m)
|
writer(message<isRequest, direct_body, Fields>& m)
|
||||||
: body_(m.body)
|
: body_(m.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -315,7 +315,7 @@ public:
|
|||||||
{
|
{
|
||||||
using value_type = std::string;
|
using value_type = std::string;
|
||||||
|
|
||||||
class reader
|
class writer
|
||||||
{
|
{
|
||||||
value_type& body_;
|
value_type& body_;
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest, indirect_body, Fields>& m)
|
writer(message<isRequest, indirect_body, Fields>& m)
|
||||||
: body_(m.body)
|
: body_(m.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@@ -6,16 +6,16 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/http/concepts.hpp>
|
#include <beast/http/type_traits.hpp>
|
||||||
|
|
||||||
#include <beast/http/empty_body.hpp>
|
#include <beast/http/empty_body.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
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
|
} // http
|
||||||
} // beast
|
} // beast
|
@@ -37,7 +37,7 @@ public:
|
|||||||
{
|
{
|
||||||
using value_type = std::string;
|
using value_type = std::string;
|
||||||
|
|
||||||
class writer
|
class reader
|
||||||
{
|
{
|
||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Allocator>
|
template<bool isRequest, class Allocator>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, unsized_body, Allocator> const& msg)
|
reader(message<isRequest, unsized_body, Allocator> const& msg)
|
||||||
: body_(msg.body)
|
: body_(msg.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ public:
|
|||||||
bool mutable read = false;
|
bool mutable read = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class writer
|
class reader
|
||||||
{
|
{
|
||||||
int step_ = 0;
|
int step_ = 0;
|
||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
@@ -96,7 +96,7 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, test_body,
|
reader(message<isRequest, test_body,
|
||||||
Fields> const& msg)
|
Fields> const& msg)
|
||||||
: body_(msg.body)
|
: body_(msg.body)
|
||||||
{
|
{
|
||||||
@@ -196,11 +196,11 @@ public:
|
|||||||
|
|
||||||
struct fail_body
|
struct fail_body
|
||||||
{
|
{
|
||||||
class writer;
|
class reader;
|
||||||
|
|
||||||
class value_type
|
class value_type
|
||||||
{
|
{
|
||||||
friend class writer;
|
friend class reader;
|
||||||
|
|
||||||
std::string s_;
|
std::string s_;
|
||||||
test::fail_counter& fc_;
|
test::fail_counter& fc_;
|
||||||
@@ -220,7 +220,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class writer
|
class reader
|
||||||
{
|
{
|
||||||
std::size_t n_ = 0;
|
std::size_t n_ = 0;
|
||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
@@ -233,7 +233,7 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Allocator>
|
template<bool isRequest, class Allocator>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, fail_body, Allocator> const& msg)
|
reader(message<isRequest, fail_body, Allocator> const& msg)
|
||||||
: body_(msg.body)
|
: body_(msg.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user