vector_body.hpp 4.1 KB

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