mirror of
https://github.com/boostorg/beast.git
synced 2025-08-03 06:44:39 +02:00
BodyReader and BodyWriter names are swapped (API Change):
Body::reader and Body::writer meanings are reversed, for consistency with the names of the stream operations: * Body::reader is used for read, read_some, async_read, async_read_some * Body::writer is used for write, write_some, async_write, async_write_some Actions Required: * Swap the reader and writer names for user defined Body types * Swap use of is_body_reader and is_body_writer
This commit is contained in:
@@ -8,10 +8,13 @@ Version 132:
|
||||
API Changes:
|
||||
|
||||
* Fields::writer replaces Fields::reader
|
||||
* BodyReader and BodyWriter names are swapped
|
||||
|
||||
Actions Required:
|
||||
|
||||
* Rename reader to writer for user defined Fields
|
||||
* Swap the reader and writer names for user defined Body types
|
||||
* Swap use of is_body_reader and is_body_writer
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@@ -17,10 +17,10 @@ shows the customization points available to user-defined body types:
|
||||
/// Defines a Body type
|
||||
struct body
|
||||
{
|
||||
/// This determines the type of the `message::body` member
|
||||
/// This determines the return type of the `message::body` member function
|
||||
using value_type = ...;
|
||||
|
||||
/// An optional function, returns the body's payload size
|
||||
/// An optional function, returns the body's payload size (which may be zero)
|
||||
static
|
||||
std::uint64_t
|
||||
size(value_type const& v);
|
||||
@@ -48,17 +48,17 @@ The meaning of the nested types is as follows
|
||||
[`reader`]
|
||||
[
|
||||
An optional nested type meeting the requirements of __BodyReader__,
|
||||
which provides the algorithm for converting the body representation
|
||||
to a forward range of buffer sequences.
|
||||
If present this body type may be used with a __serializer__.
|
||||
which provides the algorithm for storing a forward range of buffer
|
||||
sequences in the body representation.
|
||||
If present, this body type may be used with a __parser__.
|
||||
]
|
||||
][
|
||||
[`writer`]
|
||||
[
|
||||
An optional nested type meeting the requirements of __BodyWriter__,
|
||||
which provides the algorithm for storing a forward range of buffer
|
||||
sequences in the body representation.
|
||||
If present, this body type may be used with a __parser__.
|
||||
which provides the algorithm for converting the body representation
|
||||
to a forward range of buffer sequences.
|
||||
If present this body type may be used with a __serializer__.
|
||||
]
|
||||
]
|
||||
]
|
||||
@@ -67,7 +67,7 @@ The meaning of the nested types is as follows
|
||||
|
||||
The `value_type` nested type allows the body to define the declaration of
|
||||
the body type as it appears in the message. This can be any type. For
|
||||
example, a body's value type may specify `std::vector<char>` or even
|
||||
example, a body's value type may specify `std::vector<char>` or
|
||||
`std::list<std::string>`. A custom body may even set the value type to
|
||||
something that is not a container for body octets, such as a
|
||||
[@boost:/libs/filesystem/doc/reference.html#class-path `boost::filesystem::path`].
|
||||
@@ -82,20 +82,14 @@ struct Body
|
||||
{
|
||||
using value_type = boost::property_tree::ptree;
|
||||
|
||||
class reader;
|
||||
|
||||
class reader
|
||||
class writer;
|
||||
|
||||
// Optional member
|
||||
static
|
||||
std::uint64_t
|
||||
size(value_type const&);
|
||||
};
|
||||
```
|
||||
|
||||
As long as a suitable reader or writer is available to provide the
|
||||
algorithm for transferring buffers in and out of the value type,
|
||||
those bodies may be serialized or parsed.
|
||||
those bodies may be parsed or serialized.
|
||||
|
||||
|
||||
|
||||
@@ -105,7 +99,9 @@ Use of the flexible __Body__ concept customization point enables authors to
|
||||
preserve the self-contained nature of the __message__ object while allowing
|
||||
domain specific behaviors. Common operations for HTTP servers include sending
|
||||
responses which deliver file contents, and allowing for file uploads. In this
|
||||
example we build the `basic_file_body` type which supports both reading and
|
||||
example we build the
|
||||
[link beast.ref.boost__beast__http__basic_file_body `basic_file_body`]
|
||||
type which supports both reading and
|
||||
writing to a file on the file system. The interface is a class templated
|
||||
on the type of file used to access the file system, which must meet the
|
||||
requirements of __File__.
|
||||
@@ -124,7 +120,7 @@ file is removed from the file system in between calls.
|
||||
|
||||
[example_http_file_body_2]
|
||||
|
||||
Our implementation of __BodyReader__ will contain a small buffer
|
||||
Our implementation of __BodyWriter__ will contain a small buffer
|
||||
from which the file contents are read. The buffer is provided to
|
||||
the implementation on each call until everything has been read in.
|
||||
|
||||
@@ -135,13 +131,13 @@ And here are the definitions for the functions we have declared:
|
||||
[example_http_file_body_4]
|
||||
|
||||
Files can be read now, and the next step is to allow writing to files
|
||||
by implementing the __BodyWriter__. The style is similar to the reader,
|
||||
by implementing the __BodyReader__. The style is similar to the writer,
|
||||
except that buffers are incoming instead of outgoing. Here's the
|
||||
declaration:
|
||||
|
||||
[example_http_file_body_5]
|
||||
|
||||
Finally, here is the implementation of the writer member functions:
|
||||
Finally, here is the implementation of the reader member functions:
|
||||
|
||||
[example_http_file_body_6]
|
||||
|
||||
|
@@ -33,26 +33,25 @@ In this table:
|
||||
[`B::value_type`]
|
||||
[]
|
||||
[
|
||||
The type of the `message::body` member.
|
||||
The return type of the `message::body` member function.
|
||||
If this is not movable or not copyable, the containing message
|
||||
will be not movable or not copyable.
|
||||
]
|
||||
][
|
||||
[`B::writer`]
|
||||
[]
|
||||
[
|
||||
If present, indicates that the body can hold a message body
|
||||
parsing result. The type must meet the requirements of
|
||||
__BodyWriter__. The implementation constructs an object of
|
||||
this type to obtain buffers into which parsed body octets
|
||||
are placed.
|
||||
]
|
||||
][
|
||||
[`B::reader`]
|
||||
[]
|
||||
[
|
||||
If present, indicates that the body is serializable. The type
|
||||
If present, indicates that the body can be parsed. The type
|
||||
must meet the requirements of __BodyReader__. The implementation
|
||||
constructs an object of this type to obtain buffers into which
|
||||
parsed body octets are placed.
|
||||
]
|
||||
][
|
||||
[`B::writer`]
|
||||
[]
|
||||
[
|
||||
If present, indicates that the body is serializable. The type
|
||||
must meet the requirements of __BodyWriter__. The implementation
|
||||
constructs an object of this type to obtain buffers representing
|
||||
the message body for serialization.
|
||||
]
|
||||
@@ -67,7 +66,8 @@ In this table:
|
||||
[
|
||||
This static member function is optional. It returns the payload
|
||||
size of `body` in bytes not including any chunked transfer encoding.
|
||||
The function shall not exit via an exception.
|
||||
The return value may be zero, to indicate that the message is known
|
||||
to have no payload. The function shall not exit via an exception.
|
||||
|
||||
When this function is present:
|
||||
|
||||
|
@@ -9,20 +9,18 @@
|
||||
|
||||
[section:BodyReader BodyReader]
|
||||
|
||||
A [*BodyReader] provides an
|
||||
[@https://en.wikipedia.org/wiki/Online_algorithm 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 one or more times to
|
||||
retrieve buffers holding body octets. The interface of [*BodyReader] is
|
||||
intended to obtain buffers for these scenarios:
|
||||
A [*BodyReader] provides an online algorithm to transfer a series of zero
|
||||
or more buffers containing parsed body octets into a message container. The
|
||||
__parser__ creates an instance of this type when needed, and calls into
|
||||
it zero or more times to transfer buffers. The interface of [*BodyReader]
|
||||
is intended to allow the conversion of buffers into these scenarios for
|
||||
representation:
|
||||
|
||||
* 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 whose size is not known ahead of time.
|
||||
* Body data generated dynamically from other threads.
|
||||
* Body data computed algorithmically.
|
||||
* Storing a body in a dynamic buffer
|
||||
* Storing a body in a user defined container with a custom allocator
|
||||
* Transformation of incoming body data before storage, for example
|
||||
to compress it first.
|
||||
* Saving body data to a file
|
||||
|
||||
[heading Associated Types]
|
||||
|
||||
@@ -37,68 +35,71 @@ In this table:
|
||||
* `B` denotes a __Body__ where
|
||||
`std::is_same<R, B::reader>::value == true`.
|
||||
* `a` denotes a value of type `R`.
|
||||
* `m` denotes a possibly const value of type `message&` where
|
||||
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
|
||||
* `b` is an object whose type meets the requirements of __ConstBufferSequence__
|
||||
* `m` denotes a value of type `message&` where
|
||||
`std::is_same<decltype(m.body), Body::value_type>::value == true`.
|
||||
* `n` is a value of type `boost::optional<std::uint64_t>`.
|
||||
* `ec` is a value of type [link beast.ref.boost__beast__error_code `error_code&`].
|
||||
* `R<T>` is the type `boost::optional<std::pair<T, bool>>`.
|
||||
|
||||
[table Valid expressions
|
||||
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
|
||||
[
|
||||
[`R::const_buffers_type`]
|
||||
[]
|
||||
[
|
||||
A type which meets the requirements of __ConstBufferSequence__.
|
||||
This is the type of buffer returned by `R::get`.
|
||||
]
|
||||
][
|
||||
[`R(m);`]
|
||||
[]
|
||||
[
|
||||
Constructible from `m`. The lifetime of `m` is guaranteed
|
||||
to end no earlier than after the `R` is destroyed.
|
||||
The reader shall not access the contents of `m` before the
|
||||
first call to `init`, permitting lazy construction of the
|
||||
Constructible from `m`. The lifetime of `m` is guaranteed to
|
||||
end no earlier than after the `R` is destroyed. The constructor
|
||||
will be called after a complete header is stored in `m`, and
|
||||
before parsing body octets for messages indicating that a body
|
||||
is present The reader shall not access the contents of `m` before
|
||||
the first call to `init`, permitting lazy construction of the
|
||||
message.
|
||||
|
||||
The constructor may optionally require that `m` is const, which
|
||||
has these consequences:
|
||||
|
||||
* If `R` requires that `m` is a const reference, then serializers
|
||||
constructed for messages with this body type will also require a
|
||||
const reference to a message, otherwise:
|
||||
|
||||
* If `R` requires that `m` is a non-const reference, then serializers
|
||||
constructed for messages with this body type will aso require
|
||||
a non-const reference to a message.
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
][
|
||||
[`a.init(ec)`]
|
||||
[`a.init(n, ec)`]
|
||||
[]
|
||||
[
|
||||
Called once to fully initialize the object before any calls to
|
||||
`get`. The message body becomes valid before entering this function,
|
||||
`put`. The message body is valid before entering this function,
|
||||
and remains valid until the reader is destroyed.
|
||||
The value of `n` will be set to the content length of the
|
||||
body if known, otherwise `n` will be equal to `boost::none`.
|
||||
Implementations of [*BodyReader] may use this information to
|
||||
optimize allocation.
|
||||
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
][
|
||||
[`a.get(ec)`]
|
||||
[`R<R::const_buffers_type>`]
|
||||
[`a.put(b,ec)`]
|
||||
[`std::size_t`]
|
||||
[
|
||||
Called one or more times after `init` succeeds. This function
|
||||
returns `boost::none` if all buffers representing the body have
|
||||
been returned in previous calls or if it sets `ec` to indicate an
|
||||
error. Otherwise, if there are buffers remaining the function
|
||||
should return a pair with the first element containing a non-zero
|
||||
length buffer sequence representing the next set of octets in
|
||||
the body, while the second element is a `bool` meaning `true`
|
||||
if there may be additional buffers returned on a subsequent call,
|
||||
or `false` if the buffer returned on this call is the last
|
||||
buffer representing the body.
|
||||
This function is called to append some or all of the buffers
|
||||
specified by `b` into the body representation. The number of
|
||||
bytes inserted from `b` is returned. If the number of bytes
|
||||
inserted is less than the total input, the remainder of the
|
||||
input will be presented in the next call to `put`.
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
][
|
||||
[`a.finish(ec)`]
|
||||
[]
|
||||
[
|
||||
This function is called when no more body octets are remaining.
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
][
|
||||
[`is_body_reader<B>`]
|
||||
[`std::true_type`]
|
||||
[
|
||||
An alias for `std::true_type` for `B`, otherwise an alias
|
||||
for `std::false_type`.
|
||||
]
|
||||
]]
|
||||
|
||||
[heading Exemplar]
|
||||
|
@@ -9,18 +9,20 @@
|
||||
|
||||
[section:BodyWriter BodyWriter]
|
||||
|
||||
A [*BodyWriter] provides an online algorithm to transfer a series of zero
|
||||
or more buffers containing parsed body octets into a message container. The
|
||||
__parser__ creates an instance of this type when needed, and calls into
|
||||
it zero or more times to transfer buffers. The interface of [*BodyWriter]
|
||||
is intended to allow the conversion of buffers into these scenarios for
|
||||
representation:
|
||||
A [*BodyWriter] provides an
|
||||
[@https://en.wikipedia.org/wiki/Online_algorithm 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 one or more times to
|
||||
retrieve buffers holding body octets. The interface of [*BodyWriter] is
|
||||
intended to obtain buffers for these scenarios:
|
||||
|
||||
* Storing a body in a dynamic buffer
|
||||
* Storing a body in a user defined container with a custom allocator
|
||||
* Transformation of incoming body data before storage, for example
|
||||
to compress it first.
|
||||
* Saving body data to a file
|
||||
* 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 whose size is not known ahead of time.
|
||||
* Body data generated dynamically from other threads.
|
||||
* Body data computed algorithmically.
|
||||
|
||||
[heading Associated Types]
|
||||
|
||||
@@ -35,71 +37,68 @@ In this table:
|
||||
* `B` denotes a __Body__ where
|
||||
`std::is_same<W, B::writer>::value == true`.
|
||||
* `a` denotes a value of type `W`.
|
||||
* `b` is an object whose type meets the requirements of __ConstBufferSequence__
|
||||
* `m` denotes a value of type `message&` where
|
||||
`std::is_same<decltype(m.body), Body::value_type>::value == true`.
|
||||
* `n` is a value of type `boost::optional<std::uint64_t>`.
|
||||
* `m` denotes a possibly const value of type `message&` where
|
||||
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
|
||||
* `ec` is a value of type [link beast.ref.boost__beast__error_code `error_code&`].
|
||||
* `W<T>` is the type `boost::optional<std::pair<T, bool>>`.
|
||||
|
||||
[table Valid expressions
|
||||
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
|
||||
[
|
||||
[`W::const_buffers_type`]
|
||||
[]
|
||||
[
|
||||
A type which meets the requirements of __ConstBufferSequence__.
|
||||
This is the type of buffer returned by `W::get`.
|
||||
]
|
||||
][
|
||||
[`W(m);`]
|
||||
[]
|
||||
[
|
||||
Constructible from `m`. The lifetime of `m` is guaranteed to
|
||||
end no earlier than after the `W` is destroyed. The constructor
|
||||
will be called after a complete header is stored in `m`, and
|
||||
before parsing body octets for messages indicating that a body
|
||||
is present The writer shall not access the contents of `m` before
|
||||
the first call to `init`, permitting lazy construction of the
|
||||
Constructible from `m`. The lifetime of `m` is guaranteed
|
||||
to end no earlier than after the `W` is destroyed.
|
||||
The writer shall not access the contents of `m` before the
|
||||
first call to `init`, permitting lazy construction of the
|
||||
message.
|
||||
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
The constructor may optionally require that `m` is const, which
|
||||
has these consequences:
|
||||
|
||||
* If `W` requires that `m` is a const reference, then serializers
|
||||
constructed for messages with this body type will also require a
|
||||
const reference to a message, otherwise:
|
||||
|
||||
* If `W` requires that `m` is a non-const reference, then serializers
|
||||
constructed for messages with this body type will aso require
|
||||
a non-const reference to a message.
|
||||
]
|
||||
][
|
||||
[`a.init(n, ec)`]
|
||||
[`a.init(ec)`]
|
||||
[]
|
||||
[
|
||||
Called once to fully initialize the object before any calls to
|
||||
`put`. The message body is valid before entering this function,
|
||||
`get`. The message body becomes valid before entering this function,
|
||||
and remains valid until the writer is destroyed.
|
||||
The value of `n` will be set to the content length of the
|
||||
body if known, otherwise `n` will be equal to `boost::none`.
|
||||
Implementations of [*BodyWriter] may use this information to
|
||||
optimize allocation.
|
||||
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
][
|
||||
[`a.put(b,ec)`]
|
||||
[`std::size_t`]
|
||||
[`a.get(ec)`]
|
||||
[`W<W::const_buffers_type>`]
|
||||
[
|
||||
This function is called to append some or all of the buffers
|
||||
specified by `b` into the body representation. The number of
|
||||
bytes inserted from `b` is returned. If the number of bytes
|
||||
inserted is less than the total input, the remainder of the
|
||||
input will be presented in the next call to `put`.
|
||||
Called one or more times after `init` succeeds. This function
|
||||
returns `boost::none` if all buffers representing the body have
|
||||
been returned in previous calls or if it sets `ec` to indicate an
|
||||
error. Otherwise, if there are buffers remaining the function
|
||||
should return a pair with the first element containing a non-zero
|
||||
length buffer sequence representing the next set of octets in
|
||||
the body, while the second element is a `bool` meaning `true`
|
||||
if there may be additional buffers returned on a subsequent call,
|
||||
or `false` if the buffer returned on this call is the last
|
||||
buffer representing the body.
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
][
|
||||
[`a.finish(ec)`]
|
||||
[]
|
||||
[
|
||||
This function is called when no more body octets are remaining.
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
][
|
||||
[`is_body_writer<B>`]
|
||||
[`std::true_type`]
|
||||
[
|
||||
An alias for `std::true_type` for `B`, otherwise an alias
|
||||
for `std::false_type`.
|
||||
]
|
||||
]]
|
||||
|
||||
[heading Exemplar]
|
||||
|
@@ -111,8 +111,8 @@
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="beast.ref.boost__beast__http__is_body">is_body</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__http__is_body_writer">is_body_writer</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__http__is_body_reader">is_body_reader</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__http__is_body_writer">is_body_writer</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__http__is_fields">is_fields</link></member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||
|
@@ -56,7 +56,7 @@ struct basic_dynamic_body
|
||||
return v.size();
|
||||
}
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
@@ -64,51 +64,13 @@ struct basic_dynamic_body
|
||||
using reader = implementation_defined;
|
||||
#else
|
||||
class reader
|
||||
{
|
||||
DynamicBuffer const& body_;
|
||||
|
||||
public:
|
||||
using const_buffers_type =
|
||||
typename DynamicBuffer::const_buffers_type;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
basic_dynamic_body, Fields> const& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
return {{body_.data(), false}};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
class writer
|
||||
{
|
||||
value_type& body_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest,
|
||||
reader(message<isRequest,
|
||||
basic_dynamic_body, Fields>& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
@@ -160,6 +122,44 @@ struct basic_dynamic_body
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
|
||||
Meets the requirements of @b BodyWriter.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
class writer
|
||||
{
|
||||
DynamicBuffer const& body_;
|
||||
|
||||
public:
|
||||
using const_buffers_type =
|
||||
typename DynamicBuffer::const_buffers_type;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest,
|
||||
basic_dynamic_body, Fields> const& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
return {{body_.data(), false}};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
} // http
|
||||
|
@@ -51,10 +51,10 @@ struct basic_file_body
|
||||
/// The type of File this body uses
|
||||
using file_type = File;
|
||||
|
||||
// Algorithm for retrieving buffers when serializing.
|
||||
// Algorithm for storing buffers when parsing.
|
||||
class reader;
|
||||
|
||||
// Algorithm for storing buffers when parsing.
|
||||
// Algorithm for retrieving buffers when serializing.
|
||||
class writer;
|
||||
|
||||
// The type of the @ref message::body member.
|
||||
@@ -225,7 +225,7 @@ size(value_type const& body)
|
||||
to extract the buffers representing the body.
|
||||
*/
|
||||
template<class File>
|
||||
class basic_file_body<File>::reader
|
||||
class basic_file_body<File>::writer
|
||||
{
|
||||
value_type& body_; // The body we are reading from
|
||||
std::uint64_t remain_; // The number of unread bytes
|
||||
@@ -239,8 +239,8 @@ public:
|
||||
|
||||
// Constructor.
|
||||
//
|
||||
// `m` holds the message we are sending, which will
|
||||
// always have the `file_body` as the body type.
|
||||
// `m` holds the message we are serializing, which will
|
||||
// always have the `basic_file_body` as the body type.
|
||||
//
|
||||
// Note that the message is passed by non-const reference.
|
||||
// This is intentional, because reading from the file
|
||||
@@ -248,7 +248,7 @@ public:
|
||||
// operation logically not-const (although it is bitwise
|
||||
// const).
|
||||
//
|
||||
// The BodyReader concept allows the reader to choose
|
||||
// The BodyWriter concept allows the writer to choose
|
||||
// whether to take the message by const reference or
|
||||
// non-const reference. Depending on the choice, a
|
||||
// serializer constructed using that body type will
|
||||
@@ -262,13 +262,13 @@ public:
|
||||
// a time.
|
||||
//
|
||||
template<bool isRequest, class Fields>
|
||||
reader(message<
|
||||
writer(message<
|
||||
isRequest, basic_file_body, Fields>& m);
|
||||
|
||||
// Initializer
|
||||
//
|
||||
// This is called before the body is serialized and
|
||||
// gives the reader a chance to do something that might
|
||||
// gives the writer a chance to do something that might
|
||||
// need to return an error code.
|
||||
//
|
||||
void
|
||||
@@ -295,8 +295,8 @@ public:
|
||||
template<class File>
|
||||
template<bool isRequest, class Fields>
|
||||
basic_file_body<File>::
|
||||
reader::
|
||||
reader(message<isRequest, basic_file_body, Fields>& m)
|
||||
writer::
|
||||
writer(message<isRequest, basic_file_body, Fields>& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
// The file must already be open
|
||||
@@ -310,7 +310,7 @@ reader(message<isRequest, basic_file_body, Fields>& m)
|
||||
template<class File>
|
||||
void
|
||||
basic_file_body<File>::
|
||||
reader::
|
||||
writer::
|
||||
init(error_code& ec)
|
||||
{
|
||||
// The error_code specification requires that we
|
||||
@@ -329,7 +329,7 @@ init(error_code& ec)
|
||||
template<class File>
|
||||
auto
|
||||
basic_file_body<File>::
|
||||
reader::
|
||||
writer::
|
||||
get(error_code& ec) ->
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
{
|
||||
@@ -389,7 +389,7 @@ get(error_code& ec) ->
|
||||
to store incoming buffers representing the body.
|
||||
*/
|
||||
template<class File>
|
||||
class basic_file_body<File>::writer
|
||||
class basic_file_body<File>::reader
|
||||
{
|
||||
value_type& body_; // The body we are writing to
|
||||
|
||||
@@ -399,17 +399,17 @@ public:
|
||||
// This is called after the header is parsed and
|
||||
// indicates that a non-zero sized body may be present.
|
||||
// `m` holds the message we are receiving, which will
|
||||
// always have the `file_body` as the body type.
|
||||
// always have the `basic_file_body` as the body type.
|
||||
//
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(
|
||||
reader(
|
||||
message<isRequest, basic_file_body, Fields>& m);
|
||||
|
||||
// Initializer
|
||||
//
|
||||
// This is called before the body is parsed and
|
||||
// gives the writer a chance to do something that might
|
||||
// gives the reader a chance to do something that might
|
||||
// need to return an error code. It informs us of
|
||||
// the payload size (`content_length`) which we can
|
||||
// optionally use for optimization.
|
||||
@@ -440,14 +440,14 @@ public:
|
||||
|
||||
//[example_http_file_body_6
|
||||
|
||||
// We don't do much in the writer constructor since the
|
||||
// We don't do much in the reader constructor since the
|
||||
// file is already open.
|
||||
//
|
||||
template<class File>
|
||||
template<bool isRequest, class Fields>
|
||||
basic_file_body<File>::
|
||||
writer::
|
||||
writer(message<isRequest, basic_file_body, Fields>& m)
|
||||
reader::
|
||||
reader(message<isRequest, basic_file_body, Fields>& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
}
|
||||
@@ -455,7 +455,7 @@ writer(message<isRequest, basic_file_body, Fields>& m)
|
||||
template<class File>
|
||||
void
|
||||
basic_file_body<File>::
|
||||
writer::
|
||||
reader::
|
||||
init(
|
||||
boost::optional<std::uint64_t> const& content_length,
|
||||
error_code& ec)
|
||||
@@ -482,7 +482,7 @@ template<class File>
|
||||
template<class ConstBufferSequence>
|
||||
std::size_t
|
||||
basic_file_body<File>::
|
||||
writer::
|
||||
reader::
|
||||
put(ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
// This function must return the total number of
|
||||
@@ -513,7 +513,7 @@ put(ConstBufferSequence const& buffers, error_code& ec)
|
||||
template<class File>
|
||||
void
|
||||
basic_file_body<File>::
|
||||
writer::
|
||||
reader::
|
||||
finish(error_code& ec)
|
||||
{
|
||||
// This has to be cleared before returning, to
|
||||
|
@@ -91,7 +91,7 @@ struct buffer_body
|
||||
bool more = true;
|
||||
};
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
@@ -99,6 +99,64 @@ struct buffer_body
|
||||
using reader = implementation_defined;
|
||||
#else
|
||||
class reader
|
||||
{
|
||||
value_type& body_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest, buffer_body, Fields>& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(boost::optional<std::uint64_t> const&, error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
std::size_t
|
||||
put(ConstBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::buffer_copy;
|
||||
if(! body_.data)
|
||||
{
|
||||
ec = error::need_buffer;
|
||||
return 0;
|
||||
}
|
||||
auto const bytes_transferred =
|
||||
buffer_copy(boost::asio::buffer(
|
||||
body_.data, body_.size), buffers);
|
||||
body_.data = reinterpret_cast<char*>(
|
||||
body_.data) + bytes_transferred;
|
||||
body_.size -= bytes_transferred;
|
||||
if(bytes_transferred == buffer_size(buffers))
|
||||
ec.assign(0, ec.category());
|
||||
else
|
||||
ec = error::need_buffer;
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
void
|
||||
finish(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
|
||||
Meets the requirements of @b BodyWriter.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
class writer
|
||||
{
|
||||
bool toggle_ = false;
|
||||
value_type const& body_;
|
||||
@@ -109,7 +167,7 @@ struct buffer_body
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
writer(message<isRequest,
|
||||
buffer_body, Fields> const& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
@@ -153,64 +211,6 @@ struct buffer_body
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
class writer
|
||||
{
|
||||
value_type& body_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest, buffer_body, Fields>& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(boost::optional<std::uint64_t> const&, error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
std::size_t
|
||||
put(ConstBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::buffer_copy;
|
||||
if(! body_.data)
|
||||
{
|
||||
ec = error::need_buffer;
|
||||
return 0;
|
||||
}
|
||||
auto const bytes_transferred =
|
||||
buffer_copy(boost::asio::buffer(
|
||||
body_.data, body_.size), buffers);
|
||||
body_.data = reinterpret_cast<char*>(
|
||||
body_.data) + bytes_transferred;
|
||||
body_.size -= bytes_transferred;
|
||||
if(bytes_transferred == buffer_size(buffers))
|
||||
ec.assign(0, ec.category());
|
||||
else
|
||||
ec = error::need_buffer;
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
void
|
||||
finish(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
#if ! BOOST_BEAST_DOXYGEN
|
||||
|
@@ -52,7 +52,7 @@ struct empty_body
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
@@ -61,43 +61,9 @@ struct empty_body
|
||||
#else
|
||||
struct reader
|
||||
{
|
||||
using const_buffers_type =
|
||||
boost::asio::null_buffers;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
empty_body, Fields> const&)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
return boost::none;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
struct writer
|
||||
{
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest, empty_body, Fields>&)
|
||||
reader(message<isRequest, empty_body, Fields>&)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -123,6 +89,40 @@ struct empty_body
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
|
||||
Meets the requirements of @b BodyWriter.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
struct writer
|
||||
{
|
||||
using const_buffers_type =
|
||||
boost::asio::null_buffers;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest,
|
||||
empty_body, Fields> const&)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
return boost::none;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
} // http
|
||||
|
@@ -42,15 +42,15 @@ struct basic_file_body<file_win32>
|
||||
{
|
||||
using file_type = file_win32;
|
||||
|
||||
class reader;
|
||||
class writer;
|
||||
class reader;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class value_type
|
||||
{
|
||||
friend class reader;
|
||||
friend class writer;
|
||||
friend class reader;
|
||||
friend struct basic_file_body<file_win32>;
|
||||
|
||||
template<class, class, bool, class>
|
||||
@@ -100,7 +100,7 @@ struct basic_file_body<file_win32>
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class reader
|
||||
class writer
|
||||
{
|
||||
template<class, class, bool, class>
|
||||
friend class detail::write_some_win32_op;
|
||||
@@ -123,7 +123,7 @@ struct basic_file_body<file_win32>
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
reader(message<isRequest,
|
||||
writer(message<isRequest,
|
||||
basic_file_body<file_win32>, Fields>& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
@@ -160,14 +160,14 @@ struct basic_file_body<file_win32>
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class writer
|
||||
class reader
|
||||
{
|
||||
value_type& body_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest, basic_file_body, Fields>& m)
|
||||
reader(message<isRequest, basic_file_body, Fields>& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
}
|
||||
|
@@ -44,7 +44,7 @@ parser(parser<isRequest, OtherBody, Allocator>&& other,
|
||||
, m_(other.release(), std::forward<Args>(args)...)
|
||||
, wr_(m_)
|
||||
{
|
||||
if(other.wr_inited_)
|
||||
if(other.rd_inited_)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
||||
"moved-from parser has a body"});
|
||||
}
|
||||
|
@@ -738,8 +738,8 @@ read(
|
||||
"DynamicBuffer requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
error_code ec;
|
||||
auto const bytes_transferred =
|
||||
read(stream, buffer, msg, ec);
|
||||
@@ -766,8 +766,8 @@ read(
|
||||
"DynamicBuffer requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
parser<isRequest, Body, Allocator> p{std::move(msg)};
|
||||
p.eager(true);
|
||||
auto const bytes_transferred =
|
||||
@@ -798,8 +798,8 @@ async_read(
|
||||
"DynamicBuffer requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
boost::asio::async_completion<
|
||||
ReadHandler,
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
|
@@ -499,8 +499,8 @@ write_some(
|
||||
"SyncWriteStream requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
error_code ec;
|
||||
auto const bytes_transferred =
|
||||
write_some(stream, sr, ec);
|
||||
@@ -522,8 +522,8 @@ write_some(
|
||||
"SyncWriteStream requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
return detail::write_some(stream, sr, ec);
|
||||
}
|
||||
|
||||
@@ -543,8 +543,8 @@ async_write_some(
|
||||
"AsyncWriteStream requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
return detail::async_write_some(stream, sr,
|
||||
std::forward<WriteHandler>(handler));
|
||||
}
|
||||
@@ -562,8 +562,8 @@ write_header(SyncWriteStream& stream,
|
||||
"SyncWriteStream requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
error_code ec;
|
||||
auto const bytes_transferred =
|
||||
write_header(stream, sr, ec);
|
||||
@@ -585,8 +585,8 @@ write_header(
|
||||
"SyncWriteStream requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
sr.split(true);
|
||||
std::size_t bytes_transferred = 0;
|
||||
if(! sr.is_header_done())
|
||||
@@ -626,8 +626,8 @@ async_write_header(
|
||||
"AsyncWriteStream requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
sr.split(true);
|
||||
boost::asio::async_completion<
|
||||
WriteHandler,
|
||||
@@ -703,8 +703,8 @@ async_write(
|
||||
"AsyncWriteStream requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
sr.split(false);
|
||||
boost::asio::async_completion<
|
||||
WriteHandler,
|
||||
@@ -733,8 +733,8 @@ write(
|
||||
"SyncWriteStream requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
error_code ec;
|
||||
auto const bytes_transferred =
|
||||
write(stream, msg, ec);
|
||||
@@ -756,8 +756,8 @@ write(
|
||||
"SyncWriteStream requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
serializer<isRequest, Body, Fields> sr{msg};
|
||||
return write(stream, sr, ec);
|
||||
}
|
||||
@@ -778,8 +778,8 @@ async_write(
|
||||
"AsyncWriteStream requirements not met");
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
boost::asio::async_completion<
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
@@ -860,8 +860,8 @@ operator<<(std::ostream& os,
|
||||
{
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
serializer<isRequest, Body, Fields> sr{msg};
|
||||
error_code ec;
|
||||
detail::write_ostream_lambda<decltype(sr)> f{os, sr};
|
||||
|
@@ -53,8 +53,8 @@ class parser
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
|
||||
template<bool, class, class>
|
||||
friend class parser;
|
||||
@@ -63,8 +63,8 @@ class parser
|
||||
parser<isRequest, Body, Allocator>>;
|
||||
|
||||
message<isRequest, Body, basic_fields<Allocator>> m_;
|
||||
typename Body::writer wr_;
|
||||
bool wr_inited_ = false;
|
||||
typename Body::reader wr_;
|
||||
bool rd_inited_ = false;
|
||||
|
||||
std::function<void(
|
||||
std::uint64_t,
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
This constructs a new parser by move constructing the
|
||||
header from another parser with a different body type. The
|
||||
constructed-from parser must not have any parsed body octets or
|
||||
initialized @b BodyWriter, otherwise an exception is generated.
|
||||
initialized @b BodyReader, otherwise an exception is generated.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
@@ -148,7 +148,7 @@ public:
|
||||
constructor.
|
||||
|
||||
@throws std::invalid_argument Thrown when the constructed-from
|
||||
parser has already initialized a body writer.
|
||||
parser has already initialized a body reader.
|
||||
|
||||
@note This function participates in overload resolution only
|
||||
if the other parser uses a different body type.
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
BOOST_STATIC_ASSERT(! std::is_const<Callback>::value);
|
||||
|
||||
// Can't set the callback after receiving any chunk data!
|
||||
BOOST_ASSERT(! wr_inited_);
|
||||
BOOST_ASSERT(! rd_inited_);
|
||||
|
||||
cb_h_ = std::ref(cb);
|
||||
}
|
||||
@@ -295,7 +295,7 @@ public:
|
||||
BOOST_STATIC_ASSERT(! std::is_const<Callback>::value);
|
||||
|
||||
// Can't set the callback after receiving any chunk data!
|
||||
BOOST_ASSERT(! wr_inited_);
|
||||
BOOST_ASSERT(! rd_inited_);
|
||||
|
||||
cb_b_ = std::ref(cb);
|
||||
}
|
||||
@@ -377,7 +377,7 @@ private:
|
||||
error_code& ec)
|
||||
{
|
||||
wr_.init(content_length, ec);
|
||||
wr_inited_ = true;
|
||||
rd_inited_ = true;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
|
@@ -60,22 +60,22 @@ public:
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
|
||||
/** The type of message this serializer uses
|
||||
|
||||
This may be const or non-const depending on the
|
||||
implementation of the corresponding @b BodyReader.
|
||||
implementation of the corresponding @b BodyWriter.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using value_type = implementation_defined;
|
||||
#else
|
||||
using value_type =
|
||||
typename std::conditional<
|
||||
std::is_constructible<typename Body::reader,
|
||||
std::is_constructible<typename Body::writer,
|
||||
message<isRequest, Body, Fields>&>::value &&
|
||||
! std::is_constructible<typename Body::reader,
|
||||
! std::is_constructible<typename Body::writer,
|
||||
message<isRequest, Body, Fields> const&>::value,
|
||||
message<isRequest, Body, Fields>,
|
||||
message<isRequest, Body, Fields> const>::type;
|
||||
@@ -111,7 +111,7 @@ private:
|
||||
void
|
||||
do_visit(error_code& ec, Visit& visit);
|
||||
|
||||
using reader = typename Body::reader;
|
||||
using writer = typename Body::writer;
|
||||
|
||||
using cb1_t = buffers_suffix<typename
|
||||
Fields::writer::const_buffers_type>; // header
|
||||
@@ -119,11 +119,11 @@ private:
|
||||
|
||||
using cb2_t = buffers_suffix<buffers_cat_view<
|
||||
typename Fields::writer::const_buffers_type,// header
|
||||
typename reader::const_buffers_type>>; // body
|
||||
typename writer::const_buffers_type>>; // body
|
||||
using pcb2_t = buffers_prefix_view<cb2_t const&>;
|
||||
|
||||
using cb3_t = buffers_suffix<
|
||||
typename reader::const_buffers_type>; // body
|
||||
typename writer::const_buffers_type>; // body
|
||||
using pcb3_t = buffers_prefix_view<cb3_t const&>;
|
||||
|
||||
using cb4_t = buffers_suffix<buffers_cat_view<
|
||||
@@ -131,7 +131,7 @@ private:
|
||||
detail::chunk_size, // chunk-size
|
||||
boost::asio::const_buffer, // chunk-ext
|
||||
chunk_crlf, // crlf
|
||||
typename reader::const_buffers_type, // body
|
||||
typename writer::const_buffers_type, // body
|
||||
chunk_crlf>>; // crlf
|
||||
using pcb4_t = buffers_prefix_view<cb4_t const&>;
|
||||
|
||||
@@ -139,7 +139,7 @@ private:
|
||||
detail::chunk_size, // chunk-header
|
||||
boost::asio::const_buffer, // chunk-ext
|
||||
chunk_crlf, // crlf
|
||||
typename reader::const_buffers_type, // body
|
||||
typename writer::const_buffers_type, // body
|
||||
chunk_crlf>>; // crlf
|
||||
using pcb5_t = buffers_prefix_view<cb5_t const&>;
|
||||
|
||||
@@ -147,7 +147,7 @@ private:
|
||||
detail::chunk_size, // chunk-header
|
||||
boost::asio::const_buffer, // chunk-size
|
||||
chunk_crlf, // crlf
|
||||
typename reader::const_buffers_type, // body
|
||||
typename writer::const_buffers_type, // body
|
||||
chunk_crlf, // crlf
|
||||
boost::asio::const_buffer, // chunk-final
|
||||
boost::asio::const_buffer, // trailers
|
||||
@@ -159,7 +159,7 @@ private:
|
||||
detail::chunk_size, // chunk-size
|
||||
boost::asio::const_buffer, // chunk-ext
|
||||
chunk_crlf, // crlf
|
||||
typename reader::const_buffers_type, // body
|
||||
typename writer::const_buffers_type, // body
|
||||
chunk_crlf, // crlf
|
||||
boost::asio::const_buffer, // chunk-final
|
||||
boost::asio::const_buffer, // trailers
|
||||
@@ -173,7 +173,7 @@ private:
|
||||
using pcb8_t = buffers_prefix_view<cb8_t const&>;
|
||||
|
||||
value_type& m_;
|
||||
reader rd_;
|
||||
writer rd_;
|
||||
boost::optional<typename Fields::writer> frd_;
|
||||
beast::detail::variant<
|
||||
cb1_t, cb2_t, cb3_t, cb4_t,
|
||||
@@ -210,7 +210,7 @@ public:
|
||||
the type of Body used, this may or may not be a `const` reference.
|
||||
|
||||
@note This function participates in overload resolution only if
|
||||
Body::reader is constructible from a `const` message reference.
|
||||
Body::writer is constructible from a `const` message reference.
|
||||
*/
|
||||
explicit
|
||||
serializer(value_type& msg);
|
||||
@@ -336,17 +336,17 @@ public:
|
||||
void
|
||||
consume(std::size_t n);
|
||||
|
||||
/** Provides low-level access to the associated @b BodyReader
|
||||
/** Provides low-level access to the associated @b BodyWriter
|
||||
|
||||
This function provides access to the instance of the reader
|
||||
This function provides access to the instance of the writer
|
||||
associated with the body and created by the serializer
|
||||
upon construction. The behavior of accessing this object
|
||||
is defined by the specification of the particular reader
|
||||
is defined by the specification of the particular writer
|
||||
and its associated body.
|
||||
|
||||
@return A reference to the reader.
|
||||
@return A reference to the writer.
|
||||
*/
|
||||
reader&
|
||||
writer&
|
||||
reader_impl()
|
||||
{
|
||||
return rd_;
|
||||
|
@@ -59,7 +59,7 @@ public:
|
||||
return body.size();
|
||||
}
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
@@ -67,55 +67,13 @@ public:
|
||||
using reader = implementation_defined;
|
||||
#else
|
||||
class reader
|
||||
{
|
||||
value_type const& body_;
|
||||
|
||||
public:
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
span_body, Fields> const& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
return {{
|
||||
{ body_.data(),
|
||||
body_.size() * sizeof(typename
|
||||
value_type::value_type)},
|
||||
false}};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
class writer
|
||||
{
|
||||
value_type& body_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest,
|
||||
reader(message<isRequest,
|
||||
span_body, Fields>& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
@@ -162,6 +120,48 @@ public:
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
|
||||
Meets the requirements of @b BodyWriter.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
class writer
|
||||
{
|
||||
value_type const& body_;
|
||||
|
||||
public:
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest,
|
||||
span_body, Fields> const& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
return {{
|
||||
{ body_.data(),
|
||||
body_.size() * sizeof(typename
|
||||
value_type::value_type)},
|
||||
false}};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
} // http
|
||||
|
@@ -67,7 +67,7 @@ public:
|
||||
return body.size();
|
||||
}
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
@@ -75,52 +75,13 @@ public:
|
||||
using reader = implementation_defined;
|
||||
#else
|
||||
class reader
|
||||
{
|
||||
value_type const& body_;
|
||||
|
||||
public:
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
basic_string_body, Fields> const& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
return {{const_buffers_type{
|
||||
body_.data(), body_.size()}, false}};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
class writer
|
||||
{
|
||||
value_type& body_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest,
|
||||
reader(message<isRequest,
|
||||
basic_string_body, Fields>& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
@@ -188,6 +149,45 @@ public:
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
|
||||
Meets the requirements of @b BodyWriter.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
class writer
|
||||
{
|
||||
value_type const& body_;
|
||||
|
||||
public:
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest,
|
||||
basic_string_body, Fields> const& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
return {{const_buffers_type{
|
||||
body_.data(), body_.size()}, false}};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
/// A @b Body using `std::string`
|
||||
|
@@ -57,7 +57,7 @@ using is_body = detail::has_value_type<T>;
|
||||
|
||||
@li `T` has a nested type named `reader`
|
||||
|
||||
@li The nested type meets the requirements of @b BodyReader.
|
||||
@li The nested type meets the requirements of @b BodyWriter.
|
||||
|
||||
@tparam T The body type to test.
|
||||
|
||||
@@ -65,55 +65,9 @@ using is_body = detail::has_value_type<T>;
|
||||
@code
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void check_can_serialize(message<isRequest, Body, Fields> const&)
|
||||
{
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"Cannot serialize Body, no reader");
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
#if BOOST_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,
|
||||
boost::asio::is_const_buffer_sequence<
|
||||
typename T::reader::const_buffers_type>::value &&
|
||||
std::is_constructible<typename T::reader,
|
||||
message<true, T, detail::fields_model>&>::value &&
|
||||
std::is_constructible<typename T::reader,
|
||||
message<false, T, detail::fields_model>&>::value
|
||||
> {};
|
||||
#endif
|
||||
|
||||
/** Determine if a @b Body type has a writer.
|
||||
|
||||
This metafunction is equivalent to `std::true_type` if:
|
||||
|
||||
@li `T` has a nested type named `writer`
|
||||
|
||||
@li The nested type meets the requirements of @b BodyWriter.
|
||||
|
||||
@tparam T The body type to test.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void check_can_parse(message<isRequest, Body, Fields>&)
|
||||
{
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"Cannot parse Body, no writer");
|
||||
"Cannot serialize Body, no reader");
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
@@ -125,20 +79,66 @@ template<class T, class = void>
|
||||
struct is_body_writer : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_body_writer<T, beast::detail::void_t<decltype(
|
||||
std::declval<typename T::writer&>().init(
|
||||
struct is_body_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,
|
||||
boost::asio::is_const_buffer_sequence<
|
||||
typename T::writer::const_buffers_type>::value &&
|
||||
std::is_constructible<typename T::writer,
|
||||
message<true, T, detail::fields_model>&>::value &&
|
||||
std::is_constructible<typename T::writer,
|
||||
message<false, T, detail::fields_model>&>::value
|
||||
> {};
|
||||
#endif
|
||||
|
||||
/** Determine if a @b Body type has a reader.
|
||||
|
||||
This metafunction is equivalent to `std::true_type` if:
|
||||
|
||||
@li `T` has a nested type named `reader`
|
||||
|
||||
@li The nested type meets the requirements of @b BodyReader.
|
||||
|
||||
@tparam T The body type to test.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void check_can_parse(message<isRequest, Body, Fields>&)
|
||||
{
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"Cannot parse Body, no reader");
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
#if BOOST_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<decltype(
|
||||
std::declval<typename T::reader&>().init(
|
||||
boost::optional<std::uint64_t>(),
|
||||
std::declval<error_code&>()),
|
||||
std::declval<std::size_t&>() =
|
||||
std::declval<typename T::writer&>().put(
|
||||
std::declval<typename T::reader&>().put(
|
||||
std::declval<boost::asio::const_buffer>(),
|
||||
std::declval<error_code&>()),
|
||||
std::declval<typename T::writer&>().finish(
|
||||
std::declval<typename T::reader&>().finish(
|
||||
std::declval<error_code&>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
std::is_constructible<typename T::writer,
|
||||
std::is_constructible<typename T::reader,
|
||||
message<true, T, detail::fields_model>&>::value &&
|
||||
std::is_constructible<typename T::writer,
|
||||
std::is_constructible<typename T::reader,
|
||||
message<false, T, detail::fields_model>&>::value
|
||||
>
|
||||
{
|
||||
|
@@ -62,7 +62,7 @@ public:
|
||||
return body.size();
|
||||
}
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
@@ -70,52 +70,13 @@ public:
|
||||
using reader = implementation_defined;
|
||||
#else
|
||||
class reader
|
||||
{
|
||||
value_type const& body_;
|
||||
|
||||
public:
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
vector_body, Fields> const& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
return {{const_buffers_type{
|
||||
body_.data(), body_.size()}, false}};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for parsing the body
|
||||
|
||||
Meets the requirements of @b BodyReader.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
class writer
|
||||
{
|
||||
value_type& body_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest,
|
||||
reader(message<isRequest,
|
||||
vector_body, Fields>& m)
|
||||
: body_(m.body())
|
||||
{
|
||||
@@ -177,6 +138,45 @@ public:
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The algorithm for serializing the body
|
||||
|
||||
Meets the requirements of @b BodyWriter.
|
||||
*/
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using writer = implementation_defined;
|
||||
#else
|
||||
class writer
|
||||
{
|
||||
value_type const& body_;
|
||||
|
||||
public:
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest,
|
||||
vector_body, Fields> const& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
return {{const_buffers_type{
|
||||
body_.data(), body_.size()}, false}};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
} // http
|
||||
|
@@ -15,8 +15,8 @@ namespace beast {
|
||||
namespace http {
|
||||
|
||||
BOOST_STATIC_ASSERT(is_body<empty_body>::value);
|
||||
BOOST_STATIC_ASSERT(is_body_reader<empty_body>::value);
|
||||
BOOST_STATIC_ASSERT(is_body_writer<empty_body>::value);
|
||||
BOOST_STATIC_ASSERT(is_body_reader<empty_body>::value);
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
@@ -24,13 +24,13 @@ public:
|
||||
{
|
||||
struct value_type{};
|
||||
|
||||
struct reader
|
||||
struct writer
|
||||
{
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
reader(message<isRequest, const_body, Fields> const&);
|
||||
writer(message<isRequest, const_body, Fields> const&);
|
||||
|
||||
void
|
||||
init(error_code& ec);
|
||||
@@ -44,13 +44,13 @@ public:
|
||||
{
|
||||
struct value_type{};
|
||||
|
||||
struct reader
|
||||
struct writer
|
||||
{
|
||||
using const_buffers_type =
|
||||
boost::asio::const_buffer;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
reader(message<isRequest, mutable_body, Fields>&);
|
||||
writer(message<isRequest, mutable_body, Fields>&);
|
||||
|
||||
void
|
||||
init(error_code& ec);
|
||||
|
@@ -34,7 +34,7 @@ struct span_body_test
|
||||
BEAST_EXPECT(req.body().size() == 3);
|
||||
BEAST_EXPECT(B::size(req.body()) == 3);
|
||||
|
||||
B::reader r{req};
|
||||
B::writer r{req};
|
||||
error_code ec;
|
||||
r.init(ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
@@ -50,7 +50,7 @@ struct span_body_test
|
||||
using B = span_body<char>;
|
||||
request<B> req;
|
||||
req.body() = span<char>{buf, sizeof(buf)};
|
||||
B::writer w{req};
|
||||
B::reader w{req};
|
||||
error_code ec;
|
||||
w.init(boost::none, ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
|
@@ -15,8 +15,8 @@ namespace beast {
|
||||
namespace http {
|
||||
|
||||
BOOST_STATIC_ASSERT(is_body<string_body>::value);
|
||||
BOOST_STATIC_ASSERT(is_body_reader<string_body>::value);
|
||||
BOOST_STATIC_ASSERT(is_body_writer<string_body>::value);
|
||||
BOOST_STATIC_ASSERT(is_body_reader<string_body>::value);
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
@@ -17,11 +17,11 @@ namespace boost {
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
BOOST_STATIC_ASSERT(! is_body_reader<int>::value);
|
||||
BOOST_STATIC_ASSERT(! is_body_writer<int>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(is_body_reader<empty_body>::value);
|
||||
BOOST_STATIC_ASSERT(is_body_writer<empty_body>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(! is_body_writer<std::string>::value);
|
||||
BOOST_STATIC_ASSERT(! is_body_reader<std::string>::value);
|
||||
|
||||
namespace {
|
||||
|
||||
|
@@ -15,8 +15,8 @@ namespace beast {
|
||||
namespace http {
|
||||
|
||||
BOOST_STATIC_ASSERT(is_body<vector_body<char>>::value);
|
||||
BOOST_STATIC_ASSERT(is_body_reader<vector_body<char>>::value);
|
||||
BOOST_STATIC_ASSERT(is_body_writer<vector_body<char>>::value);
|
||||
BOOST_STATIC_ASSERT(is_body_reader<vector_body<char>>::value);
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
@@ -38,7 +38,7 @@ public:
|
||||
{
|
||||
using value_type = std::string;
|
||||
|
||||
class reader
|
||||
class writer
|
||||
{
|
||||
value_type const& body_;
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
|
||||
template<bool isRequest, class Allocator>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
writer(message<isRequest,
|
||||
unsized_body, Allocator> const& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
bool mutable read = false;
|
||||
};
|
||||
|
||||
class reader
|
||||
class writer
|
||||
{
|
||||
int step_ = 0;
|
||||
value_type const& body_;
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
writer(message<isRequest,
|
||||
test_body, Fields> const& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
@@ -195,11 +195,11 @@ public:
|
||||
|
||||
struct fail_body
|
||||
{
|
||||
class reader;
|
||||
class writer;
|
||||
|
||||
class value_type
|
||||
{
|
||||
friend class reader;
|
||||
friend class writer;
|
||||
|
||||
std::string s_;
|
||||
test::fail_counter& fc_;
|
||||
@@ -219,7 +219,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class reader
|
||||
class writer
|
||||
{
|
||||
std::size_t n_ = 0;
|
||||
value_type const& body_;
|
||||
@@ -230,7 +230,7 @@ public:
|
||||
|
||||
template<bool isRequest, class Allocator>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
writer(message<isRequest,
|
||||
fail_body, Allocator> const& msg)
|
||||
: body_(msg.body())
|
||||
{
|
||||
|
@@ -19,8 +19,8 @@ namespace boost {
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class BodyReader;
|
||||
class BodyWriter;
|
||||
class BodyReader;
|
||||
|
||||
//[concept_Body
|
||||
|
||||
@@ -29,10 +29,10 @@ struct Body
|
||||
// The type of message::body when used
|
||||
struct value_type;
|
||||
|
||||
/// The algorithm used for extracting buffers
|
||||
/// The algorithm used during parsing
|
||||
class reader;
|
||||
|
||||
/// The algorithm used for inserting buffers
|
||||
/// The algorithm used during serialization
|
||||
class writer;
|
||||
|
||||
/// Returns the body's payload size
|
||||
@@ -45,27 +45,27 @@ static_assert(is_body<Body>::value, "");
|
||||
|
||||
//]
|
||||
|
||||
struct Body_BodyReader {
|
||||
struct Body_BodyWriter {
|
||||
struct value_type{};
|
||||
//[concept_BodyReader
|
||||
//[concept_BodyWriter
|
||||
|
||||
struct BodyReader
|
||||
struct BodyWriter
|
||||
{
|
||||
public:
|
||||
/// The type of buffer returned by `get`.
|
||||
using const_buffers_type = boost::asio::const_buffer;
|
||||
|
||||
/** Construct the reader.
|
||||
/** Construct the writer.
|
||||
|
||||
@param msg The message whose body is to be retrieved.
|
||||
@param msg The message whose body is to be serialized.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
explicit
|
||||
BodyReader(message<isRequest, Body, Fields> const& msg);
|
||||
BodyWriter(message<isRequest, Body, Fields> const& msg);
|
||||
|
||||
/** Initialize the reader
|
||||
/** Initialize the writer.
|
||||
|
||||
This is called after construction and before the first
|
||||
call to `get`. The message is valid and complete upon
|
||||
@@ -109,26 +109,26 @@ public:
|
||||
};
|
||||
|
||||
//]
|
||||
using reader = BodyReader;
|
||||
using writer = BodyWriter;
|
||||
};
|
||||
|
||||
static_assert(is_body_reader<Body_BodyReader>::value, "");
|
||||
static_assert(is_body_writer<Body_BodyWriter>::value, "");
|
||||
|
||||
struct Body_BodyWriter {
|
||||
struct Body_BodyReader {
|
||||
struct value_type{};
|
||||
//[concept_BodyWriter
|
||||
//[concept_BodyReader
|
||||
|
||||
struct BodyWriter
|
||||
struct BodyReader
|
||||
{
|
||||
/** Construct the writer.
|
||||
/** Construct the reader.
|
||||
|
||||
@param msg The message whose body is to be stored.
|
||||
@param msg The message whose body is to be parsed.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
explicit
|
||||
BodyWriter(message<isRequest, Body, Fields>& msg);
|
||||
BodyReader(message<isRequest, Body, Fields>& msg);
|
||||
|
||||
/** Initialize the writer
|
||||
/** Initialize the reader.
|
||||
|
||||
This is called after construction and before the first
|
||||
call to `put`. The message is valid and complete upon
|
||||
@@ -180,10 +180,10 @@ struct BodyWriter
|
||||
};
|
||||
|
||||
//]
|
||||
using writer = BodyWriter;
|
||||
using reader = BodyReader;
|
||||
};
|
||||
|
||||
static_assert(is_body_writer<Body_BodyWriter>::value, "");
|
||||
static_assert(is_body_reader<Body_BodyReader>::value, "");
|
||||
|
||||
//[concept_Fields
|
||||
|
||||
|
@@ -299,7 +299,7 @@ void fxx() {
|
||||
the @b SyncWriteStream concept.
|
||||
|
||||
@param m The message to send. The Body type must support
|
||||
the @b BodyReader concept.
|
||||
the @b BodyWriter concept.
|
||||
*/
|
||||
template<
|
||||
class SyncWriteStream,
|
||||
@@ -312,8 +312,8 @@ send(
|
||||
// Check the template types
|
||||
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||
"SyncWriteStream requirements not met");
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"BodyWriter requirements not met");
|
||||
|
||||
// Create the instance of serializer for the message
|
||||
serializer<isRequest, Body, Fields> sr{m};
|
||||
|
Reference in New Issue
Block a user