[/ Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] [section:BodyReader BodyReader] A [*BodyReader] provides an online algorithm to obtain a sequence of zero or more buffers from a body during serialization. The implementation creates an instance of this type when needed, and calls into it one or more times to retrieve buffers holding body octets. The interface of [*BodyReader] is intended to obtain buffers for these scenarios: * A body that does not entirely fit in memory. * A body produced incrementally from coroutine output. * A body represented by zero or more buffers already in memory. * A body whose size is not known ahead of time. * Body data generated dynamically from other threads. * Body data computed algorithmically. In this table: * `X` denotes a type meeting the requirements of [*BodyReader]. * `B` denotes a __Body__ where `std::is_same::value == true`. * `a` denotes a value of type `X`. * `m` denotes a value of type `message const&` where `std::is_same:value == true`. * `ec` is a value of type [link beast.ref.beast__error_code `error_code&`]. * `R` is the type `boost::optional>`. [table BodyReader requirements [[expression] [type] [semantics, pre/post-conditions]] [ [`X::const_buffers_type`] [] [ A type which meets the requirements of __ConstBufferSequence__. This is the type of buffer returned by `X::get`. ] ][ [`X::is_deferred`] [] [ The type `std::true_type` if the serialization implementation should only attempt to retrieve buffers from the reader after the header has been serialized. Otherwise, if this type is `std::false_type` the implementation will activate an optimization: the first buffer produced during serialization will contain both the header and some or all of this body. Implementations of [*BodyReader] for which initialization is expensive, should use `std::false_type` here, to reduce the latency experienced by the remote host when expecting to read the HTTP header. ] ][ [`X(m);`] [] [ Constructible from `m`. The lifetime of `m` is guaranteed to end no earlier than after the `X` is destroyed. ] ][ [`a.init(ec)`] [] [ Called immediately after construction. 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`] [ Called repeatedly 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 after the reader indicates there are no more buffers 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`] [`std::true_type`] [ An alias for `std::true_type` for `B`, otherwise an alias for `std::false_type`. ] ] ] [note Definitions for required [*BodyReader] member functions may be declared inline so the generated code can become part of the implementation. ] Exemplar: ``` struct reader { public: /** Controls when the implementation requests buffers. If false, the implementation will request the first buffer immediately and try to serialize both the header and some or all of the body in a single buffer. */ using is_deferred = std::false_type; /// The type of buffer returned by `get`. using const_buffers_type = boost::asio::const_buffers_1; /** Construct the reader. @param msg The message whose body is to be retrieved. */ template explicit reader(message const& msg); /** Initialization. Called once immediately after construction. @param ec Set to the error, if any occurred. */ void init(error_code& ec) { // The specification requires this to indicate "no error" ec = {}; } /** Returns the next buffer in the body. @li If the return value is `boost::none` (unseated optional) and `ec` does not contain an error, this indicates the end of the body, no more buffers are present. @li If the optional contains a value, the first element of the pair represents a @b ConstBufferSequence containing one or more octets of the body data. The second element indicates whether or not there are additional octets of body data. A value of `true` means there is more data, and that the implementation will perform a subsequent call to `get`. A value of `false` means there is no more body data. @li If `ec` contains an error code, the return value is ignored. @param ec Set to the error, if any occurred. */ boost::optional> get(error_code& ec); /** Called after `get` indicates there are no more buffers. @param ec Set to the error, if any occurred. */ void finish(error_code& ec); }; ``` [endsect]