1 | // Copyright (C) 2023 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include <QtGrpc/qgrpccalloptions.h> |
5 | |
6 | #include <QtCore/qbytearray.h> |
7 | #include <QtCore/qdebug.h> |
8 | #include <QtCore/qvariant.h> |
9 | |
10 | QT_BEGIN_NAMESPACE |
11 | |
12 | using namespace Qt::StringLiterals; |
13 | |
14 | /*! |
15 | \class QGrpcCallOptions |
16 | \inmodule QtGrpc |
17 | \brief The QGrpcCallOptions class offers various options for fine-tuning |
18 | individual RPCs. |
19 | \since 6.6 |
20 | |
21 | QGrpcCallOptions lets you customize individual remote procedure calls (RPCs). |
22 | The generated client interface provides access points to pass the QGrpcCallOptions. |
23 | These options supersede the ones set via QGrpcChannelOptions. |
24 | |
25 | To configure the default options shared by RPCs, use QGrpcChannelOptions. |
26 | */ |
27 | |
28 | class QGrpcCallOptionsPrivate : public QSharedData |
29 | { |
30 | public: |
31 | std::optional<std::chrono::milliseconds> timeout; |
32 | QHash<QByteArray, QByteArray> metadata; |
33 | }; |
34 | |
35 | QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QGrpcCallOptionsPrivate) |
36 | |
37 | /*! |
38 | Default-constructs an empty QGrpcCallOptions. |
39 | */ |
40 | QGrpcCallOptions::QGrpcCallOptions() : d_ptr(new QGrpcCallOptionsPrivate()) |
41 | { |
42 | } |
43 | |
44 | /*! |
45 | Destroys the QGrpcCallOptions. |
46 | */ |
47 | QGrpcCallOptions::~QGrpcCallOptions() = default; |
48 | |
49 | /*! |
50 | Copy-constructs a QGrpcCallOptions from \a other. |
51 | */ |
52 | QGrpcCallOptions::QGrpcCallOptions(const QGrpcCallOptions &other) = default; |
53 | |
54 | /*! |
55 | Assigns \a other to this QGrpcCallOptions and returns a reference to the |
56 | updated object. |
57 | */ |
58 | QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other) = default; |
59 | |
60 | /*! |
61 | \fn QGrpcCallOptions::QGrpcCallOptions(QGrpcCallOptions &&other) |
62 | |
63 | Move-constructs a new QGrpcCallOptions from \a other. |
64 | |
65 | \include qtgrpc-shared.qdocinc move-note-desc |
66 | */ |
67 | |
68 | /*! |
69 | \fn QGrpcCallOptions &QGrpcCallOptions::operator=(QGrpcCallOptions &&other) |
70 | |
71 | Move-assigns \a other to this QGrpcCallOptions and returns a reference to |
72 | the updated object. |
73 | |
74 | \include qtgrpc-shared.qdocinc move-note-desc |
75 | */ |
76 | |
77 | /*! |
78 | \since 6.8 |
79 | |
80 | \include qtgrpc-shared.qdocinc qvariant-desc |
81 | */ |
82 | QGrpcCallOptions::operator QVariant() const |
83 | { |
84 | return QVariant::fromValue(value: *this); |
85 | } |
86 | |
87 | /*! |
88 | \since 6.8 |
89 | \fn void QGrpcCallOptions::swap(QGrpcCallOptions &other) |
90 | |
91 | \include qtgrpc-shared.qdocinc swap-desc |
92 | */ |
93 | |
94 | /*! |
95 | Sets the \a timeout for a specific RPC and returns a reference to the |
96 | updated object. |
97 | |
98 | //! [set-deadline-desc] |
99 | A deadline sets the limit for how long a client is willing to wait for a |
100 | response from a server. The actual deadline is computed by adding the \a |
101 | timeout to the start time of the RPC. |
102 | |
103 | The deadline applies to the entire lifetime of an RPC, which includes |
104 | receiving the final QGrpcStatus for a previously started call and can thus |
105 | be unwanted for (long-lived) streams. |
106 | //! [set-deadline-desc] |
107 | |
108 | \note Setting this field overrides the value set by |
109 | QGrpcChannelOptions::setDeadline() for a specific RPC. |
110 | */ |
111 | QGrpcCallOptions &QGrpcCallOptions::setDeadlineTimeout(std::chrono::milliseconds timeout) |
112 | { |
113 | if (d_ptr->timeout == timeout) |
114 | return *this; |
115 | d_ptr.detach(); |
116 | Q_D(QGrpcCallOptions); |
117 | d->timeout = timeout; |
118 | return *this; |
119 | } |
120 | |
121 | /*! |
122 | \fn QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QHash<QByteArray, QByteArray> &metadata) |
123 | \fn QGrpcCallOptions &QGrpcCallOptions::setMetadata(QHash<QByteArray, QByteArray> &&metadata) |
124 | |
125 | Sets the client \a metadata for a specific RPC and returns a reference to the |
126 | updated object. |
127 | |
128 | //! [set-metadata-desc] |
129 | QGrpcHttp2Channel converts the metadata into appropriate HTTP/2 headers |
130 | which will be added to the HTTP/2 request. |
131 | //! [set-metadata-desc] |
132 | |
133 | \note Setting this field overrides the value set by |
134 | QGrpcChannelOptions::setMetadata() for a specific RPC. |
135 | */ |
136 | QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QHash<QByteArray, QByteArray> &metadata) |
137 | { |
138 | if (d_ptr->metadata == metadata) |
139 | return *this; |
140 | d_ptr.detach(); |
141 | Q_D(QGrpcCallOptions); |
142 | d->metadata = metadata; |
143 | return *this; |
144 | } |
145 | |
146 | QGrpcCallOptions &QGrpcCallOptions::setMetadata(QHash<QByteArray, QByteArray> &&metadata) |
147 | { |
148 | if (d_ptr->metadata == metadata) |
149 | return *this; |
150 | d_ptr.detach(); |
151 | Q_D(QGrpcCallOptions); |
152 | d->metadata = std::move(metadata); |
153 | return *this; |
154 | } |
155 | |
156 | /*! |
157 | Returns the timeout duration that is used to calculate the deadline for a |
158 | specific RPC. |
159 | |
160 | If this field is unset, returns an empty \c {std::optional}. |
161 | */ |
162 | std::optional<std::chrono::milliseconds> QGrpcCallOptions::deadlineTimeout() const noexcept |
163 | { |
164 | Q_D(const QGrpcCallOptions); |
165 | return d->timeout; |
166 | } |
167 | |
168 | /*! |
169 | \fn const QHash<QByteArray, QByteArray> &QGrpcCallOptions::metadata() const & |
170 | \fn QHash<QByteArray, QByteArray> QGrpcCallOptions::metadata() && |
171 | |
172 | Returns the client metadata for a specific RPC. |
173 | If this field is unset, returns empty metadata. |
174 | */ |
175 | const QHash<QByteArray, QByteArray> &QGrpcCallOptions::metadata() const & noexcept |
176 | { |
177 | Q_D(const QGrpcCallOptions); |
178 | return d->metadata; |
179 | } |
180 | |
181 | QHash<QByteArray, QByteArray> QGrpcCallOptions::metadata() && |
182 | { |
183 | Q_D(QGrpcCallOptions); |
184 | if (d->ref.loadRelaxed() != 1) // return copy if shared |
185 | return { d->metadata }; |
186 | return std::move(d->metadata); |
187 | } |
188 | |
189 | #ifndef QT_NO_DEBUG_STREAM |
190 | /*! |
191 | \since 6.8 |
192 | \fn QDebug QGrpcCallOptions::operator<<(QDebug debug, const QGrpcCallOptions &callOpts) |
193 | |
194 | Writes \a callOpts to the specified stream \a debug. |
195 | */ |
196 | QDebug operator<<(QDebug debug, const QGrpcCallOptions &callOpts) |
197 | { |
198 | const QDebugStateSaver save(debug); |
199 | debug.nospace().noquote(); |
200 | debug << "QGrpcCallOptions(deadline: " << callOpts.deadlineTimeout() |
201 | << ", metadata: " << callOpts.metadata() << ')'; |
202 | return debug; |
203 | } |
204 | #endif |
205 | |
206 | QT_END_NAMESPACE |
207 | |