From 66984e6a3cc3bb8b3a98f16a8630d9814316df4e Mon Sep 17 00:00:00 2001 From: Dennis Oberst Date: Wed, 30 Apr 2025 14:17:43 +0200 Subject: [PATCH] QGrpc{Channel,Call}Options: Support incremental updates via addMetadata Currently we only provide `setMetadata(~)` as a way for users to supply their metadata. However, certain code paths would benefit from having an `add` functionality as well, without requiring the user to create a temporary object. [ChangeLog][GRPC][QGrpc*Options] Added support for incrementally adding metadata via `addMetadata()`. Change-Id: Ibc5d721850745df5f171b9126b595ca9c6b0c319 Reviewed-by: Alexey Edelev --- src/grpc/qgrpccalloptions.cpp | 16 ++++++++++++++++ src/grpc/qgrpccalloptions.h | 1 + src/grpc/qgrpcchanneloptions.cpp | 16 ++++++++++++++++ src/grpc/qgrpcchanneloptions.h | 1 + src/grpc/qgrpccommonoptions.cpp | 20 ++++++++++++++++++++ src/grpc/qgrpccommonoptions_p.h | 1 + tests/auto/grpc/shared/grpccommonoptions.h | 8 ++++++++ 7 files changed, 63 insertions(+) diff --git a/src/grpc/qgrpccalloptions.cpp b/src/grpc/qgrpccalloptions.cpp index 663b7704..f8770dac 100644 --- a/src/grpc/qgrpccalloptions.cpp +++ b/src/grpc/qgrpccalloptions.cpp @@ -256,6 +256,22 @@ QGrpcCallOptions::setMetadata(std::initializer_list(list)); } +/*! + \include qgrpccommonoptions.cpp add-metadata + + \include qgrpccalloptions.cpp merge-md-note + \l{QGrpcChannelOptions::addMetadata()} +*/ +QGrpcCallOptions &QGrpcCallOptions::addMetadata(QByteArray key, QByteArray value) +{ + if (d_ptr->metadata(QtGrpc::MultiValue).contains(key, value)) + return *this; + d_ptr.detach(); + Q_D(QGrpcCallOptions); + d->addMetadata(std::move(key), std::move(value)); + return *this; +} + #ifndef QT_NO_DEBUG_STREAM /*! \since 6.8 diff --git a/src/grpc/qgrpccalloptions.h b/src/grpc/qgrpccalloptions.h index 98a09d68..600da0c6 100644 --- a/src/grpc/qgrpccalloptions.h +++ b/src/grpc/qgrpccalloptions.h @@ -62,6 +62,7 @@ public: Q_GRPC_EXPORT QGrpcCallOptions &setMetadata(QMultiHash &&metadata); Q_GRPC_EXPORT QGrpcCallOptions & setMetadata(std::initializer_list> list); + Q_GRPC_EXPORT QGrpcCallOptions &addMetadata(QByteArray key, QByteArray value); private: QExplicitlySharedDataPointer d_ptr; diff --git a/src/grpc/qgrpcchanneloptions.cpp b/src/grpc/qgrpcchanneloptions.cpp index 2ec8c7da..6a552cbc 100644 --- a/src/grpc/qgrpcchanneloptions.cpp +++ b/src/grpc/qgrpcchanneloptions.cpp @@ -265,6 +265,22 @@ QGrpcChannelOptions::setMetadata(std::initializer_list(list)); } +/*! + \include qgrpccommonoptions.cpp add-metadata + + \include qgrpcchanneloptions.cpp merge-md-note + \l{QGrpcCallOptions::addMetadata()} +*/ +QGrpcChannelOptions &QGrpcChannelOptions::addMetadata(QByteArray key, QByteArray value) +{ + if (d_ptr->metadata(QtGrpc::MultiValue).contains(key, value)) + return *this; + d_ptr.detach(); + Q_D(QGrpcChannelOptions); + d->addMetadata(std::move(key), std::move(value)); + return *this; +} + /*! \since 6.8 diff --git a/src/grpc/qgrpcchanneloptions.h b/src/grpc/qgrpcchanneloptions.h index a6896dd2..caa2e4ca 100644 --- a/src/grpc/qgrpcchanneloptions.h +++ b/src/grpc/qgrpcchanneloptions.h @@ -68,6 +68,7 @@ public: Q_GRPC_EXPORT QGrpcChannelOptions &setMetadata(QMultiHash &&metadata); Q_GRPC_EXPORT QGrpcChannelOptions & setMetadata(std::initializer_list> list); + Q_GRPC_EXPORT QGrpcChannelOptions &addMetadata(QByteArray key, QByteArray value); [[nodiscard]] Q_GRPC_EXPORT QGrpcSerializationFormat serializationFormat() const; Q_GRPC_EXPORT QGrpcChannelOptions & diff --git a/src/grpc/qgrpccommonoptions.cpp b/src/grpc/qgrpccommonoptions.cpp index 9f237af5..556b759d 100644 --- a/src/grpc/qgrpccommonoptions.cpp +++ b/src/grpc/qgrpccommonoptions.cpp @@ -137,4 +137,24 @@ void QGrpcCommonOptions::setMetadata(QMultiHash &&md) #endif } +/*! +//! [add-metadata] + \since 6.10 + + Adds \a key and \a value to the \l metadata if the exact pair is not already contained. + The same key may appear multiple times with different values. + + \sa {metadata(QtGrpc::MultiValueTag)}{metadata()} {setMetadata(const + QMultiHash&)}{setMetadata()} +//! [add-metadata] +*/ +void QGrpcCommonOptions::addMetadata(QByteArray &&key, QByteArray &&value) +{ +#if QT_DEPRECATED_SINCE(6, 13) + if (m_deprecatedQHashRefUsed) + m_metadata.insertOrAssign(key, value); +#endif + m_metadataMulti.emplace(std::move(key), std::move(value)); +} + QT_END_NAMESPACE diff --git a/src/grpc/qgrpccommonoptions_p.h b/src/grpc/qgrpccommonoptions_p.h index 85e2591a..38c46bc1 100644 --- a/src/grpc/qgrpccommonoptions_p.h +++ b/src/grpc/qgrpccommonoptions_p.h @@ -46,6 +46,7 @@ public: QMultiHash metadata(QtGrpc::MultiValueTag /*tag*/) &&; void setMetadata(const QMultiHash &md); void setMetadata(QMultiHash &&md); + void addMetadata(QByteArray &&key, QByteArray &&value); private: std::optional m_timeout; diff --git a/tests/auto/grpc/shared/grpccommonoptions.h b/tests/auto/grpc/shared/grpccommonoptions.h index 689db084..beac6b56 100644 --- a/tests/auto/grpc/shared/grpccommonoptions.h +++ b/tests/auto/grpc/shared/grpccommonoptions.h @@ -210,6 +210,14 @@ QT_WARNING_POP T o4; o4.setMetadata(list); QCOMPARE_EQ(o4.metadata(QtGrpc::MultiValue), data); + + // addMetadata + T o5 = T{}.addMetadata("keyA", "valA1").addMetadata("keyA", "valA2"); + auto o5Detach = o5; + QByteArray k = "keyB", v = "valB"; + o5.addMetadata(k, v); + QCOMPARE_EQ(o5.metadata(QtGrpc::MultiValue), data); + QCOMPARE_NE(o5.metadata(QtGrpc::MultiValue), o5Detach.metadata(QtGrpc::MultiValue)); } void propertyDeadline() const {