[/ 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:BodyWriter BodyWriter requirements] When HTTP messages are parsed, the implementation constructs a [*BodyWriter] object to provide the means for transferring parsed body octets into the message container. These body writers come in two flavors, direct and indirect: Direct writers provide a buffer to callers, into which body data is placed. This type of writer is used when the bytes corresponding to the body data are stored without transformation. The parse algorithm performs stream or socket reads directly into the buffer provided by the writer, hence the name "direct." This model avoids an unnecessary buffer copy. An example of a __Body__ type with a direct writer is [link beast.ref.http__string_body `string_body`]. Indirect writers are passed body data in a buffer managed by the parsing algorithm. This writer is appropriate when the body data is transformed or not otherwised stored verbatim. Some examples of when an indirect writer is appropriate: * When bytes corresponding to the body are written to a file as they are parsed. * The content of the message is JSON, which is parsed as it is being read in, and stored in a structured, hierarchical format. In the tables below: * `X` denotes a type meeting the requirements of [*Writer]. * `B` denotes a __Body__ where `std::is_same::value == true`. * `a` denotes a value of type `X`. * `n` is a value convertible to `std::size_t` without loss of precision. * `v` is a value convertible to `std::uint64_t` without loss of precision. * `s` is a value of type [link beast.ref.string_view `string_view`]. * `ec` is a value of type [link beast.ref.error_code `error_code&`]. * `m` denotes a value of type `message&` where `std::is_same::value == true`. [table Direct Writer requirements [[expression] [type] [semantics, pre/post-conditions]] [ [`X::is_direct`] [`bool`] [ This static constant must be set to `true` to indicate this is a direct writer. ] ] [ [`X::mutable_buffers_type`] [] [ A type which meets the requirements of __MutableBufferSequence__. ] ] [ [`X a{m};`] [] [ `a` is constructible from `m`. The lifetime of `m` is guaranteed to end no earlier than after `a` is destroyed. The constructor will be called after all headers have been stored in `m`, and just before parsing bytes corresponding to the body for messages whose semantics indicate that a body is present with non-zero length. ] ] [ [`a.init()`] [] [ This function is called once before any bytes corresponding to the body are presented to the writer, for messages whose body is determined by the end-of-file marker on a stream, or for messages where the chunked Transfer-Encoding is specified. ] ] [ [`a.init(v)`] [] [ This function is called once before any bytes corresponding to the body are presented to the writer, for messages where the Content-Length is specified. The value of `v` will be set to the number of bytes indicated by the content length. ] ] [ [`a.prepare(n)`] [`X::mutable_buffers_type`] [ The implementation calls this function to obtain a mutable buffer sequence of up to `n` bytes in size in which to place data corresponding to the body. The buffer returned must be at least one byte in size, and may be smaller than `n`. ] ] [ [`a.commit(n)`] [] [ The implementation calls this function to indicate to the writer that `n` bytes of data have been successfully placed into the buffer obtained through a prior call to `prepare`. The value of `n` will be less than or equal to the size of the buffer returned in the previous call to `prepare`. ] ] [ [`a.finish()`] [] [ This function is called after all the bytes corresponding to the body have been written to the buffers and committed. ] ] [ [`is_body_writer`] [`std::true_type`] [ An alias for `std::true_type` for `B`, otherwise an alias for `std::false_type`. ] ] ] [table Indirect Writer requirements [[expression] [type] [semantics, pre/post-conditions]] [ [`X::is_direct`] [`bool`] [ This static constant must be set to `false` to indicate this is an indirect writer. ] ] [ [`X a{m};`] [] [ `a` is constructible from `m`. The lifetime of `m` is guaranteed to end no earlier than after `a` is destroyed. The constructor will be called after all headers have been stored in `m`, and just before parsing bytes corresponding to the body for messages whose semantics indicate that a body is present with non-zero length. ] ] [ [`a.init(ec)`] [] [ This function is called once before any bytes corresponding to the body are presented to the writer, for messages whose body is determined by the end-of-file market on a stream, or for messages where the chunked Transfer-Encoding is specified. If `ec` is set before returning, parsing will stop and the error will be returned to the caller. ] ] [ [`a.init(v,ec)`] [] [ This function is called once before any bytes corresponding to the body are presented to the writer, for messages where the Content-Length is specified. The value of `v` will be set to the number of bytes indicated by the content length. If `ec` is set before returning, parsing will stop and the error will be returned to the caller. ] ] [ [`a.write(s,ec)`] [] [ The implementation calls this function with `s` containing bytes corresponding to the body, after removing any present chunked encoding transformation. If `ec` is set before returning, parsing will stop and the error will be returned to the caller. ] ] [ [`a.finish(ec)`] [] [ This function is called after all the bytes corresponding to the body have been written to the buffers and committed. If `ec` is set before returning, parsing will stop and the error will be returned to the caller. ] ] [ [`is_body_writer`] [`std::true_type`] [ An alias for `std::true_type` for `B`, otherwise an alias for `std::false_type`. ] ] ] [note Definitions for required [*Writer] member functions should be declared inline so the generated code can become part of the implementation. ] [endsect]