mirror of
https://github.com/boostorg/beast.git
synced 2025-08-01 05:44:38 +02:00
@@ -2,6 +2,7 @@ Version 48
|
||||
|
||||
* Make buffer_prefix_view public
|
||||
* Remove detail::sync_ostream
|
||||
* Tidy up core type traits
|
||||
|
||||
API Changes:
|
||||
|
||||
|
@@ -16,6 +16,31 @@
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
|
||||
// A few workarounds to keep things working
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
// for has_get_io_service
|
||||
class io_service;
|
||||
|
||||
// for is_dynamic_buffer
|
||||
template<class Allocator>
|
||||
class basic_streambuf;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// for is_buffer_sequence
|
||||
template<class Buffer, class Buffers>
|
||||
class consuming_buffers;
|
||||
|
||||
} // detail
|
||||
|
||||
} // asio
|
||||
} // boost
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
@@ -32,6 +57,11 @@ struct make_void
|
||||
template<class... Ts>
|
||||
using void_t = typename make_void<Ts...>::type;
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
void
|
||||
accept_rv(T){}
|
||||
|
||||
template<class... Ts>
|
||||
inline
|
||||
void
|
||||
@@ -109,8 +139,7 @@ is_invocable_test(C&& c, long, A&& ...a);
|
||||
*/
|
||||
/** @{ */
|
||||
template<class C, class F>
|
||||
struct is_invocable
|
||||
: std::false_type
|
||||
struct is_invocable : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
@@ -145,72 +174,57 @@ using ConstBufferSequence =
|
||||
using MutableBufferSequence =
|
||||
BufferSequence<boost::asio::mutable_buffer>;
|
||||
|
||||
template<class T, class BufferType>
|
||||
class is_buffer_sequence
|
||||
template<class T, class B, class = void>
|
||||
struct is_buffer_sequence : std::false_type {};
|
||||
|
||||
template<class T, class B>
|
||||
struct is_buffer_sequence<T, B, void_t<decltype(
|
||||
std::declval<typename T::value_type>(),
|
||||
std::declval<typename T::const_iterator&>() =
|
||||
std::declval<T const&>().begin(),
|
||||
std::declval<typename T::const_iterator&>() =
|
||||
std::declval<T const&>().end(),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
std::is_convertible<typename T::value_type, B>::value &&
|
||||
#if 0
|
||||
std::is_base_of<std::bidirectional_iterator_tag,
|
||||
typename std::iterator_traits<
|
||||
typename T::const_iterator>::iterator_category>::value
|
||||
#else
|
||||
// workaround:
|
||||
// boost::asio::detail::consuming_buffers::const_iterator
|
||||
// is not bidirectional
|
||||
std::is_base_of<std::forward_iterator_tag,
|
||||
typename std::iterator_traits<
|
||||
typename T::const_iterator>::iterator_category>::value
|
||||
#endif
|
||||
>
|
||||
{
|
||||
template<class U, class R = std::is_convertible<
|
||||
typename U::value_type, BufferType> >
|
||||
static R check1(int);
|
||||
template<class>
|
||||
static std::false_type check1(...);
|
||||
using type1 = decltype(check1<T>(0));
|
||||
|
||||
template<class U, class R = std::is_base_of<
|
||||
#if 0
|
||||
std::bidirectional_iterator_tag,
|
||||
typename std::iterator_traits<
|
||||
typename U::const_iterator>::iterator_category>>
|
||||
#else
|
||||
// workaround:
|
||||
// boost::asio::detail::consuming_buffers::const_iterator
|
||||
// is not bidirectional
|
||||
std::forward_iterator_tag,
|
||||
typename std::iterator_traits<
|
||||
typename U::const_iterator>::iterator_category>>
|
||||
#endif
|
||||
static R check2(int);
|
||||
template<class>
|
||||
static std::false_type check2(...);
|
||||
using type2 = decltype(check2<T>(0));
|
||||
|
||||
template<class U, class R = typename
|
||||
std::is_convertible<decltype(
|
||||
std::declval<U>().begin()),
|
||||
typename U::const_iterator>::type>
|
||||
static R check3(int);
|
||||
template<class>
|
||||
static std::false_type check3(...);
|
||||
using type3 = decltype(check3<T>(0));
|
||||
|
||||
template<class U, class R = typename std::is_convertible<decltype(
|
||||
std::declval<U>().end()),
|
||||
typename U::const_iterator>::type>
|
||||
static R check4(int);
|
||||
template<class>
|
||||
static std::false_type check4(...);
|
||||
using type4 = decltype(check4<T>(0));
|
||||
|
||||
public:
|
||||
using type = std::integral_constant<bool,
|
||||
std::is_copy_constructible<T>::value &&
|
||||
std::is_destructible<T>::value &&
|
||||
type1::value && type2::value &&
|
||||
type3::value && type4::value>;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#if 0
|
||||
// workaround:
|
||||
// boost::asio::detail::consuming_buffers::const_iterator
|
||||
// is not bidirectional
|
||||
template<class Buffer, class Buffers, class B>
|
||||
struct is_buffer_sequence<
|
||||
boost::asio::detail::consuming_buffers<Buffer, Buffers>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class B1, class... Bn>
|
||||
struct is_all_const_buffer_sequence
|
||||
: std::integral_constant<bool,
|
||||
is_buffer_sequence<B1, boost::asio::const_buffer>::type::value &&
|
||||
is_buffer_sequence<B1, boost::asio::const_buffer>::value &&
|
||||
is_all_const_buffer_sequence<Bn...>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template<class B1>
|
||||
struct is_all_const_buffer_sequence<B1>
|
||||
: is_buffer_sequence<B1, boost::asio::const_buffer>::type
|
||||
: is_buffer_sequence<B1, boost::asio::const_buffer>
|
||||
{
|
||||
};
|
||||
|
||||
@@ -345,14 +359,4 @@ public:
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
// for is_dynamic_buffer
|
||||
template<class Allocator>
|
||||
class basic_streambuf;
|
||||
|
||||
} // asio
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
|
@@ -21,31 +21,86 @@ namespace beast {
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// Determine if `T` meets the requirements of @b ConstBufferSequence.
|
||||
/** Determine if `T` meets the requirements of @b ConstBufferSequence.
|
||||
|
||||
@par Example
|
||||
Use with `static_assert`:
|
||||
@code
|
||||
template<class ConstBufferSequence>
|
||||
void f(ConstBufferSequence const& buffers)
|
||||
{
|
||||
static_assert(is_const_buffer_sequence<ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
Use with `std::enable_if`
|
||||
@code
|
||||
template<class ConstBufferSequence>
|
||||
typename std::enable_if<is_const_buffer_sequence<ConstBufferSequence>::value>::type
|
||||
f(ConstBufferSequence const& buffers);
|
||||
@endcode
|
||||
*/
|
||||
template<class T>
|
||||
#if BEAST_DOXYGEN
|
||||
struct is_const_buffer_sequence : std::integral_constant<bool, ...>
|
||||
#else
|
||||
struct is_const_buffer_sequence :
|
||||
detail::is_buffer_sequence<T,
|
||||
boost::asio::const_buffer>::type
|
||||
detail::is_buffer_sequence<T, boost::asio::const_buffer>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
/// Determine if `T` meets the requirements of @b MutableBufferSequence.
|
||||
/** Determine if `T` meets the requirements of @b MutableBufferSequence.
|
||||
|
||||
@par Example
|
||||
Use with `static_assert`:
|
||||
@code
|
||||
template<class MutableBufferSequence>
|
||||
void f(MutableBufferSequence const& buffers)
|
||||
{
|
||||
static_assert(is_const_buffer_sequence<MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
Use with `std::enable_if`
|
||||
@code
|
||||
template<class MutableBufferSequence>
|
||||
typename std::enable_if<is_mutable_buffer_sequence<MutableBufferSequence>::value>::type
|
||||
f(MutableBufferSequence const& buffers);
|
||||
@endcode
|
||||
*/
|
||||
template<class T>
|
||||
#if BEAST_DOXYGEN
|
||||
struct is_mutable_buffer_sequence : std::integral_constant<bool, ...>
|
||||
#else
|
||||
struct is_mutable_buffer_sequence :
|
||||
detail::is_buffer_sequence<T,
|
||||
boost::asio::mutable_buffer>::type
|
||||
detail::is_buffer_sequence<T, boost::asio::mutable_buffer>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
/// Determine if `T` meets the requirements of @b DynamicBuffer.
|
||||
/** Determine if `T` meets the requirements of @b DynamicBuffer.
|
||||
|
||||
@par Example
|
||||
Use with `static_assert`:
|
||||
@code
|
||||
template<class DynamicBuffer>
|
||||
void f(DynamicBuffer& buffer)
|
||||
{
|
||||
static_assert(is_dynamic_buffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
Use with `std::enable_if`
|
||||
@code
|
||||
template<class DynamicBuffer>
|
||||
typename std::enable_if<is_dynamic_buffer<DynamicBuffer>::value>::type
|
||||
f(DynamicBuffer const& buffer);
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct is_dynamic_buffer : std::integral_constant<bool, ...> {};
|
||||
@@ -54,8 +109,7 @@ template<class T, class = void>
|
||||
struct is_dynamic_buffer : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_dynamic_buffer<T, beast::detail::void_t<
|
||||
decltype(
|
||||
struct is_dynamic_buffer<T, detail::void_t<decltype(
|
||||
std::declval<std::size_t&>() =
|
||||
std::declval<T const&>().size(),
|
||||
std::declval<std::size_t&>() =
|
||||
@@ -64,7 +118,7 @@ struct is_dynamic_buffer<T, beast::detail::void_t<
|
||||
std::declval<T const&>().capacity(),
|
||||
std::declval<T&>().commit(std::declval<std::size_t>()),
|
||||
std::declval<T&>().consume(std::declval<std::size_t>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
(void)0)> > : std::integral_constant<bool,
|
||||
is_const_buffer_sequence<
|
||||
typename T::const_buffers_type>::value &&
|
||||
is_mutable_buffer_sequence<
|
||||
@@ -93,32 +147,77 @@ struct is_dynamic_buffer<
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// Determine if `T` meets the requirements of @b CompletionHandler.
|
||||
/** Determine if `T` meets the requirements of @b CompletionHandler.
|
||||
|
||||
This metafunction will be equivalent to `std::true_type` if `T`
|
||||
meets the requirements for a completion handler callable with
|
||||
the given signature.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
struct handler
|
||||
{
|
||||
void operator()(error_code&);
|
||||
};
|
||||
|
||||
static_assert(is_completion_handler<handler, void(error_code&)>::value,
|
||||
"Not a completion handler");
|
||||
@endcode
|
||||
*/
|
||||
template<class T, class Signature>
|
||||
#if BEAST_DOXYGEN
|
||||
using is_completion_handler = std::integral_constant<bool, ...>;
|
||||
#else
|
||||
using is_completion_handler = std::integral_constant<bool,
|
||||
std::is_copy_constructible<typename std::decay<T>::type>::value &&
|
||||
detail::is_invocable<T, Signature>::value>;
|
||||
detail::is_invocable<T, Signature>::value>;
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Stream concepts
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// Determine if `T` has the `get_io_service` member.
|
||||
template<class T>
|
||||
/** Determine if `T` has the `get_io_service` member.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
struct stream
|
||||
{
|
||||
boost::asio::io_service& get_io_service();
|
||||
};
|
||||
|
||||
static_assert(has_get_io_service<stream>::value,
|
||||
"Missing get_io_service member");
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct has_get_io_service : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using has_get_io_service = typename detail::has_get_io_service<T>::type;
|
||||
template<class T, class = void>
|
||||
struct has_get_io_service : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct has_get_io_service<T, beast::detail::void_t<decltype(
|
||||
detail::accept_rv<boost::asio::io_service&>(
|
||||
std::declval<T&>().get_io_service()),
|
||||
(void)0)>> : std::true_type {};
|
||||
#endif
|
||||
|
||||
/// Returns `T::lowest_layer_type` if it exists, else `T`
|
||||
/** Returns `T::lowest_layer_type` if it exists, else `T`
|
||||
|
||||
@par Example
|
||||
@code
|
||||
template<class Stream>
|
||||
struct stream_wrapper
|
||||
{
|
||||
using next_layer_type = typename std::remove_reference<Stream>::type;
|
||||
using lowest_layer_type = typename get_lowest_layer<stream_type>::type;
|
||||
};
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct get_lowest_layer;
|
||||
@@ -137,52 +236,213 @@ struct get_lowest_layer<T, detail::void_t<
|
||||
};
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b AsyncReadStream.
|
||||
template<class T>
|
||||
/** Determine if `T` meets the requirements of @b AsyncReadStream.
|
||||
|
||||
@par Example
|
||||
Use with `static_assert`:
|
||||
@code
|
||||
template<class AsyncReadStream>
|
||||
void f(AsyncReadStream& stream)
|
||||
{
|
||||
static_assert(is_async_read_stream<AsyncReadStream>::value,
|
||||
"AsyncReadStream requirements not met");
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
Use with `std::enable_if`
|
||||
@code
|
||||
template<class AsyncReadStream>
|
||||
typename std::enable_if<is_async_read_stream<AsyncReadStream>::value>::type
|
||||
f(AsyncReadStream& stream);
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct is_async_read_stream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using is_async_read_stream = typename detail::is_async_read_stream<T>::type;
|
||||
template<class T, class = void>
|
||||
struct is_async_read_stream : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_async_read_stream<T, detail::void_t<decltype(
|
||||
std::declval<T>().async_read_some(
|
||||
std::declval<detail::MutableBufferSequence>(),
|
||||
std::declval<detail::ReadHandler>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
has_get_io_service<T>::value
|
||||
> {};
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b AsyncWriteStream.
|
||||
template<class T>
|
||||
/** Determine if `T` meets the requirements of @b AsyncWriteStream.
|
||||
|
||||
@par Example
|
||||
Use with `static_assert`:
|
||||
@code
|
||||
template<class AsyncWriteStream>
|
||||
void f(AsyncWriteStream& stream)
|
||||
{
|
||||
static_assert(is_async_write_stream<AsyncWriteStream>::value,
|
||||
"AsyncWriteStream requirements not met");
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
Use with `std::enable_if`
|
||||
@code
|
||||
template<class AsyncWriteStream>
|
||||
typename std::enable_if<is_async_write_stream<AsyncWriteStream>::value>::type
|
||||
f(AsyncWriteStream& stream);
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct is_async_write_stream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using is_async_write_stream = typename detail::is_async_write_stream<T>::type;
|
||||
template<class T, class = void>
|
||||
struct is_async_write_stream : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_async_write_stream<T, detail::void_t<decltype(
|
||||
std::declval<T>().async_write_some(
|
||||
std::declval<detail::ConstBufferSequence>(),
|
||||
std::declval<detail::WriteHandler>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
has_get_io_service<T>::value
|
||||
> {};
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b SyncReadStream.
|
||||
template<class T>
|
||||
/** Determine if `T` meets the requirements of @b SyncReadStream.
|
||||
|
||||
@par Example
|
||||
Use with `static_assert`:
|
||||
@code
|
||||
template<class SyncReadStream>
|
||||
void f(SyncReadStream& stream)
|
||||
{
|
||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
Use with `std::enable_if`
|
||||
@code
|
||||
template<class SyncReadStream>
|
||||
typename std::enable_if<is_sync_read_stream<SyncReadStream>::value>::type
|
||||
f(SyncReadStream& stream);
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct is_sync_read_stream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using is_sync_read_stream = typename detail::is_sync_read_stream<T>::type;
|
||||
template<class T, class = void>
|
||||
struct is_sync_read_stream : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_sync_read_stream<T, detail::void_t<decltype(
|
||||
std::declval<std::size_t&>() = std::declval<T>().read_some(
|
||||
std::declval<detail::MutableBufferSequence>()),
|
||||
std::declval<std::size_t&>() = std::declval<T>().read_some(
|
||||
std::declval<detail::MutableBufferSequence>(),
|
||||
std::declval<boost::system::error_code&>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
has_get_io_service<T>::value
|
||||
> {};
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b SyncWriterStream.
|
||||
template<class T>
|
||||
/** Determine if `T` meets the requirements of @b SyncWriterStream.
|
||||
|
||||
@par Example
|
||||
Use with `static_assert`:
|
||||
@code
|
||||
template<class SyncReadStream>
|
||||
void f(SyncReadStream& stream)
|
||||
{
|
||||
static_assert(is_sync_read_stream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
Use with `std::enable_if`
|
||||
@code
|
||||
template<class SyncReadStream>
|
||||
typename std::enable_if<is_sync_read_stream<SyncReadStream>::value>::type
|
||||
f(SyncReadStream& stream);
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct is_sync_write_stream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using is_sync_write_stream = typename detail::is_sync_write_stream<T>::type;
|
||||
template<class T, class = void>
|
||||
struct is_sync_write_stream : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_sync_write_stream<T, detail::void_t<decltype(
|
||||
std::declval<std::size_t&>() = std::declval<T&>().write_some(
|
||||
std::declval<detail::ConstBufferSequence>()),
|
||||
std::declval<std::size_t&>() = std::declval<T&>().write_some(
|
||||
std::declval<detail::ConstBufferSequence>(),
|
||||
std::declval<boost::system::error_code&>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
has_get_io_service<T>::value
|
||||
> {};
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b AsyncStream.
|
||||
template<class T>
|
||||
/** Determine if `T` meets the requirements of @b AsyncStream.
|
||||
|
||||
@par Example
|
||||
Use with `static_assert`:
|
||||
@code
|
||||
template<class AsyncStream>
|
||||
void f(AsyncStream& stream)
|
||||
{
|
||||
static_assert(is_async_stream<AsyncStream>::value,
|
||||
"AsyncStream requirements not met");
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
Use with `std::enable_if`
|
||||
@code
|
||||
template<class AsyncStream>
|
||||
typename std::enable_if<is_async_stream<AsyncStream>::value>::type
|
||||
f(AsyncStream& stream);
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct is_async_stream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
template<class T>
|
||||
using is_async_stream = std::integral_constant<bool,
|
||||
is_async_read_stream<T>::value && is_async_write_stream<T>::value>;
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b SyncStream.
|
||||
template<class T>
|
||||
/** Determine if `T` meets the requirements of @b SyncStream.
|
||||
|
||||
|
||||
@par Example
|
||||
Use with `static_assert`:
|
||||
@code
|
||||
template<class SyncStream>
|
||||
void f(SyncStream& stream)
|
||||
{
|
||||
static_assert(is_sync_stream<SyncStream>::value,
|
||||
"SyncStream requirements not met");
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
Use with `std::enable_if`
|
||||
@code
|
||||
template<class SyncStream>
|
||||
typename std::enable_if<is_sync_stream<SyncStream>::value>::type
|
||||
f(SyncStream& stream);
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
struct is_sync_stream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
template<class T>
|
||||
using is_sync_stream = std::integral_constant<bool,
|
||||
is_sync_read_stream<T>::value && is_sync_write_stream<T>::value>;
|
||||
#endif
|
||||
|
@@ -16,6 +16,9 @@ namespace http {
|
||||
template<bool isRequest, class Fields>
|
||||
struct header;
|
||||
|
||||
template<bool, class, class>
|
||||
struct message;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
@@ -32,6 +35,35 @@ public:
|
||||
template<class T>
|
||||
using is_header = typename is_header_impl<T>::type;
|
||||
|
||||
struct fields_model
|
||||
{
|
||||
string_view method() const;
|
||||
string_view reason() const;
|
||||
string_view target() const;
|
||||
};
|
||||
|
||||
template<class T, class = beast::detail::void_t<>>
|
||||
struct has_value_type : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct has_value_type<T, beast::detail::void_t<
|
||||
typename T::value_type
|
||||
> > : std::true_type {};
|
||||
|
||||
template<class T, class = beast::detail::void_t<>>
|
||||
struct has_content_length : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct has_content_length<T, beast::detail::void_t<decltype(
|
||||
std::declval<T>().content_length()
|
||||
)> > : std::true_type
|
||||
{
|
||||
static_assert(std::is_convertible<
|
||||
decltype(std::declval<T>().content_length()),
|
||||
std::uint64_t>::value,
|
||||
"Writer::content_length requirements not met");
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include <beast/core/error.hpp>
|
||||
#include <beast/core/string_view.hpp>
|
||||
#include <beast/core/type_traits.hpp>
|
||||
#include <beast/http/detail/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <type_traits>
|
||||
@@ -20,43 +21,23 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
template<bool, class, class>
|
||||
struct message;
|
||||
/** Determine if `T` meets the requirements of @b Body.
|
||||
|
||||
namespace detail {
|
||||
This metafunction is equivalent to `std::true_type`
|
||||
if `T` has a nested type named `value_type`.
|
||||
|
||||
struct fields_model
|
||||
{
|
||||
string_view method() const;
|
||||
string_view reason() const;
|
||||
string_view target() const;
|
||||
};
|
||||
@tparam T The body type to test.
|
||||
|
||||
template<class T, class = beast::detail::void_t<>>
|
||||
struct has_value_type : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct has_value_type<T, beast::detail::void_t<
|
||||
typename T::value_type
|
||||
> > : std::true_type {};
|
||||
|
||||
template<class T, class = beast::detail::void_t<>>
|
||||
struct has_content_length : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct has_content_length<T, beast::detail::void_t<decltype(
|
||||
std::declval<T>().content_length()
|
||||
)> > : std::true_type
|
||||
{
|
||||
static_assert(std::is_convertible<
|
||||
decltype(std::declval<T>().content_length()),
|
||||
std::uint64_t>::value,
|
||||
"Writer::content_length requirements not met");
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
/// Determine if `T` meets the requirements of @b Body.
|
||||
@par Example
|
||||
@code
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void check_body(message<isRequest, Body, Fields> const&)
|
||||
{
|
||||
static_assert(is_body<Body>::value,
|
||||
"Body requirements not met");
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
template<class T>
|
||||
#if BEAST_DOXYGEN
|
||||
struct is_body : std::integral_constant<bool, ...>{};
|
||||
@@ -68,11 +49,20 @@ using is_body = detail::has_value_type<T>;
|
||||
|
||||
This metafunction is equivalent to `std::true_type` if:
|
||||
|
||||
@li @b T has a nested type named `reader`
|
||||
@li `T` has a nested type named `reader`
|
||||
|
||||
@li The nested type meets the requirements of @b BodyReader.
|
||||
|
||||
@tparam T The body type to test.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void check_can_serialize(message<isRequest, Body, Fields> const&)
|
||||
{
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"Cannot serialize Body, no reader");
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
@@ -95,20 +85,27 @@ struct is_body_reader<T, beast::detail::void_t<
|
||||
typename T::reader::const_buffers_type>::value &&
|
||||
std::is_constructible<typename T::reader,
|
||||
message<true, T, detail::fields_model> const& >::value
|
||||
>
|
||||
{
|
||||
};
|
||||
> {};
|
||||
#endif
|
||||
|
||||
/** Determine if a @b Body type has a writer.
|
||||
|
||||
This metafunction is equivalent to `std::true_type` if:
|
||||
|
||||
@li @b T has a nested type named `writer`
|
||||
@li `T` has a nested type named `writer`
|
||||
|
||||
@li The nested type meets the requirements of @b BodyWriter.
|
||||
|
||||
@tparam T The body type to test.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void check_can_parse(message<isRequest, Body, Fields>&)
|
||||
{
|
||||
static_assert(is_body_writer<Body>::value,
|
||||
"Cannot parse Body, no writer");
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
template<class T>
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <boost/asio/detail/consuming_buffers.hpp>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -125,10 +126,16 @@ BOOST_STATIC_ASSERT(! is_completion_handler<H, void(void)>::value);
|
||||
// stream concepts
|
||||
//
|
||||
|
||||
//namespace {
|
||||
namespace {
|
||||
|
||||
using stream_type = boost::asio::ip::tcp::socket;
|
||||
|
||||
struct not_a_stream
|
||||
{
|
||||
void
|
||||
get_io_service();
|
||||
};
|
||||
|
||||
BOOST_STATIC_ASSERT(has_get_io_service<stream_type>::value);
|
||||
BOOST_STATIC_ASSERT(is_async_read_stream<stream_type>::value);
|
||||
BOOST_STATIC_ASSERT(is_async_write_stream<stream_type>::value);
|
||||
@@ -137,12 +144,12 @@ BOOST_STATIC_ASSERT(is_sync_read_stream<stream_type>::value);
|
||||
BOOST_STATIC_ASSERT(is_sync_write_stream<stream_type>::value);
|
||||
BOOST_STATIC_ASSERT(is_sync_stream<stream_type>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(! has_get_io_service<int>::value);
|
||||
BOOST_STATIC_ASSERT(! is_async_read_stream<int>::value);
|
||||
BOOST_STATIC_ASSERT(! is_async_write_stream<int>::value);
|
||||
BOOST_STATIC_ASSERT(! is_sync_read_stream<int>::value);
|
||||
BOOST_STATIC_ASSERT(! is_sync_write_stream<int>::value);
|
||||
BOOST_STATIC_ASSERT(! has_get_io_service<not_a_stream>::value);
|
||||
BOOST_STATIC_ASSERT(! is_async_read_stream<not_a_stream>::value);
|
||||
BOOST_STATIC_ASSERT(! is_async_write_stream<not_a_stream>::value);
|
||||
BOOST_STATIC_ASSERT(! is_sync_read_stream<not_a_stream>::value);
|
||||
BOOST_STATIC_ASSERT(! is_sync_write_stream<not_a_stream>::value);
|
||||
|
||||
//} // (anonymous)
|
||||
} // (anonymous)
|
||||
|
||||
} // beast
|
||||
|
Reference in New Issue
Block a user