span_body.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. #ifndef BOOST_BEAST_HTTP_SPAN_BODY_HPP
  10. #define BOOST_BEAST_HTTP_SPAN_BODY_HPP
  11. #include <boost/beast/http/span_body_fwd.hpp>
  12. #include <boost/beast/core/buffer_traits.hpp>
  13. #include <boost/beast/core/detail/config.hpp>
  14. #include <boost/beast/core/span.hpp>
  15. #include <boost/beast/http/error.hpp>
  16. #include <boost/beast/http/message.hpp>
  17. #include <boost/optional.hpp>
  18. namespace boost {
  19. namespace beast {
  20. namespace http {
  21. /** A <em>Body</em> using @ref span
  22. This body uses @ref span as a memory-based container for
  23. holding message payloads. The container represents a
  24. non-owning reference to a contiguous area of memory.
  25. Messages using this body type may be serialized and
  26. parsed.
  27. Unlike @ref buffer_body, only one buffer may be provided
  28. during a parse or serialize operation.
  29. */
  30. template<class T>
  31. struct span_body
  32. {
  33. private:
  34. static_assert(
  35. std::is_trivially_default_constructible<T>::value &&
  36. std::is_trivially_copyable<T>::value &&
  37. std::is_standard_layout<T>::value,
  38. "POD requirements not met");
  39. public:
  40. /** The type of container used for the body
  41. This determines the type of @ref message::body
  42. when this body type is used with a message container.
  43. */
  44. using value_type = span<T>;
  45. /** Returns the payload size of the body
  46. When this body is used with @ref message::prepare_payload,
  47. the Content-Length will be set to the payload size, and
  48. any chunked Transfer-Encoding will be removed.
  49. */
  50. static
  51. std::uint64_t
  52. size(value_type const& body)
  53. {
  54. return body.size();
  55. }
  56. /** The algorithm for parsing the body
  57. Meets the requirements of <em>BodyReader</em>.
  58. */
  59. #if BOOST_BEAST_DOXYGEN
  60. using reader = __implementation_defined__;
  61. #else
  62. class reader
  63. {
  64. value_type& body_;
  65. public:
  66. template<bool isRequest, class Fields>
  67. explicit
  68. reader(header<isRequest, Fields>&, value_type& b)
  69. : body_(b)
  70. {
  71. }
  72. void
  73. init(boost::optional<
  74. std::uint64_t> const& length, error_code& ec)
  75. {
  76. if(length && *length > body_.size())
  77. {
  78. BOOST_BEAST_ASSIGN_EC(ec, error::buffer_overflow);
  79. return;
  80. }
  81. ec = {};
  82. }
  83. template<class ConstBufferSequence>
  84. std::size_t
  85. put(ConstBufferSequence const& buffers,
  86. error_code& ec)
  87. {
  88. auto const n = buffer_bytes(buffers);
  89. auto const len = body_.size();
  90. if(n > len)
  91. {
  92. BOOST_BEAST_ASSIGN_EC(ec, error::buffer_overflow);
  93. return 0;
  94. }
  95. ec = {};
  96. net::buffer_copy(net::buffer(
  97. body_.data(), n), buffers);
  98. body_ = value_type{
  99. body_.data() + n, body_.size() - n};
  100. return n;
  101. }
  102. void
  103. finish(error_code& ec)
  104. {
  105. ec = {};
  106. }
  107. };
  108. #endif
  109. /** The algorithm for serializing the body
  110. Meets the requirements of <em>BodyWriter</em>.
  111. */
  112. #if BOOST_BEAST_DOXYGEN
  113. using writer = __implementation_defined__;
  114. #else
  115. class writer
  116. {
  117. value_type const& body_;
  118. public:
  119. using const_buffers_type =
  120. net::const_buffer;
  121. template<bool isRequest, class Fields>
  122. explicit
  123. writer(header<isRequest, Fields> const&, value_type const& b)
  124. : body_(b)
  125. {
  126. }
  127. void
  128. init(error_code& ec)
  129. {
  130. ec = {};
  131. }
  132. boost::optional<std::pair<const_buffers_type, bool>>
  133. get(error_code& ec)
  134. {
  135. ec = {};
  136. return {{
  137. { body_.data(),
  138. body_.size() * sizeof(typename
  139. value_type::value_type)},
  140. false}};
  141. }
  142. };
  143. #endif
  144. };
  145. } // http
  146. } // beast
  147. } // boost
  148. #endif