1// Copyright (C) 2020 Mikhail Svetkin <mikhail.svetkin@gmail.com>
2// Copyright (C) 2019 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6#ifndef QHTTPSERVERROUTERVIEWTRAITS_H
7#define QHTTPSERVERROUTERVIEWTRAITS_H
8
9#include <QtHttpServer/qhttpserverviewtraits_impl.h>
10
11QT_BEGIN_NAMESPACE
12
13class QHttpServerRequest;
14class QHttpServerResponder;
15
16namespace QtPrivate {
17
18template<typename ViewHandler, bool DisableStaticAssert>
19struct RouterViewTraitsHelper : ViewTraits<ViewHandler, DisableStaticAssert> {
20 using VTraits = ViewTraits<ViewHandler, DisableStaticAssert>;
21 using FunctionTraits = typename VTraits::FTraits;
22
23 template<int I>
24 struct ArgumentChecker : FunctionTraits::template Arg<I> {
25 using IsRequest = typename VTraits::template Special<I, const QHttpServerRequest &>;
26 static_assert(IsRequest::AssertCondition,
27 "ViewHandler arguments error: "
28 "QHttpServerRequest can only be passed as a const reference");
29
30 using IsResponder = typename VTraits::template Special<I, QHttpServerResponder &>;
31 static_assert(IsResponder::AssertCondition,
32 "ViewHandler arguments error: "
33 "QHttpServerResponder can only be passed as a reference");
34
35 using IsSpecial = CheckAny<IsRequest, IsResponder>;
36
37 struct IsSimple {
38 static constexpr bool Value = !IsSpecial::Value &&
39 I < FunctionTraits::ArgumentCount &&
40 FunctionTraits::ArgumentIndexMax != -1;
41 static constexpr bool Valid =
42 !IsSpecial::Valid && FunctionTraits::template Arg<I>::CopyConstructible;
43
44 static constexpr bool StaticAssert =
45 DisableStaticAssert || !Value || Valid;
46
47
48 static_assert(StaticAssert,
49 "ViewHandler arguments error: "
50 "Type is not copy constructible");
51 };
52
53 using CheckOk = CheckAny<IsSimple, IsSpecial>;
54
55 static constexpr bool Valid = CheckOk::Valid;
56 static constexpr bool StaticAssert = CheckOk::StaticAssert;
57 };
58
59
60 struct Arguments {
61 template<size_t ... I>
62 struct ArgumentsReturn {
63 template<int Idx>
64 using Arg = ArgumentChecker<Idx>;
65
66 template<int Idx>
67 static constexpr QMetaType metaType() noexcept
68 {
69 using Type = typename FunctionTraits::template Arg<Idx>::CleanType;
70 constexpr bool Simple = Arg<Idx>::IsSimple::Valid;
71
72 if constexpr (Simple && std::is_copy_assignable_v<Type>)
73 return QMetaType::fromType<Type>();
74 else
75 return QMetaType::fromType<void>();
76 }
77
78 static constexpr std::size_t Count = FunctionTraits::ArgumentCount;
79 static constexpr std::size_t CapturableCount =
80 (0 + ... + static_cast<std::size_t>(!Arg<I>::IsSpecial::Value));
81
82 static constexpr std::size_t SpecialsCount = Count - CapturableCount;
83
84 static constexpr bool Valid = (Arg<I>::Valid && ...);
85 static constexpr bool StaticAssert = (Arg<I>::StaticAssert && ...);
86
87 using Indexes = std::index_sequence<I...>;
88
89 using CapturableIndexes = std::make_index_sequence<CapturableCount>;
90
91 using SpecialIndexes = std::make_index_sequence<SpecialsCount>;
92
93 using Last = Arg<FunctionTraits::ArgumentIndexMax>;
94 };
95
96 template<size_t ... I>
97 static constexpr ArgumentsReturn<I...> eval(std::index_sequence<I...>) noexcept;
98 };
99
100 template<int CaptureOffset>
101 struct BindType {
102 template<typename ... Args>
103 struct FunctionWrapper {
104 using Type = std::function<typename FunctionTraits::ReturnType (Args...)>;
105 };
106
107 template<int Id>
108 using OffsetArg = typename FunctionTraits::template Arg<CaptureOffset + Id>::Type;
109
110 template<size_t ... Idx>
111 static constexpr typename FunctionWrapper<OffsetArg<Idx>...>::Type
112 eval(std::index_sequence<Idx...>) noexcept;
113 };
114};
115
116
117} // namespace QtPrivate
118
119template <typename ViewHandler, bool DisableStaticAssert = false>
120struct QHttpServerRouterViewTraits
121{
122 using Helpers = typename QtPrivate::RouterViewTraitsHelper<ViewHandler, DisableStaticAssert>;
123 using ReturnType = typename Helpers::FunctionTraits::ReturnType;
124 using Arguments = decltype(Helpers::Arguments::eval(typename Helpers::ArgumentIndexes{}));
125 using BindableType = decltype(Helpers::template BindType<Arguments::CapturableCount>::eval(
126 typename Arguments::SpecialIndexes{}));
127};
128
129
130QT_END_NAMESPACE
131
132#endif // QHTTPSERVERROUTERVIEWTRAITS_H
133

source code of qthttpserver/src/httpserver/qhttpserverrouterviewtraits.h