vector_body.hpp 4.5 KB

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