span_body.hpp 4.0 KB

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