type_traits.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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_TYPE_TRAITS_HPP
  10. #define BOOST_BEAST_HTTP_TYPE_TRAITS_HPP
  11. #include <boost/beast/core/detail/config.hpp>
  12. #include <boost/beast/core/error.hpp>
  13. #include <boost/beast/core/string.hpp>
  14. #include <boost/beast/http/detail/type_traits.hpp>
  15. #include <boost/asio/buffer.hpp>
  16. #include <boost/optional.hpp>
  17. #include <type_traits>
  18. #include <utility>
  19. namespace boost {
  20. namespace beast {
  21. namespace http {
  22. template<bool, class, class>
  23. class message;
  24. /** Determine if a type meets the <em>Body</em> named requirements.
  25. This alias template is `std::true_type` if `T` meets
  26. the requirements, otherwise it is `std::false_type`.
  27. @tparam T The type to test.
  28. @par Example
  29. @code
  30. template<bool isRequest, class Body, class Fields>
  31. void check_body(message<isRequest, Body, Fields> const&)
  32. {
  33. static_assert(is_body<Body>::value,
  34. "Body type requirements not met");
  35. }
  36. @endcode
  37. */
  38. template<class T>
  39. #if BOOST_BEAST_DOXYGEN
  40. using is_body = __see_below__;
  41. #else
  42. using is_body = detail::has_value_type<T>;
  43. #endif
  44. /** Determine if a type has a nested <em>BodyWriter</em>.
  45. This alias template is `std::true_type` when:
  46. @li `T` has a nested type named `writer`
  47. @li `writer` meets the requirements of <em>BodyWriter</em>.
  48. @tparam T The body type to test.
  49. @par Example
  50. @code
  51. template<bool isRequest, class Body, class Fields>
  52. void check_can_serialize(message<isRequest, Body, Fields> const&)
  53. {
  54. static_assert(is_body_writer<Body>::value,
  55. "Cannot serialize Body, no reader");
  56. }
  57. @endcode
  58. */
  59. #if BOOST_BEAST_DOXYGEN
  60. template<class T>
  61. using is_body_writer = __see_below__;
  62. #else
  63. template<class T, class = void>
  64. struct is_body_writer : std::false_type {};
  65. template<class T>
  66. struct is_body_writer<T, beast::detail::void_t<
  67. typename T::writer,
  68. typename T::writer::const_buffers_type,
  69. decltype(
  70. std::declval<typename T::writer&>().init(std::declval<error_code&>()),
  71. std::declval<boost::optional<std::pair<
  72. typename T::writer::const_buffers_type, bool>>&>() =
  73. std::declval<typename T::writer>().get(std::declval<error_code&>())
  74. )>> : std::integral_constant<bool,
  75. net::is_const_buffer_sequence<
  76. typename T::writer::const_buffers_type>::value && (
  77. (std::is_constructible<typename T::writer,
  78. header<true, detail::fields_model>&,
  79. typename T::value_type&>::value &&
  80. std::is_constructible<typename T::writer,
  81. header<false, detail::fields_model>&,
  82. typename T::value_type&>::value)
  83. )
  84. > {};
  85. #endif
  86. /** Determine if a type has a nested <em>BodyWriter</em>.
  87. This alias template is `std::true_type` when:
  88. @li `T` has a nested type named `writer`
  89. @li `writer` meets the requirements of <em>BodyWriter</em>.
  90. @tparam T The body type to test.
  91. */
  92. #if BOOST_BEAST_DOXYGEN
  93. template<class T>
  94. using is_mutable_body_writer = __see_below__;
  95. #else
  96. template<class T, class = void>
  97. struct is_mutable_body_writer : std::false_type {};
  98. template<class T>
  99. struct is_mutable_body_writer<T, beast::detail::void_t<
  100. typename T::writer,
  101. typename T::writer::const_buffers_type,
  102. decltype(
  103. std::declval<typename T::writer&>().init(std::declval<error_code&>()),
  104. std::declval<boost::optional<std::pair<
  105. typename T::writer::const_buffers_type, bool>>&>() =
  106. std::declval<typename T::writer>().get(std::declval<error_code&>())
  107. )>> : std::integral_constant<bool,
  108. net::is_const_buffer_sequence<
  109. typename T::writer::const_buffers_type>::value && ((
  110. std::is_constructible<typename T::writer,
  111. header<true, detail::fields_model>&,
  112. typename T::value_type&>::value &&
  113. std::is_constructible<typename T::writer,
  114. header<false, detail::fields_model>&,
  115. typename T::value_type&>::value &&
  116. ! std::is_constructible<typename T::writer,
  117. header<true, detail::fields_model> const&,
  118. typename T::value_type const&>::value &&
  119. ! std::is_constructible<typename T::writer,
  120. header<false, detail::fields_model> const&,
  121. typename T::value_type const&>::value
  122. ))
  123. >{};
  124. #endif
  125. /** Determine if a type has a nested <em>BodyReader</em>.
  126. This alias template is `std::true_type` when:
  127. @li `T` has a nested type named `reader`
  128. @li `reader` meets the requirements of <em>BodyReader</em>.
  129. @tparam T The body type to test.
  130. @par Example
  131. @code
  132. template<bool isRequest, class Body, class Fields>
  133. void check_can_parse(message<isRequest, Body, Fields>&)
  134. {
  135. static_assert(is_body_reader<Body>::value,
  136. "Cannot parse Body, no reader");
  137. }
  138. @endcode
  139. */
  140. #if BOOST_BEAST_DOXYGEN
  141. template<class T>
  142. using is_body_reader = __see_below__;
  143. #else
  144. template<class T, class = void>
  145. struct is_body_reader : std::false_type {};
  146. template<class T>
  147. struct is_body_reader<T, beast::detail::void_t<decltype(
  148. std::declval<typename T::reader&>().init(
  149. boost::optional<std::uint64_t>(),
  150. std::declval<error_code&>()),
  151. std::declval<std::size_t&>() =
  152. std::declval<typename T::reader&>().put(
  153. std::declval<net::const_buffer>(),
  154. std::declval<error_code&>()),
  155. std::declval<typename T::reader&>().finish(
  156. std::declval<error_code&>())
  157. )>> : std::integral_constant<bool,
  158. (std::is_constructible<typename T::reader,
  159. header<true, detail::fields_model>&,
  160. typename T::value_type&>::value &&
  161. std::is_constructible<typename T::reader,
  162. header<false,detail::fields_model>&,
  163. typename T::value_type&>::value)
  164. >
  165. {
  166. };
  167. #endif
  168. /** Determine if a type meets the <em>Fields</em> named requirements.
  169. This alias template is `std::true_type` if `T` meets
  170. the requirements, otherwise it is `std::false_type`.
  171. @tparam T The type to test.
  172. @par Example
  173. Use with `static_assert`:
  174. @code
  175. template<bool isRequest, class Body, class Fields>
  176. void f(message<isRequest, Body, Fields> const&)
  177. {
  178. static_assert(is_fields<Fields>::value,
  179. "Fields type requirements not met");
  180. ...
  181. @endcode
  182. Use with `std::enable_if` (SFINAE):
  183. @code
  184. template<bool isRequest, class Body, class Fields>
  185. typename std::enable_if<is_fields<Fields>::value>::type
  186. f(message<isRequest, Body, Fields> const&);
  187. @endcode
  188. */
  189. #if BOOST_BEAST_DOXYGEN
  190. template<class T>
  191. using is_fields = __see_below__;
  192. #else
  193. template<class T>
  194. using is_fields = typename detail::is_fields_helper<T>::type;
  195. #endif
  196. } // http
  197. } // beast
  198. } // boost
  199. #endif