Revision control
++ // Copyright (C) 2020 Mikhail Svetkin <mikhail.svetkin@gmail.com>
++ // Copyright (C) 2019 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #ifndef QHTTPSERVERROUTERVIEWTRAITS_H
++ #define QHTTPSERVERROUTERVIEWTRAITS_H
++
++ #include <QtHttpServer/qhttpserverviewtraits_impl.h>
++
++ QT_BEGIN_NAMESPACE
++
++ class QHttpServerRequest;
++ class QHttpServerResponder;
++
++ namespace QtPrivate {
++
++ template<typename ViewHandler, bool DisableStaticAssert>
++ struct RouterViewTraitsHelper : ViewTraits<ViewHandler, DisableStaticAssert> {
++ using VTraits = ViewTraits<ViewHandler, DisableStaticAssert>;
++ using FunctionTraits = typename VTraits::FTraits;
++
++ template<int I>
++ struct ArgumentChecker : FunctionTraits::template Arg<I> {
++ using IsRequestCLvalue = typename VTraits::template Special<I, const QHttpServerRequest &>;
++ using IsRequestValue = typename VTraits::template Special<I, QHttpServerRequest>;
++ using IsRequest = CheckAny<IsRequestCLvalue, IsRequestValue>;
++ static_assert(IsRequest::StaticAssert,
++ "ViewHandler arguments error: "
++ "QHttpServerRequest can only be passed by value or as a const Lvalue");
++
++ using IsResponderLvalue = typename VTraits::template Special<I, QHttpServerResponder &>;
++ using IsResponderRvalue = typename VTraits::template Special<I, QHttpServerResponder &&>;
++ using IsResponder = CheckAny<IsResponderLvalue, IsResponderRvalue>;
++ static_assert(IsResponder::StaticAssert,
++ "ViewHandler arguments error: "
++ "QHttpServerResponder can only be passed as a reference or Rvalue "
++ "reference");
++
++ using IsSpecial = CheckAny<IsRequest, IsResponder>;
++
++ struct IsSimple {
++ static constexpr bool TypeMatched = !IsSpecial::TypeMatched &&
++ I < FunctionTraits::ArgumentCount &&
++ FunctionTraits::ArgumentIndexMax != -1;
++ static constexpr bool Value =
++ !IsSpecial::Value && FunctionTraits::template Arg<I>::CopyConstructible;
++
++ static constexpr bool StaticAssert =
++ DisableStaticAssert || Value || !TypeMatched;
++
++
++ static_assert(StaticAssert,
++ "ViewHandler arguments error: "
++ "Type is not copy constructible");
++ };
++
++ using CheckOk = CheckAny<IsSimple, IsSpecial>;
++
++ static constexpr bool Value = CheckOk::Value;
++ static constexpr bool StaticAssert = CheckOk::StaticAssert;
++ };
++
++
++ struct Arguments {
++ template<size_t ... I>
++ struct ArgumentsReturn {
++ template<int Idx>
++ using Arg = ArgumentChecker<Idx>;
++
++ template<int Idx>
++ static constexpr QMetaType metaType() noexcept
++ {
++ using Type = typename FunctionTraits::template Arg<Idx>::CleanType;
++ constexpr bool Simple = Arg<Idx>::IsSimple::Value;
++
++ if constexpr (Simple && std::is_copy_assignable_v<Type>)
++ return QMetaType::fromType<Type>();
++ else
++ return QMetaType::fromType<void>();
++ }
++
++ static constexpr std::size_t Count = FunctionTraits::ArgumentCount;
++ static constexpr std::size_t CapturableCount =
++ (0 + ... + static_cast<std::size_t>(Arg<I>::IsSimple::Value));
++
++ static constexpr std::size_t SpecialsCount = Count - CapturableCount;
++
++ static constexpr bool Value = (Arg<I>::Value && ...);
++ static constexpr bool StaticAssert = (Arg<I>::StaticAssert && ...);
++
++ using Indexes = std::index_sequence<I...>;
++
++ using CapturableIndexes = std::make_index_sequence<CapturableCount>;
++
++ using SpecialIndexes = std::make_index_sequence<SpecialsCount>;
++
++ using Last = Arg<FunctionTraits::ArgumentIndexMax>;
++ using SecondLast = Arg<FunctionTraits::ArgumentIndexMax - 1>;
++ };
++
++ template<size_t ... I>
++ static constexpr ArgumentsReturn<I...> eval(std::index_sequence<I...>) noexcept;
++ };
++
++ template<int CaptureOffset>
++ struct BindType {
++ template<typename ... Args>
++ struct FunctionWrapper {
++ using Type = std::function<typename FunctionTraits::ReturnType (Args...)>;
++ };
++
++ template<int Id>
++ using OffsetArg = typename FunctionTraits::template Arg<CaptureOffset + Id>::Type;
++
++ template<size_t ... Idx>
++ static constexpr typename FunctionWrapper<OffsetArg<Idx>...>::Type
++ eval(std::index_sequence<Idx...>) noexcept;
++ };
++ };
++
++
++ } // namespace QtPrivate
++
++ template <typename ViewHandler, bool DisableStaticAssert = false>
++ struct QHttpServerRouterViewTraits
++ {
++ using Helpers = typename QtPrivate::RouterViewTraitsHelper<ViewHandler, DisableStaticAssert>;
++ using ReturnType = typename Helpers::FunctionTraits::ReturnType;
++ using Arguments = decltype(Helpers::Arguments::eval(typename Helpers::ArgumentIndexes{}));
++ using BindableType = decltype(Helpers::template BindType<Arguments::CapturableCount>::eval(
++ typename Arguments::SpecialIndexes{}));
++ };
++
++
++ QT_END_NAMESPACE
++
++ #endif // QHTTPSERVERROUTERVIEWTRAITS_H