mirror of https://github.com/qt/qtgrpc.git
QGrpcSerializationFormat: transform into implicitly shared value class
As this class is copyable and really looks like a implicitly shared value class transform it into such. Also extend the testcase for this class. As a drive-by use a view for the suffix() getter. Task-number: QTBUG-123625 Pick-to: 6.8 Change-Id: I331c62e666a88e4ff6afbe5d484c639f5c96782e Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
parent
72a4cc0af6
commit
c746115e11
|
|
@ -391,7 +391,7 @@ void QGrpcHttp2ChannelPrivate::Http2Handler::attachStream(QHttp2Stream *stream_)
|
||||||
QObject::connect(m_stream.get(), &QHttp2Stream::uploadFinished, this,
|
QObject::connect(m_stream.get(), &QHttp2Stream::uploadFinished, this,
|
||||||
&Http2Handler::processQueue);
|
&Http2Handler::processQueue);
|
||||||
|
|
||||||
std::optional<QGrpcDuration> deadline;
|
std::optional<std::chrono::milliseconds> deadline;
|
||||||
if (channelOpPtr->callOptions().deadline())
|
if (channelOpPtr->callOptions().deadline())
|
||||||
deadline = channelOpPtr->callOptions().deadline();
|
deadline = channelOpPtr->callOptions().deadline();
|
||||||
else if (parentChannel->channelOptions.deadline())
|
else if (parentChannel->channelOptions.deadline())
|
||||||
|
|
@ -589,7 +589,7 @@ QGrpcHttp2ChannelPrivate::QGrpcHttp2ChannelPrivate(const QUrl &uri,
|
||||||
const QGrpcChannelOptions &options)
|
const QGrpcChannelOptions &options)
|
||||||
: hostUri(uri), channelOptions(options)
|
: hostUri(uri), channelOptions(options)
|
||||||
{
|
{
|
||||||
const QByteArray formatSuffix = channelOptions.serializationFormat().suffix();
|
auto formatSuffix = channelOptions.serializationFormat().suffix();
|
||||||
const QByteArray defaultContentType = DefaultContentType.toByteArray();
|
const QByteArray defaultContentType = DefaultContentType.toByteArray();
|
||||||
const QByteArray contentTypeFromOptions = !formatSuffix.isEmpty()
|
const QByteArray contentTypeFromOptions = !formatSuffix.isEmpty()
|
||||||
? defaultContentType + '+' + formatSuffix
|
? defaultContentType + '+' + formatSuffix
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,10 @@
|
||||||
#include <QtProtobuf/qprotobufjsonserializer.h>
|
#include <QtProtobuf/qprotobufjsonserializer.h>
|
||||||
#include <QtProtobuf/qprotobufserializer.h>
|
#include <QtProtobuf/qprotobufserializer.h>
|
||||||
|
|
||||||
|
#include <QtCore/qbytearray.h>
|
||||||
|
#include <QtCore/qdebug.h>
|
||||||
|
#include <QtCore/qvariant.h>
|
||||||
|
|
||||||
using namespace QtGrpc;
|
using namespace QtGrpc;
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
@ -13,6 +17,7 @@ QT_BEGIN_NAMESPACE
|
||||||
/*!
|
/*!
|
||||||
\class QGrpcSerializationFormat
|
\class QGrpcSerializationFormat
|
||||||
\inmodule QtGrpc
|
\inmodule QtGrpc
|
||||||
|
\compares equality
|
||||||
\brief The QGrpcSerializationFormat class holds the protobuf message
|
\brief The QGrpcSerializationFormat class holds the protobuf message
|
||||||
serializer and the related content type suffix.
|
serializer and the related content type suffix.
|
||||||
\since 6.8
|
\since 6.8
|
||||||
|
|
@ -26,7 +31,7 @@ QT_BEGIN_NAMESPACE
|
||||||
\sa QAbstractGrpcChannel
|
\sa QAbstractGrpcChannel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class QGrpcSerializationFormatPrivate
|
class QGrpcSerializationFormatPrivate : public QSharedData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QGrpcSerializationFormatPrivate(QByteArrayView suffix_,
|
QGrpcSerializationFormatPrivate(QByteArrayView suffix_,
|
||||||
|
|
@ -34,14 +39,12 @@ public:
|
||||||
: suffix(suffix_.toByteArray()), serializer(std::move(serializer_))
|
: suffix(suffix_.toByteArray()), serializer(std::move(serializer_))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray suffix;
|
QByteArray suffix;
|
||||||
std::shared_ptr<QAbstractProtobufSerializer> serializer;
|
std::shared_ptr<QAbstractProtobufSerializer> serializer;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void dPtrDeleter(QGrpcSerializationFormatPrivate *ptr)
|
QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QGrpcSerializationFormatPrivate)
|
||||||
{
|
|
||||||
delete ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Creates a new QGrpcSerializationFormat object with the given preset
|
Creates a new QGrpcSerializationFormat object with the given preset
|
||||||
|
|
@ -50,14 +53,13 @@ static void dPtrDeleter(QGrpcSerializationFormatPrivate *ptr)
|
||||||
A \l QtGrpc::SerializationFormat::Default format is used by default.
|
A \l QtGrpc::SerializationFormat::Default format is used by default.
|
||||||
*/
|
*/
|
||||||
QGrpcSerializationFormat::QGrpcSerializationFormat(SerializationFormat format)
|
QGrpcSerializationFormat::QGrpcSerializationFormat(SerializationFormat format)
|
||||||
: dPtr(format == SerializationFormat::Json
|
: d_ptr(format == SerializationFormat::Json
|
||||||
? new QGrpcSerializationFormatPrivate("json",
|
? new QGrpcSerializationFormatPrivate("json",
|
||||||
std::make_shared<QProtobufJsonSerializer>())
|
std::make_shared<QProtobufJsonSerializer>())
|
||||||
: new QGrpcSerializationFormatPrivate(format == SerializationFormat::Protobuf
|
: new QGrpcSerializationFormatPrivate(format == SerializationFormat::Protobuf
|
||||||
? "proto"
|
? "proto"
|
||||||
: "",
|
: "",
|
||||||
std::make_shared<QProtobufSerializer>()),
|
std::make_shared<QProtobufSerializer>()))
|
||||||
dPtrDeleter)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,29 +75,20 @@ QGrpcSerializationFormat::~QGrpcSerializationFormat() = default;
|
||||||
QGrpcSerializationFormat::QGrpcSerializationFormat(QByteArrayView suffix,
|
QGrpcSerializationFormat::QGrpcSerializationFormat(QByteArrayView suffix,
|
||||||
std::shared_ptr<QAbstractProtobufSerializer>
|
std::shared_ptr<QAbstractProtobufSerializer>
|
||||||
serializer)
|
serializer)
|
||||||
: dPtr(new QGrpcSerializationFormatPrivate(suffix, std::move(serializer)),
|
: d_ptr(new QGrpcSerializationFormatPrivate(suffix, std::move(serializer)))
|
||||||
dPtrDeleter)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Constructs a copy of \a other.
|
Constructs a copy of \a other.
|
||||||
*/
|
*/
|
||||||
QGrpcSerializationFormat::QGrpcSerializationFormat(const QGrpcSerializationFormat &other)
|
QGrpcSerializationFormat::QGrpcSerializationFormat(const QGrpcSerializationFormat &other) = default;
|
||||||
: dPtr(new QGrpcSerializationFormatPrivate(*other.dPtr),
|
|
||||||
dPtrDeleter)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Assigns the \a other QGrpcSerializationFormat object to this one.
|
Assigns the \a other QGrpcSerializationFormat object to this one.
|
||||||
*/
|
*/
|
||||||
QGrpcSerializationFormat &QGrpcSerializationFormat::operator=(const QGrpcSerializationFormat &other)
|
QGrpcSerializationFormat &
|
||||||
{
|
QGrpcSerializationFormat::operator=(const QGrpcSerializationFormat &other) = default;
|
||||||
if (this != &other)
|
|
||||||
*dPtr = *other.dPtr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QGrpcSerializationFormat::QGrpcSerializationFormat(QGrpcSerializationFormat &&other) noexcept
|
\fn QGrpcSerializationFormat::QGrpcSerializationFormat(QGrpcSerializationFormat &&other) noexcept
|
||||||
|
|
@ -122,12 +115,22 @@ QGrpcSerializationFormat &QGrpcSerializationFormat::operator=(const QGrpcSeriali
|
||||||
Swaps this instance with \a other. This operation is very fast and never fails.
|
Swaps this instance with \a other. This operation is very fast and never fails.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.8
|
||||||
|
Constructs a new QVariant object from this QGrpcSerializationFormat.
|
||||||
|
*/
|
||||||
|
QGrpcSerializationFormat::operator QVariant() const
|
||||||
|
{
|
||||||
|
return QVariant::fromValue(*this);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the content type suffix for this serialization format.
|
Returns the content type suffix for this serialization format.
|
||||||
*/
|
*/
|
||||||
QByteArray QGrpcSerializationFormat::suffix() const noexcept
|
QByteArrayView QGrpcSerializationFormat::suffix() const noexcept
|
||||||
{
|
{
|
||||||
return dPtr->suffix;
|
Q_D(const QGrpcSerializationFormat);
|
||||||
|
return d->suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -137,7 +140,25 @@ QByteArray QGrpcSerializationFormat::suffix() const noexcept
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<QAbstractProtobufSerializer> QGrpcSerializationFormat::serializer() const noexcept
|
std::shared_ptr<QAbstractProtobufSerializer> QGrpcSerializationFormat::serializer() const noexcept
|
||||||
{
|
{
|
||||||
return dPtr->serializer;
|
Q_D(const QGrpcSerializationFormat);
|
||||||
|
return d->serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
|
/*!
|
||||||
|
\since 6.8
|
||||||
|
\fn QDebug QGrpcSerializationFormat::operator<<(QDebug debug, const QGrpcSerializationFormat &sfmt)
|
||||||
|
Writes \a sfmt to the specified stream \a debug.
|
||||||
|
*/
|
||||||
|
QDebug operator<<(QDebug debug, const QGrpcSerializationFormat &sfmt)
|
||||||
|
{
|
||||||
|
const QDebugStateSaver save(debug);
|
||||||
|
debug.nospace().noquote();
|
||||||
|
debug << "QGrpcSerializationFormat(suffix: " << sfmt.suffix() << ", serializer: { "
|
||||||
|
<< static_cast<void *>(sfmt.serializer().get())
|
||||||
|
<< ", useCount: " << sfmt.serializer().use_count() << " })";
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,19 @@
|
||||||
#include <QtGrpc/qtgrpcnamespace.h>
|
#include <QtGrpc/qtgrpcnamespace.h>
|
||||||
|
|
||||||
#include <QtCore/qbytearrayview.h>
|
#include <QtCore/qbytearrayview.h>
|
||||||
|
#include <QtCore/qshareddata.h>
|
||||||
#include <QtCore/qtclasshelpermacros.h>
|
#include <QtCore/qtclasshelpermacros.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QGrpcSerializationFormatPrivate;
|
|
||||||
class QAbstractProtobufSerializer;
|
class QAbstractProtobufSerializer;
|
||||||
|
class QDebug;
|
||||||
|
class QVariant;
|
||||||
|
|
||||||
|
class QGrpcSerializationFormatPrivate;
|
||||||
|
QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QGrpcSerializationFormatPrivate, Q_GRPC_EXPORT)
|
||||||
|
|
||||||
class QGrpcSerializationFormat final
|
class QGrpcSerializationFormat final
|
||||||
{
|
{
|
||||||
|
|
@ -29,19 +34,40 @@ public:
|
||||||
Q_GRPC_EXPORT QGrpcSerializationFormat &operator=(const QGrpcSerializationFormat &);
|
Q_GRPC_EXPORT QGrpcSerializationFormat &operator=(const QGrpcSerializationFormat &);
|
||||||
|
|
||||||
QGrpcSerializationFormat(QGrpcSerializationFormat &&other) noexcept = default;
|
QGrpcSerializationFormat(QGrpcSerializationFormat &&other) noexcept = default;
|
||||||
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QGrpcSerializationFormat)
|
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QGrpcSerializationFormat)
|
||||||
|
|
||||||
void swap(QGrpcSerializationFormat &other) noexcept { dPtr.swap(other.dPtr); }
|
Q_GRPC_EXPORT Q_IMPLICIT operator QVariant() const;
|
||||||
|
|
||||||
[[nodiscard]] Q_GRPC_EXPORT QByteArray suffix() const noexcept;
|
void swap(QGrpcSerializationFormat &other) noexcept { d_ptr.swap(other.d_ptr); }
|
||||||
|
|
||||||
|
[[nodiscard]] Q_GRPC_EXPORT QByteArrayView suffix() const noexcept;
|
||||||
[[nodiscard]] Q_GRPC_EXPORT std::shared_ptr<QAbstractProtobufSerializer>
|
[[nodiscard]] Q_GRPC_EXPORT std::shared_ptr<QAbstractProtobufSerializer>
|
||||||
serializer() const noexcept;
|
serializer() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<QGrpcSerializationFormatPrivate, void (*)(QGrpcSerializationFormatPrivate *)>
|
QExplicitlySharedDataPointer<QGrpcSerializationFormatPrivate> d_ptr;
|
||||||
dPtr;
|
|
||||||
|
friend bool comparesEqual(const QGrpcSerializationFormat &lhs,
|
||||||
|
const QGrpcSerializationFormat &rhs) noexcept
|
||||||
|
{
|
||||||
|
return lhs.suffix() == rhs.suffix() && lhs.serializer() == rhs.serializer();
|
||||||
|
}
|
||||||
|
Q_DECLARE_EQUALITY_COMPARABLE(QGrpcSerializationFormat)
|
||||||
|
|
||||||
|
friend size_t qHash(const QGrpcSerializationFormat &key, size_t seed = 0) noexcept
|
||||||
|
{
|
||||||
|
return qHashMulti(seed, key.suffix(), key.serializer().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
|
friend Q_GRPC_EXPORT QDebug operator<<(QDebug debug, const QGrpcSerializationFormat &sfmt);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Q_DECLARE_PRIVATE(QGrpcSerializationFormat)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_SHARED(QGrpcSerializationFormat)
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QGRPCSERIALIZATIONFORMAT_H
|
#endif // QGRPCSERIALIZATIONFORMAT_H
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,29 @@
|
||||||
// Copyright (C) 2024 The Qt Company Ltd.
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QtTest/QTest>
|
|
||||||
|
|
||||||
#include <QtGrpc/qgrpcserializationformat.h>
|
#include <QtGrpc/qgrpcserializationformat.h>
|
||||||
|
|
||||||
#include <QtProtobuf/qprotobufjsonserializer.h>
|
#include <QtProtobuf/qprotobufjsonserializer.h>
|
||||||
#include <QtProtobuf/qprotobufserializer.h>
|
#include <QtProtobuf/qprotobufserializer.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <QtTest/qtest.h>
|
||||||
|
|
||||||
using namespace QtGrpc;
|
using namespace QtGrpc;
|
||||||
|
|
||||||
class QGrpcSerializationFormatTest : public QObject
|
class QGrpcSerializationFormatTest : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
|
||||||
QGrpcSerializationFormatTest() { }
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void constructEmbedded();
|
void constructFromEnum() const;
|
||||||
void constructCustom();
|
void constructCustom() const;
|
||||||
void copyMove();
|
void hasSpecialMemberFunctions() const;
|
||||||
|
void hasImplicitQVariant() const;
|
||||||
|
void hasMemberSwap() const;
|
||||||
|
void streamsToDebug() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void QGrpcSerializationFormatTest::constructEmbedded()
|
void QGrpcSerializationFormatTest::constructFromEnum() const
|
||||||
{
|
{
|
||||||
QGrpcSerializationFormat defaultFormat = SerializationFormat::Default;
|
QGrpcSerializationFormat defaultFormat = SerializationFormat::Default;
|
||||||
QCOMPARE(defaultFormat.suffix(), "");
|
QCOMPARE(defaultFormat.suffix(), "");
|
||||||
|
|
@ -39,14 +38,14 @@ void QGrpcSerializationFormatTest::constructEmbedded()
|
||||||
QVERIFY(dynamic_cast<QProtobufSerializer *>(protobufFormat.serializer().get()) != nullptr);
|
QVERIFY(dynamic_cast<QProtobufSerializer *>(protobufFormat.serializer().get()) != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QGrpcSerializationFormatTest::constructCustom()
|
void QGrpcSerializationFormatTest::constructCustom() const
|
||||||
{
|
{
|
||||||
QGrpcSerializationFormat customFormat("test", std::make_shared<QProtobufJsonSerializer>());
|
QGrpcSerializationFormat customFormat("test", std::make_shared<QProtobufJsonSerializer>());
|
||||||
QCOMPARE(customFormat.suffix(), "test");
|
QCOMPARE(customFormat.suffix(), "test");
|
||||||
QVERIFY(dynamic_cast<QProtobufJsonSerializer *>(customFormat.serializer().get()) != nullptr);
|
QVERIFY(dynamic_cast<QProtobufJsonSerializer *>(customFormat.serializer().get()) != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QGrpcSerializationFormatTest::copyMove()
|
void QGrpcSerializationFormatTest::hasSpecialMemberFunctions() const
|
||||||
{
|
{
|
||||||
QGrpcSerializationFormat f1(SerializationFormat::Json);
|
QGrpcSerializationFormat f1(SerializationFormat::Json);
|
||||||
|
|
||||||
|
|
@ -77,6 +76,48 @@ void QGrpcSerializationFormatTest::copyMove()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QGrpcSerializationFormatTest::hasImplicitQVariant() const
|
||||||
|
{
|
||||||
|
QGrpcSerializationFormat sfmt1("test", std::make_shared<QProtobufJsonSerializer>());
|
||||||
|
QVariant v = sfmt1;
|
||||||
|
QCOMPARE_EQ(v.metaType(), QMetaType::fromType<QGrpcSerializationFormat>());
|
||||||
|
const auto sfmt2 = v.value<QGrpcSerializationFormat>();
|
||||||
|
QCOMPARE_EQ(sfmt1.suffix(), sfmt2.suffix());
|
||||||
|
QCOMPARE_EQ(sfmt1.serializer(), sfmt2.serializer());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGrpcSerializationFormatTest::hasMemberSwap() const
|
||||||
|
{
|
||||||
|
auto jsonSer = std::make_shared<QProtobufJsonSerializer>();
|
||||||
|
auto pbSer = std::make_shared<QProtobufSerializer>();
|
||||||
|
QGrpcSerializationFormat sfmt1("one", jsonSer);
|
||||||
|
QGrpcSerializationFormat sfmt2("two", pbSer);
|
||||||
|
sfmt1.swap(sfmt2);
|
||||||
|
auto check = [&](auto a, auto b) {
|
||||||
|
QCOMPARE_EQ(a.suffix(), QByteArray("two"));
|
||||||
|
QCOMPARE_EQ(a.serializer(), pbSer);
|
||||||
|
QCOMPARE_EQ(b.suffix(), QByteArray("one"));
|
||||||
|
QCOMPARE_EQ(b.serializer(), jsonSer);
|
||||||
|
};
|
||||||
|
check(sfmt1, sfmt2);
|
||||||
|
swap(sfmt1, sfmt2);
|
||||||
|
check(sfmt2, sfmt1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGrpcSerializationFormatTest::streamsToDebug() const
|
||||||
|
{
|
||||||
|
QGrpcSerializationFormat sfmt("custom", std::make_shared<QProtobufJsonSerializer>());
|
||||||
|
QString storage;
|
||||||
|
QDebug dbg(&storage);
|
||||||
|
dbg.noquote().nospace();
|
||||||
|
|
||||||
|
dbg << sfmt;
|
||||||
|
QVERIFY(!storage.isEmpty());
|
||||||
|
|
||||||
|
std::unique_ptr<char[]> ustr(QTest::toString(sfmt));
|
||||||
|
QCOMPARE_EQ(storage, QString::fromUtf8(ustr.get()));
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(QGrpcSerializationFormatTest)
|
QTEST_MAIN(QGrpcSerializationFormatTest)
|
||||||
|
|
||||||
#include "tst_qgrpcserializationformat.moc"
|
#include "tst_qgrpcserializationformat.moc"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue