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

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