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