1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtGrpc/private/qgrpccommonoptions_p.h>
5#include <QtGrpc/private/qtgrpclogging_p.h>
6#include <QtGrpc/qgrpccalloptions.h>
7
8#include <QtCore/qbytearray.h>
9#include <QtCore/qdebug.h>
10#include <QtCore/qvariant.h>
11
12QT_BEGIN_NAMESPACE
13
14using namespace Qt::StringLiterals;
15
16/*!
17 \class QGrpcCallOptions
18 \inmodule QtGrpc
19 \brief The QGrpcCallOptions class offers various options for fine-tuning
20 individual RPCs.
21 \since 6.6
22
23 QGrpcCallOptions lets you customize individual remote procedure calls (RPCs).
24 The generated client interface provides access points to pass the QGrpcCallOptions.
25 These options supersede the ones set via QGrpcChannelOptions.
26
27 To configure the default options shared by RPCs, use QGrpcChannelOptions.
28
29 \code
30 QGrpcCallOptions callOpts;
31 // Set the metadata for an individial RPC
32 callOpts.setMetadata({
33 { "header" , "value1" },
34 { "header" , "value2" },
35 });
36 const auto &md = callOpts.metadata(QtGrpc::MultiValue);
37 qDebug() << "Call Metadata: " << md;
38
39 // Set a 2-second deadline for an individial RPC
40 callOpts.setDeadlineTimeout(2s);
41 qDebug() << "Call timeout: " << callOpts.deadlineTimeout();
42 \endcode
43*/
44
45class QGrpcCallOptionsPrivate : public QGrpcCommonOptions
46{
47public:
48 QGrpcCallOptionsPrivate() = default;
49};
50
51QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QGrpcCallOptionsPrivate)
52
53/*!
54 Default-constructs an empty QGrpcCallOptions.
55*/
56QGrpcCallOptions::QGrpcCallOptions() : d_ptr(new QGrpcCallOptionsPrivate())
57{
58}
59
60/*!
61 Destroys the QGrpcCallOptions.
62*/
63QGrpcCallOptions::~QGrpcCallOptions() = default;
64
65/*!
66 Copy-constructs a QGrpcCallOptions from \a other.
67*/
68QGrpcCallOptions::QGrpcCallOptions(const QGrpcCallOptions &other) = default;
69
70/*!
71 Assigns \a other to this QGrpcCallOptions and returns a reference to the
72 updated object.
73*/
74QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other) = default;
75
76/*!
77 \fn QGrpcCallOptions::QGrpcCallOptions(QGrpcCallOptions &&other)
78
79 Move-constructs a new QGrpcCallOptions from \a other.
80
81 \include qtgrpc-shared.qdocinc move-note-desc
82*/
83
84/*!
85 \fn QGrpcCallOptions &QGrpcCallOptions::operator=(QGrpcCallOptions &&other)
86
87 Move-assigns \a other to this QGrpcCallOptions and returns a reference to
88 the updated object.
89
90 \include qtgrpc-shared.qdocinc move-note-desc
91*/
92
93/*!
94 \since 6.8
95
96 \include qtgrpc-shared.qdocinc qvariant-desc
97*/
98QGrpcCallOptions::operator QVariant() const
99{
100 return QVariant::fromValue(value: *this);
101}
102
103/*!
104 \since 6.8
105 \fn void QGrpcCallOptions::swap(QGrpcCallOptions &other)
106
107 \include qtgrpc-shared.qdocinc swap-desc
108*/
109
110/*!
111 \include qgrpccommonoptions.cpp set-deadline-timeout
112
113 \note Setting this field \b{overrides} the corresponding channel options field
114 — see \l{QGrpcChannelOptions::setDeadlineTimeout()}
115
116 \sa deadlineTimeout()
117*/
118QGrpcCallOptions &QGrpcCallOptions::setDeadlineTimeout(std::chrono::milliseconds timeout)
119{
120 if (d_ptr->deadlineTimeout() == timeout)
121 return *this;
122 d_ptr.detach();
123 Q_D(QGrpcCallOptions);
124 d->setDeadlineTimeout(timeout);
125 return *this;
126}
127
128/*!
129 \include qgrpccommonoptions.cpp deadline-timeout
130*/
131std::optional<std::chrono::milliseconds> QGrpcCallOptions::deadlineTimeout() const noexcept
132{
133 Q_D(const QGrpcCallOptions);
134 return d->deadlineTimeout();
135}
136
137#if QT_DEPRECATED_SINCE(6, 13)
138
139/*!
140 \fn const QHash<QByteArray, QByteArray> &QGrpcCallOptions::metadata() const &
141 \fn QHash<QByteArray, QByteArray> QGrpcCallOptions::metadata() &&
142 \deprecated [6.13] Use the QMultiHash overload instead.
143
144 \include qgrpccommonoptions.cpp metadata
145
146 \sa setMetadata()
147*/
148const QHash<QByteArray, QByteArray> &QGrpcCallOptions::metadata() const & noexcept
149{
150 Q_D(const QGrpcCallOptions);
151 return d->metadata();
152}
153QHash<QByteArray, QByteArray> QGrpcCallOptions::metadata() &&
154{
155 Q_D(QGrpcCallOptions);
156 if (d->ref.loadRelaxed() != 1)
157 return d->metadata();
158 return std::move(*d_ptr).metadata();
159}
160
161/*!
162 \fn QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QHash<QByteArray, QByteArray> &metadata)
163 \fn QGrpcCallOptions &QGrpcCallOptions::setMetadata(QHash<QByteArray, QByteArray> &&metadata)
164 \deprecated [6.13] Use the QMultiHash overload instead.
165
166 \include qgrpccommonoptions.cpp set-metadata
167
168//! [merge-md-note]
169 \note Call metadata is \b{merged} with any channel-level metadata when the
170 RPC starts — see
171//! [merge-md-note]
172 \l{QGrpcChannelOptions::setMetadata(const QMultiHash<QByteArray,
173 QByteArray>&)}{QGrpcChannelOptions::setMetadata(QMultiHash)}.
174
175 \sa metadata()
176*/
177QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QHash<QByteArray, QByteArray> &metadata)
178{
179 if (d_ptr->metadata() == metadata)
180 return *this;
181 d_ptr.detach();
182 Q_D(QGrpcCallOptions);
183 d->setMetadata(metadata);
184 return *this;
185}
186QGrpcCallOptions &QGrpcCallOptions::setMetadata(QHash<QByteArray, QByteArray> &&metadata)
187{
188 if (d_ptr->metadata() == metadata)
189 return *this;
190 d_ptr.detach();
191 Q_D(QGrpcCallOptions);
192 d->setMetadata(std::move(metadata));
193 return *this;
194}
195
196#endif // QT_DEPRECATED_SINCE(6, 13)
197
198/*!
199 \since 6.10
200 \fn const QMultiHash<QByteArray, QByteArray> &QGrpcCallOptions::metadata(QtGrpc::MultiValue_t) const &
201 \fn QMultiHash<QByteArray, QByteArray> QGrpcCallOptions::metadata(QtGrpc::MultiValue_t) &&
202
203 \include qgrpccommonoptions.cpp metadata-multi
204
205 \sa {setMetadata(const QMultiHash<QByteArray, QByteArray>&)}{setMetadata}
206*/
207const QMultiHash<QByteArray, QByteArray> &
208QGrpcCallOptions::metadata(QtGrpc::MultiValue_t tag) const & noexcept
209{
210 Q_D(const QGrpcCallOptions);
211 return d->metadata(tag);
212}
213QMultiHash<QByteArray, QByteArray> QGrpcCallOptions::metadata(QtGrpc::MultiValue_t tag) &&
214{
215 Q_D(QGrpcCallOptions);
216 if (d->ref.loadRelaxed() != 1)
217 return d->metadata(tag);
218 return std::move(*d_ptr).metadata(tag);
219}
220
221/*!
222 \since 6.10
223 \fn QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QMultiHash<QByteArray, QByteArray> &metadata)
224 \fn QGrpcCallOptions &QGrpcCallOptions::setMetadata(QMultiHash<QByteArray, QByteArray> &&metadata)
225 \fn QGrpcCallOptions &QGrpcCallOptions::setMetadata(std::initializer_list<std::pair<QByteArray, QByteArray>> metadata)
226
227 \include qgrpccommonoptions.cpp set-metadata-multi
228
229 \include qgrpccalloptions.cpp merge-md-note
230 \l{QGrpcChannelOptions::setMetadata(const QMultiHash<QByteArray,
231 QByteArray>&)}{QGrpcChannelOptions::setMetadata(QMultiHash)}.
232
233 \sa metadata(QtGrpc::MultiValue_t)
234*/
235QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QMultiHash<QByteArray, QByteArray> &metadata)
236{
237 if (d_ptr->metadata(QtGrpc::MultiValue) == metadata)
238 return *this;
239 d_ptr.detach();
240 Q_D(QGrpcCallOptions);
241 d->setMetadata(metadata);
242 return *this;
243}
244QGrpcCallOptions &QGrpcCallOptions::setMetadata(QMultiHash<QByteArray, QByteArray> &&metadata)
245{
246 if (d_ptr->metadata(QtGrpc::MultiValue) == metadata)
247 return *this;
248 d_ptr.detach();
249 Q_D(QGrpcCallOptions);
250 d->setMetadata(std::move(metadata));
251 return *this;
252}
253QGrpcCallOptions &
254QGrpcCallOptions::setMetadata(std::initializer_list<std::pair<QByteArray, QByteArray>> list)
255{
256 return setMetadata(QMultiHash<QByteArray, QByteArray>(list));
257}
258
259/*!
260 \include qgrpccommonoptions.cpp add-metadata
261
262 \include qgrpccalloptions.cpp merge-md-note
263 \l{QGrpcChannelOptions::addMetadata()}
264*/
265QGrpcCallOptions &QGrpcCallOptions::addMetadata(QByteArrayView key, QByteArrayView value)
266{
267 if (d_ptr->containsMetadata(key, value))
268 return *this;
269 d_ptr.detach();
270 Q_D(QGrpcCallOptions);
271 d->addMetadata(key: key.toByteArray(), value: value.toByteArray());
272 return *this;
273}
274
275/*!
276 \include qgrpccommonoptions.cpp filterServerMetadata
277 \sa QGrpcChannelOptions::filterServerMetadata()
278*/
279std::optional<bool> QGrpcCallOptions::filterServerMetadata() const noexcept
280{
281 Q_D(const QGrpcCallOptions);
282 return d->filterServerMetadata();
283}
284
285/*!
286 \include qgrpccommonoptions.cpp setFilterServerMetadata
287 \note Setting this field \b{overrides} the corresponding channel options
288 field — see \l{QGrpcChannelOptions::setFilterServerMetadata()}
289
290 \sa QGrpcChannelOptions::setFilterServerMetadata()
291*/
292QGrpcCallOptions &QGrpcCallOptions::setFilterServerMetadata(bool value)
293{
294 if (d_ptr->filterServerMetadata() == value)
295 return *this;
296 d_ptr.detach();
297 Q_D(QGrpcCallOptions);
298 d->setFilterServerMetadata(value);
299 return *this;
300}
301
302#ifndef QT_NO_DEBUG_STREAM
303/*!
304 \since 6.8
305 \fn QDebug QGrpcCallOptions::operator<<(QDebug debug, const QGrpcCallOptions &callOpts)
306
307 Writes \a callOpts to the specified stream \a debug.
308*/
309QDebug operator<<(QDebug debug, const QGrpcCallOptions &callOpts)
310{
311 const QDebugStateSaver save(debug);
312 debug.nospace().noquote();
313 debug << "QGrpcCallOptions(deadline: " << callOpts.deadlineTimeout()
314 << ", metadata: " << callOpts.metadata(tag: QtGrpc::MultiValue) << ')';
315 return debug;
316}
317#endif
318
319QT_END_NAMESPACE
320

source code of qtgrpc/src/grpc/qgrpccalloptions.cpp