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:
Vinnie Falco
2017-10-30 17:08:52 -07:00
parent 101023553e
commit 895c9fa7ed
29 changed files with 582 additions and 583 deletions

View File

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

View File

@@ -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]

View File

@@ -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:

View File

@@ -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]

View File

@@ -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]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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())
{
}

View File

@@ -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"});
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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`

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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