span_body.hpp 4.1 KB

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