// // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BEAST_HTTP_CONCEPTS_HPP #define BEAST_HTTP_CONCEPTS_HPP #include #include #include #include #include #include #include #include namespace beast { namespace http { namespace detail { struct write_function { template void operator()(ConstBufferSequence const&); }; template> struct has_value_type : std::false_type {}; template struct has_value_type > : std::true_type {}; template> struct has_content_length : std::false_type {}; template struct has_content_length().content_length() )> > : std::true_type { static_assert(std::is_convertible< decltype(std::declval().content_length()), std::uint64_t>::value, "Writer::content_length requirements not met"); }; template class is_Writer { template().init(std::declval()), std::true_type{})> static R check1(int); template static std::false_type check1(...); using type1 = decltype(check1(0)); // VFALCO This is unfortunate, we have to provide the template // argument type because this is not a deduced context? // template().template write( std::declval(), std::declval())) , bool>> static R check2(int); template static std::false_type check2(...); using type2 = decltype(check2(0)); public: static_assert(std::is_same< typename M::body_type::writer, T>::value, "Mismatched writer and message"); using type = std::integral_constant::value && type1::value && type2::value >; }; } // detail /// Determine if `T` meets the requirements of @b Body. template #if BEAST_DOXYGEN struct is_Body : std::integral_constant{}; #else using is_Body = detail::has_value_type; #endif /** Determine if a @b Body has a nested type `reader`. @tparam T The type to check, which must meet the requirements of @b Body. */ #if BEAST_DOXYGEN template struct has_reader : std::integral_constant{}; #else template> struct has_reader : std::false_type {}; template struct has_reader > : std::true_type {}; #endif /** Determine if a @b Body has a nested type `writer`. @tparam T The type to check, which must meet the requirements of @b Body. */ #if BEAST_DOXYGEN template struct has_writer : std::integral_constant{}; #else template> struct has_writer : std::false_type {}; template struct has_writer > : std::true_type {}; #endif /** Determine if `T` meets the requirements of @b Reader for `M`. @tparam T The type to test. @tparam M The message type to test with, which must be of type `message`. */ #if BEAST_DOXYGEN template struct is_Reader : std::integral_constant {}; #else template> struct is_Reader : std::true_type {}; template struct is_Reader(), std::declval().init( std::declval>()), std::declval().prepare( std::declval()), std::declval().commit( std::declval()), std::declval().finish() )> > : std::integral_constant::value && std::is_convertible().prepare( std::declval())), typename T::mutable_buffers_type >::value> { static_assert(std::is_same< typename M::body_type::reader, T>::value, "Mismatched reader and message"); }; #endif /** Determine if `T` meets the requirements of @b Writer for `M`. @tparam T The type to test. @tparam M The message type to test with, which must be of type `message`. */ template #if BEAST_DOXYGEN struct is_Writer : std::integral_constant {}; #else using is_Writer = typename detail::is_Writer::type; #endif } // http } // beast #endif