• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 #ifndef BOOST_BEAST_HTTP_SPAN_BODY_HPP
11 #define BOOST_BEAST_HTTP_SPAN_BODY_HPP
12 
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/buffer_traits.hpp>
15 #include <boost/beast/core/span.hpp>
16 #include <boost/beast/http/error.hpp>
17 #include <boost/beast/http/message.hpp>
18 #include <boost/optional.hpp>
19 
20 namespace boost {
21 namespace beast {
22 namespace http {
23 
24 /** A <em>Body</em> using @ref span
25 
26     This body uses @ref span as a memory-based container for
27     holding message payloads. The container represents a
28     non-owning reference to a contiguous area of memory.
29     Messages using this body type may be serialized and
30     parsed.
31 
32     Unlike @ref buffer_body, only one buffer may be provided
33     during a parse or serialize operation.
34 */
35 template<class T>
36 struct span_body
37 {
38 private:
39     static_assert(
40         std::is_trivial<T>::value &&
41         std::is_standard_layout<T>::value,
42             "POD requirements not met");
43 
44 public:
45     /** The type of container used for the body
46 
47         This determines the type of @ref message::body
48         when this body type is used with a message container.
49     */
50     using value_type = span<T>;
51 
52     /** Returns the payload size of the body
53 
54         When this body is used with @ref message::prepare_payload,
55         the Content-Length will be set to the payload size, and
56         any chunked Transfer-Encoding will be removed.
57     */
58     static
59     std::uint64_t
sizeboost::beast::http::span_body60     size(value_type const& body)
61     {
62         return body.size();
63     }
64 
65     /** The algorithm for parsing the body
66 
67         Meets the requirements of <em>BodyReader</em>.
68     */
69 #if BOOST_BEAST_DOXYGEN
70     using reader = __implementation_defined__;
71 #else
72     class reader
73     {
74         value_type& body_;
75 
76     public:
77         template<bool isRequest, class Fields>
78         explicit
reader(header<isRequest,Fields> &,value_type & b)79         reader(header<isRequest, Fields>&, value_type& b)
80             : body_(b)
81         {
82         }
83 
84         void
init(boost::optional<std::uint64_t> const & length,error_code & ec)85         init(boost::optional<
86             std::uint64_t> const& length, error_code& ec)
87         {
88             if(length && *length > body_.size())
89             {
90                 ec = error::buffer_overflow;
91                 return;
92             }
93             ec = {};
94         }
95 
96         template<class ConstBufferSequence>
97         std::size_t
put(ConstBufferSequence const & buffers,error_code & ec)98         put(ConstBufferSequence const& buffers,
99             error_code& ec)
100         {
101             auto const n = buffer_bytes(buffers);
102             auto const len = body_.size();
103             if(n > len)
104             {
105                 ec = error::buffer_overflow;
106                 return 0;
107             }
108             ec = {};
109             net::buffer_copy(net::buffer(
110                 body_.data(), n), buffers);
111             body_ = value_type{
112                 body_.data() + n, body_.size() - n};
113             return n;
114         }
115 
116         void
finish(error_code & ec)117         finish(error_code& ec)
118         {
119             ec = {};
120         }
121     };
122 #endif
123 
124     /** The algorithm for serializing the body
125 
126         Meets the requirements of <em>BodyWriter</em>.
127     */
128 #if BOOST_BEAST_DOXYGEN
129     using writer = __implementation_defined__;
130 #else
131     class writer
132     {
133         value_type const& body_;
134 
135     public:
136         using const_buffers_type =
137             net::const_buffer;
138 
139         template<bool isRequest, class Fields>
140         explicit
writer(header<isRequest,Fields> const &,value_type const & b)141         writer(header<isRequest, Fields> const&, value_type const& b)
142             : body_(b)
143         {
144         }
145 
146         void
init(error_code & ec)147         init(error_code& ec)
148         {
149             ec = {};
150         }
151 
152         boost::optional<std::pair<const_buffers_type, bool>>
get(error_code & ec)153         get(error_code& ec)
154         {
155             ec = {};
156             return {{
157                 { body_.data(),
158                   body_.size() * sizeof(typename
159                     value_type::value_type)},
160                 false}};
161         }
162     };
163 #endif
164 };
165 
166 } // http
167 } // beast
168 } // boost
169 
170 #endif
171