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,
|
||||
&Http2Handler::processQueue);
|
||||
|
||||
std::optional<QGrpcDuration> deadline;
|
||||
std::optional<std::chrono::milliseconds> deadline;
|
||||
if (channelOpPtr->callOptions().deadline())
|
||||
deadline = channelOpPtr->callOptions().deadline();
|
||||
else if (parentChannel->channelOptions.deadline())
|
||||
|
|
@ -589,7 +589,7 @@ QGrpcHttp2ChannelPrivate::QGrpcHttp2ChannelPrivate(const QUrl &uri,
|
|||
const QGrpcChannelOptions &options)
|
||||
: hostUri(uri), channelOptions(options)
|
||||
{
|
||||
const QByteArray formatSuffix = channelOptions.serializationFormat().suffix();
|
||||
auto formatSuffix = channelOptions.serializationFormat().suffix();
|
||||
const QByteArray defaultContentType = DefaultContentType.toByteArray();
|
||||
const QByteArray contentTypeFromOptions = !formatSuffix.isEmpty()
|
||||
? defaultContentType + '+' + formatSuffix
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
#include <QtProtobuf/qprotobufjsonserializer.h>
|
||||
#include <QtProtobuf/qprotobufserializer.h>
|
||||
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
using namespace QtGrpc;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
@ -13,6 +17,7 @@ QT_BEGIN_NAMESPACE
|
|||
/*!
|
||||
\class QGrpcSerializationFormat
|
||||
\inmodule QtGrpc
|
||||
\compares equality
|
||||
\brief The QGrpcSerializationFormat class holds the protobuf message
|
||||
serializer and the related content type suffix.
|
||||
\since 6.8
|
||||
|
|
@ -26,7 +31,7 @@ QT_BEGIN_NAMESPACE
|
|||
\sa QAbstractGrpcChannel
|
||||
*/
|
||||
|
||||
class QGrpcSerializationFormatPrivate
|
||||
class QGrpcSerializationFormatPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
QGrpcSerializationFormatPrivate(QByteArrayView suffix_,
|
||||
|
|
@ -34,14 +39,12 @@ public:
|
|||
: suffix(suffix_.toByteArray()), serializer(std::move(serializer_))
|
||||
{
|
||||
}
|
||||
|
||||
QByteArray suffix;
|
||||
std::shared_ptr<QAbstractProtobufSerializer> serializer;
|
||||
};
|
||||
|
||||
static void dPtrDeleter(QGrpcSerializationFormatPrivate *ptr)
|
||||
{
|
||||
delete ptr;
|
||||
}
|
||||
QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QGrpcSerializationFormatPrivate)
|
||||
|
||||
/*!
|
||||
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.
|
||||
*/
|
||||
QGrpcSerializationFormat::QGrpcSerializationFormat(SerializationFormat format)
|
||||
: dPtr(format == SerializationFormat::Json
|
||||
? new QGrpcSerializationFormatPrivate("json",
|
||||
std::make_shared<QProtobufJsonSerializer>())
|
||||
: new QGrpcSerializationFormatPrivate(format == SerializationFormat::Protobuf
|
||||
? "proto"
|
||||
: "",
|
||||
std::make_shared<QProtobufSerializer>()),
|
||||
dPtrDeleter)
|
||||
: d_ptr(format == SerializationFormat::Json
|
||||
? new QGrpcSerializationFormatPrivate("json",
|
||||
std::make_shared<QProtobufJsonSerializer>())
|
||||
: new QGrpcSerializationFormatPrivate(format == SerializationFormat::Protobuf
|
||||
? "proto"
|
||||
: "",
|
||||
std::make_shared<QProtobufSerializer>()))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -73,29 +75,20 @@ QGrpcSerializationFormat::~QGrpcSerializationFormat() = default;
|
|||
QGrpcSerializationFormat::QGrpcSerializationFormat(QByteArrayView suffix,
|
||||
std::shared_ptr<QAbstractProtobufSerializer>
|
||||
serializer)
|
||||
: dPtr(new QGrpcSerializationFormatPrivate(suffix, std::move(serializer)),
|
||||
dPtrDeleter)
|
||||
: d_ptr(new QGrpcSerializationFormatPrivate(suffix, std::move(serializer)))
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a copy of \a other.
|
||||
*/
|
||||
QGrpcSerializationFormat::QGrpcSerializationFormat(const QGrpcSerializationFormat &other)
|
||||
: dPtr(new QGrpcSerializationFormatPrivate(*other.dPtr),
|
||||
dPtrDeleter)
|
||||
{
|
||||
}
|
||||
QGrpcSerializationFormat::QGrpcSerializationFormat(const QGrpcSerializationFormat &other) = default;
|
||||
|
||||
/*!
|
||||
Assigns the \a other QGrpcSerializationFormat object to this one.
|
||||
*/
|
||||
QGrpcSerializationFormat &QGrpcSerializationFormat::operator=(const QGrpcSerializationFormat &other)
|
||||
{
|
||||
if (this != &other)
|
||||
*dPtr = *other.dPtr;
|
||||
return *this;
|
||||
}
|
||||
QGrpcSerializationFormat &
|
||||
QGrpcSerializationFormat::operator=(const QGrpcSerializationFormat &other) = default;
|
||||
|
||||
/*!
|
||||
\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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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.
|
||||
*/
|
||||
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
|
||||
{
|
||||
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
|
||||
|
|
|
|||
|
|
@ -8,14 +8,19 @@
|
|||
#include <QtGrpc/qtgrpcnamespace.h>
|
||||
|
||||
#include <QtCore/qbytearrayview.h>
|
||||
#include <QtCore/qshareddata.h>
|
||||
#include <QtCore/qtclasshelpermacros.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QGrpcSerializationFormatPrivate;
|
||||
class QAbstractProtobufSerializer;
|
||||
class QDebug;
|
||||
class QVariant;
|
||||
|
||||
class QGrpcSerializationFormatPrivate;
|
||||
QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QGrpcSerializationFormatPrivate, Q_GRPC_EXPORT)
|
||||
|
||||
class QGrpcSerializationFormat final
|
||||
{
|
||||
|
|
@ -29,19 +34,40 @@ public:
|
|||
Q_GRPC_EXPORT QGrpcSerializationFormat &operator=(const QGrpcSerializationFormat &);
|
||||
|
||||
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>
|
||||
serializer() const noexcept;
|
||||
|
||||
private:
|
||||
std::unique_ptr<QGrpcSerializationFormatPrivate, void (*)(QGrpcSerializationFormatPrivate *)>
|
||||
dPtr;
|
||||
QExplicitlySharedDataPointer<QGrpcSerializationFormatPrivate> d_ptr;
|
||||
|
||||
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
|
||||
|
||||
#endif // QGRPCSERIALIZATIONFORMAT_H
|
||||
|
|
|
|||
|
|
@ -1,30 +1,29 @@
|
|||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include <QObject>
|
||||
#include <QtTest/QTest>
|
||||
|
||||
#include <QtGrpc/qgrpcserializationformat.h>
|
||||
|
||||
#include <QtProtobuf/qprotobufjsonserializer.h>
|
||||
#include <QtProtobuf/qprotobufserializer.h>
|
||||
|
||||
#include <memory>
|
||||
#include <QtTest/qtest.h>
|
||||
|
||||
using namespace QtGrpc;
|
||||
|
||||
class QGrpcSerializationFormatTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QGrpcSerializationFormatTest() { }
|
||||
|
||||
private Q_SLOTS:
|
||||
void constructEmbedded();
|
||||
void constructCustom();
|
||||
void copyMove();
|
||||
void constructFromEnum() const;
|
||||
void constructCustom() const;
|
||||
void hasSpecialMemberFunctions() const;
|
||||
void hasImplicitQVariant() const;
|
||||
void hasMemberSwap() const;
|
||||
void streamsToDebug() const;
|
||||
};
|
||||
|
||||
void QGrpcSerializationFormatTest::constructEmbedded()
|
||||
void QGrpcSerializationFormatTest::constructFromEnum() const
|
||||
{
|
||||
QGrpcSerializationFormat defaultFormat = SerializationFormat::Default;
|
||||
QCOMPARE(defaultFormat.suffix(), "");
|
||||
|
|
@ -39,14 +38,14 @@ void QGrpcSerializationFormatTest::constructEmbedded()
|
|||
QVERIFY(dynamic_cast<QProtobufSerializer *>(protobufFormat.serializer().get()) != nullptr);
|
||||
}
|
||||
|
||||
void QGrpcSerializationFormatTest::constructCustom()
|
||||
void QGrpcSerializationFormatTest::constructCustom() const
|
||||
{
|
||||
QGrpcSerializationFormat customFormat("test", std::make_shared<QProtobufJsonSerializer>());
|
||||
QCOMPARE(customFormat.suffix(), "test");
|
||||
QVERIFY(dynamic_cast<QProtobufJsonSerializer *>(customFormat.serializer().get()) != nullptr);
|
||||
}
|
||||
|
||||
void QGrpcSerializationFormatTest::copyMove()
|
||||
void QGrpcSerializationFormatTest::hasSpecialMemberFunctions() const
|
||||
{
|
||||
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)
|
||||
|
||||
#include "tst_qgrpcserializationformat.moc"
|
||||
|
|
|
|||
Loading…
Reference in New Issue