Make QProtobufSerializer and QProtobufJsonSerializer non-stateless

QtProtobuf serializers now hold states that makes them mutable during
the serializing process.
QProtobufSerializer now iterate over the data received from wire
implicitly, without exposing QProtobufSelfcheckIterator to public API.
QProtobufJsonSerializer uses the single QJsonDocument to construct the
full JSON data and parse the data received from wire.

[ChangeLog][QtProtobuf] The QtProtobufBaseSerializer API is changed.
Remove the QProtobufSerializer specifics.
[ChangeLog][QtProtobuf] QProtobufSelfcheckIterator is not a part of
public API anymore.
[ChangeLog][QtProtobufWellKnownTypes][Any] Any type API is changed.
'as' and 'fromMessage' functions not accept the pointer to a
serializer.

Pick-to: 6.7
Task-number: QTBUG-113731
Change-Id: Iddf25bed690e2299c017b3894fc8a3d9306a22b9
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
This commit is contained in:
Alexey Edelev 2023-12-08 12:02:21 +01:00
parent c01245a1d6
commit e3abfef0cd
17 changed files with 781 additions and 893 deletions

View File

@ -9,7 +9,7 @@ qt_internal_add_module(Protobuf
qprotobufmessage.cpp qprotobufmessage.h qprotobufmessage_p.h
qprotobuflazymessagepointer.h
qprotobufobject.h
qprotobufselfcheckiterator.h
qprotobufselfcheckiterator_p.h
qprotobufserializer.cpp qprotobufserializer.h qprotobufserializer_p.h
qprotobufjsonserializer.cpp qprotobufjsonserializer.h
qtprotobuflogging.cpp qtprotobuflogging_p.h

View File

@ -13,9 +13,12 @@
QT_BEGIN_NAMESPACE
namespace QtProtobuf {
class Any;
}
class Q_PROTOBUF_EXPORT QAbstractProtobufSerializer
{
public:
enum DeserializationError {
NoError,
@ -69,6 +72,8 @@ private:
bool doDeserialize(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QByteArrayView data) const;
friend class QtProtobuf::Any;
};
QT_END_NAMESPACE

View File

@ -27,12 +27,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
Destroys this QProtobufBaseSerializer.
*/
QProtobufBaseSerializer::~QProtobufBaseSerializer() = default;
/*!
\fn QByteArray QProtobufBaseSerializer::serializeObject(const QProtobufMessage *message,
\fn void QProtobufBaseSerializer::serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const
@ -40,19 +35,115 @@ QProtobufBaseSerializer::~QProtobufBaseSerializer() = default;
with defined \a ordering and \a fieldInfo, that is recognized
like an object, into a QByteArray. \a message must not be \nullptr.
\sa deserializeObject()
You should not call this function directly.
\sa QProtobufBaseSerializer::deserializeObject()
*/
/*!
\fn bool QProtobufBaseSerializer::deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const
This function deserializes a registered Protobuf message \a message
with defined \a ordering from the \a it iterator. \a message must not be \nullptr.
with defined \a ordering. \a message must not be \nullptr.
Returns \c true if deserialization was successful, otherwise \c false.
\sa serializeObject()
You should not call this function directly.
\sa QProtobufBaseSerializer::serializeObject()
*/
/*!
\fn void QProtobufBaseSerializer::serializeListObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo
&fieldInfo) const
This function serializes \a message as part of a list of messages one by one
with \a ordering and \a fieldInfo.
You should not call this function directly.
\sa QProtobufBaseSerializer::deserializeListObject()
*/
/*!
\fn bool QProtobufBaseSerializer::deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const
This function deserializes an \a message from byte stream as part of list property, with
the associated message \a ordering from a wire.
Returns \c true if deserialization was successful, otherwise \c false.
You should not call this function directly.
\sa QProtobufBaseSerializer::serializeListObject()
*/
/*!
\fn void QProtobufBaseSerializer::serializeMapPair(const QVariant &key, const QVariant &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const
This function serializes pair of \a key and \a value, that belong as a protobuf map record,
according to \a fieldInfo.
You should not call this function directly.
\sa QProtobufBaseSerializer::deserializeMapPair()
*/
/*!
\fn bool QProtobufBaseSerializer::deserializeMapPair(QVariant &key, QVariant &value) const
This function deserializes a pair of \a key and \a value from a wire.
Returns \c true if deserialization was successful, otherwise \c false.
You should not call this function directly.
\sa QProtobufBaseSerializer::serializeMapPair()
*/
/*!
\fn void QProtobufBaseSerializer::serializeEnum(QtProtobuf::int64 value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const
This function serializes \a value from enum associated with property \a fieldInfo.
You should not call this function directly.
\sa QProtobufBaseSerializer::deserializeEnum()
*/
/*!
\fn bool QProtobufBaseSerializer::deserializeEnum(QtProtobuf::int64 &value) const
This function deserializes an enum \a value from a wire.
Returns \c true if deserialization was successful, otherwise \c false.
You should not call this function directly.
\sa QProtobufBaseSerializer::serializeEnum()
*/
/*!
\fn void QProtobufBaseSerializer::serializeEnumList(const QList<QtProtobuf::int64> &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const
This function serializes a list, \a value, for enum list associated with property \a fieldInfo.
You should not call this function directly.
\sa QProtobufBaseSerializer::deserializeEnumList()
*/
/*!
\fn bool QProtobufSerializer::deserializeEnumList(QList<QtProtobuf::int64> &value) const
This function deserializes a list of enum \a value from a wire.
Returns \c true if deserialization was successful, otherwise \c false.
You should not call this function directly.
\sa QProtobufBaseSerializer::serializeEnumList()
*/
/*!

View File

@ -5,7 +5,6 @@
#define QPROTOBUFSBASEERIALIZER_H
#include <QtProtobuf/qabstractprotobufserializer.h>
#include <QtProtobuf/qprotobufselfcheckiterator.h>
#include <QtCore/QList>
#include <QtCore/QMetaObject>
@ -16,58 +15,44 @@ QT_BEGIN_NAMESPACE
class Q_PROTOBUF_EXPORT QProtobufBaseSerializer: public QAbstractProtobufSerializer
{
public:
enum Status {
Serialized = 0,
SerializationInProgress,
SerializationError
};
virtual ~QProtobufBaseSerializer();
virtual QByteArray
virtual void
serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual bool deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
virtual bool
deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const = 0;
virtual QByteArray
serializeListObject(const QList<const QProtobufMessage*> &messageList,
virtual void serializeListObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual Status
const QtProtobufPrivate::QProtobufPropertyOrderingInfo
&fieldInfo) const = 0;
virtual bool
deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const = 0;
virtual QByteArray
serializeMapPair(const QList<QPair<QVariant, QVariant>> &list,
virtual void
serializeMapPair(const QVariant &key, const QVariant &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual Status deserializeMapPair(QVariant &key, QVariant &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
virtual bool deserializeMapPair(QVariant &key, QVariant &value) const = 0;
virtual QByteArray
virtual void
serializeEnum(QtProtobuf::int64 value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual QByteArray
virtual void
serializeEnumList(const QList<QtProtobuf::int64> &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual bool deserializeEnum(QtProtobuf::int64 &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
virtual bool
deserializeEnumList(QList<QtProtobuf::int64> &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
virtual bool deserializeEnum(QtProtobuf::int64 &value) const = 0;
virtual bool deserializeEnumList(QList<QtProtobuf::int64> &value) const = 0;
};
namespace QtProtobufPrivate {
using Serializer = void (*)(const QProtobufBaseSerializer *, const QVariant &,
const QProtobufPropertyOrderingInfo &, QByteArray &);
using Deserializer = void (*)(const QProtobufBaseSerializer *, QProtobufSelfcheckIterator &,
QVariant &);
const QProtobufPropertyOrderingInfo &);
using Deserializer = void (*)(const QProtobufBaseSerializer *, QVariant &);
/*!
\private
@ -90,10 +75,10 @@ extern Q_PROTOBUF_EXPORT void registerHandler(QMetaType type, const Serializatio
template <typename T,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, T>::value, int> = 0>
void serializeObject(const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
const QProtobufPropertyOrderingInfo &fieldInfo)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
buffer.append(serializer->serializeObject(value.value<T *>(), T::propertyOrdering, fieldInfo));
serializer->serializeObject(value.value<T *>(), T::propertyOrdering, fieldInfo);
}
/*!
@ -103,14 +88,12 @@ void serializeObject(const QProtobufBaseSerializer *serializer, const QVariant &
template <typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeList(const QProtobufBaseSerializer *serializer, const QVariant &listValue,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
const QProtobufPropertyOrderingInfo &fieldInfo)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QList<V> objList = listValue.value<QList<V>>();
QList<const QProtobufMessage*> messageList;
for (const auto &value : objList)
messageList.append(&value);
buffer.append(serializer->serializeListObject(messageList, V::propertyOrdering, fieldInfo));
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
for (const auto &value : listValue.value<QList<V>>()) {
serializer->serializeListObject(&value, V::propertyOrdering, fieldInfo);
}
}
/*!
@ -120,17 +103,13 @@ void serializeList(const QProtobufBaseSerializer *serializer, const QVariant &li
template <typename K, typename V,
typename std::enable_if_t<!std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeMap(const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
const QProtobufPropertyOrderingInfo &fieldInfo)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QHash<K, V> original = value.value<QHash<K, V>>();
QList<QPair<QVariant, QVariant>> variantContainer;
for (const auto &[k, v] : original.asKeyValueRange()) {
variantContainer.append(qMakePair(QVariant::fromValue<K>(k),
QVariant::fromValue<V>(v)));
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
for (const auto &[k, v] : value.value<QHash<K, V>>().asKeyValueRange()) {
serializer->serializeMapPair(QVariant::fromValue<K>(k), QVariant::fromValue<V>(v),
fieldInfo);
}
buffer.append(serializer->serializeMapPair(variantContainer, fieldInfo));
}
/*!
@ -141,17 +120,13 @@ void serializeMap(const QProtobufBaseSerializer *serializer, const QVariant &val
template <typename K, typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeMap(const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
const QProtobufPropertyOrderingInfo &fieldInfo)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QHash<K, V> original = value.value<QHash<K, V>>();
QList<QPair<QVariant, QVariant>> variantContainer;
for (const auto &[k, v] : original.asKeyValueRange()) {
variantContainer.append(qMakePair(QVariant::fromValue<K>(k),
QVariant::fromValue<V *>(&v)));
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
for (const auto &[k, v] : value.value<QHash<K, V>>().asKeyValueRange()) {
serializer->serializeMapPair(QVariant::fromValue<K>(k), QVariant::fromValue<V *>(&v),
fieldInfo);
}
buffer.append(serializer->serializeMapPair(variantContainer, fieldInfo));
}
/*!
@ -160,10 +135,10 @@ void serializeMap(const QProtobufBaseSerializer *serializer, const QVariant &val
*/
template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void serializeEnum(const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
const QProtobufPropertyOrderingInfo &fieldInfo)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
buffer.append(serializer->serializeEnum(QtProtobuf::int64(value.value<T>()), fieldInfo));
serializer->serializeEnum(QtProtobuf::int64(value.value<T>()), fieldInfo);
}
/*!
@ -172,14 +147,14 @@ void serializeEnum(const QProtobufBaseSerializer *serializer, const QVariant &va
*/
template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void serializeEnumList(const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
const QProtobufPropertyOrderingInfo &fieldInfo)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QList<QtProtobuf::int64> intList;
for (auto enumValue : value.value<QList<T>>()) {
intList.append(QtProtobuf::int64(enumValue));
}
buffer.append(serializer->serializeEnumList(intList, fieldInfo));
serializer->serializeEnumList(intList, fieldInfo);
}
/*!
@ -188,8 +163,7 @@ void serializeEnumList(const QProtobufBaseSerializer *serializer, const QVariant
*/
template <typename T,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, T>::value, int> = 0>
void deserializeObject(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &to)
void deserializeObject(const QProtobufBaseSerializer *serializer, QVariant &to)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
Q_ASSERT_X(to.isNull() || to.metaType() == QMetaType::fromType<T *>(),
@ -201,7 +175,7 @@ void deserializeObject(const QProtobufBaseSerializer *serializer, QProtobufSelfc
value = new T;
to = QVariant::fromValue<T *>(value);
}
serializer->deserializeObject(value, T::propertyOrdering, it);
serializer->deserializeObject(value, T::propertyOrdering);
}
/*!
@ -210,19 +184,15 @@ void deserializeObject(const QProtobufBaseSerializer *serializer, QProtobufSelfc
*/
template <typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeList(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
void deserializeList(const QProtobufBaseSerializer *serializer, QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
V newValue;
QProtobufBaseSerializer::Status result = QProtobufBaseSerializer::SerializationError;
do {
result = serializer->deserializeListObject(&newValue, V::propertyOrdering, it);
serializer->deserializeListObject(&newValue, V::propertyOrdering);
QList<V> list = previous.value<QList<V>>();
list.append(newValue);
previous.setValue(list);
} while (result == QProtobufBaseSerializer::SerializationInProgress);
}
/*!
@ -232,8 +202,7 @@ void deserializeList(const QProtobufBaseSerializer *serializer, QProtobufSelfche
*/
template <typename K, typename V,
typename std::enable_if_t<!std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
void deserializeMap(const QProtobufBaseSerializer *serializer, QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
@ -241,7 +210,7 @@ void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfchec
QVariant key = QVariant::fromValue<K>(K());
QVariant value = QVariant::fromValue<V>(V());
if (serializer->deserializeMapPair(key, value, it) == QProtobufBaseSerializer::Serialized) {
if (serializer->deserializeMapPair(key, value)) {
out[key.value<K>()] = value.value<V>();
previous = QVariant::fromValue<QHash<K, V>>(out);
}
@ -255,8 +224,7 @@ void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfchec
*/
template <typename K, typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
void deserializeMap(const QProtobufBaseSerializer *serializer, QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
@ -264,7 +232,7 @@ void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfchec
QVariant key = QVariant::fromValue<K>(K());
QVariant value = QVariant::fromValue<V *>(nullptr);
if (serializer->deserializeMapPair(key, value, it) == QProtobufBaseSerializer::Serialized) {
if (serializer->deserializeMapPair(key, value)) {
const auto valuePtr = value.value<V *>();
out[key.value<K>()] = valuePtr ? *valuePtr : V();
previous = QVariant::fromValue<QHash<K, V>>(out);
@ -277,12 +245,11 @@ void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfchec
\brief default deserializer template for enum type T
*/
template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void deserializeEnum(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &to)
void deserializeEnum(const QProtobufBaseSerializer *serializer, QVariant &to)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QtProtobuf::int64 intValue;
if (serializer->deserializeEnum(intValue, it))
if (serializer->deserializeEnum(intValue))
to = QVariant::fromValue<T>(static_cast<T>(intValue._t));
}
@ -292,12 +259,11 @@ void deserializeEnum(const QProtobufBaseSerializer *serializer, QProtobufSelfche
\brief default deserializer template for enumList type T
*/
template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void deserializeEnumList(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
void deserializeEnumList(const QProtobufBaseSerializer *serializer, QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QList<QtProtobuf::int64> intList;
if (!serializer->deserializeEnumList(intList, it))
if (!serializer->deserializeEnumList(intList))
return;
QList<T> enumList = previous.value<QList<T>>();
for (auto intValue : intList)

View File

@ -54,7 +54,7 @@ class QProtobufJsonSerializerPrivate final
Q_DISABLE_COPY_MOVE(QProtobufJsonSerializerPrivate)
public:
using Serializer = std::function<QByteArray(const QVariant&)>;
using Serializer = std::function<QJsonValue(const QVariant &)>;
using Deserializer = std::function<QVariant(const QJsonValue&, bool &ok)>;
struct SerializationHandlers {
@ -67,126 +67,115 @@ public:
// TBD Replace std::unordered_map to QHash
using SerializerRegistry = std::unordered_map<int/*metatypeid*/, SerializationHandlers>;
static QByteArray serializeFloat(const QVariant &propertyValue)
template <typename T>
static QJsonValue serializeVarint(const QVariant &propertyValue)
{
bool ok = false;
float value = propertyValue.toFloat(&ok);
if (!ok || qIsNaN(value)) {
return QByteArray("NaN");
}
return QByteArray::number(value, 'g', 7);
return QJsonValue(qint64(propertyValue.value<T>()));
}
static QByteArray serializeDouble(const QVariant &propertyValue)
template <typename T>
static QJsonValue serializeInt64Int(const QVariant &propertyValue)
{
bool ok = false;
double value = propertyValue.toDouble(&ok);
if (!ok || qIsNaN(value)) {
return QByteArray("NaN");
}
return QByteArray::number(value, 'g', 14);
return QJsonValue(QString::number(propertyValue.value<T>()));
}
static QByteArray serializeString(const QVariant &propertyValue)
static QJsonValue serializeFloat(const QVariant &propertyValue)
{
return '"' + propertyValue.toString().toUtf8() + '"';
// TODO: this is weak approach to no have some precision loss. Not sure why this happens,
// should be converted without the conversion to string.
return QJsonValue(QString::number(propertyValue.toFloat()).toDouble());
}
static QByteArray serializeBytes(const QVariant &propertyValue) {
return QByteArray("\"") + propertyValue.toByteArray().toBase64() + "\"";
static QJsonValue serializeDouble(const QVariant &propertyValue)
{
return QJsonValue(propertyValue.toDouble());
}
static QJsonValue serializeString(const QVariant &propertyValue)
{
return QJsonValue(propertyValue.toString());
}
static QJsonValue serializeBytes(const QVariant &propertyValue)
{
return QJsonValue(QString::fromUtf8(propertyValue.toByteArray().toBase64()));
}
template <typename L>
static QByteArray serializeList(const QVariant &propertyValue)
static QJsonValue serializeList(const QVariant &propertyValue)
{
QJsonArray arr;
L listValue = propertyValue.value<L>();
QByteArray result("[");
for (auto value : listValue) {
result += QByteArray::number(value) + ",";
for (const auto &value : listValue) {
arr.append(QJsonValue(qint64(value)));
}
//Remove trailing `,`
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
return QJsonValue(arr);
}
static QByteArray serializeBoolList(const QVariant &propertyValue)
template <typename L>
static QJsonValue serializeInt64bitList(const QVariant &propertyValue)
{
QJsonArray arr;
L listValue = propertyValue.value<L>();
for (const auto &value : listValue) {
arr.append(QJsonValue(QString::number(value)));
}
return QJsonValue(arr);
}
static QJsonValue serializeBoolList(const QVariant &propertyValue)
{
QJsonArray arr;
QtProtobuf::boolList listValue = propertyValue.value<QtProtobuf::boolList>();
QByteArray result("[");
for (auto value : listValue) {
if (value)
result += QByteArray("true,");
else
result += QByteArray("false,");
for (const auto &value : listValue) {
arr.append(QJsonValue(value));
}
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
return QJsonValue(arr);
}
static QByteArray serializeFloatList(const QVariant &propertyValue)
static QJsonValue serializeFloatList(const QVariant &propertyValue)
{
QJsonArray arr;
QtProtobuf::floatList listValue = propertyValue.value<QtProtobuf::floatList>();
QByteArray result("[");
for (auto value : listValue) {
if (qIsNaN(value))
return QByteArray("NaN");
result += QByteArray::number(value, 'g', 7) + ",";
for (const auto &value : listValue) {
// TODO: this is weak approach to not have some precision loss. Not sure why this
// happens, should be converted without the conversion to string.
arr.append(QJsonValue(QString::number(value).toDouble()));
}
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
return QJsonValue(arr);
}
static QByteArray serializeStringList(const QVariant &propertyValue)
static QJsonValue serializeStringList(const QVariant &propertyValue)
{
QJsonArray arr;
QStringList listValue = propertyValue.value<QStringList>();
QByteArray result("[");
for (auto value : listValue) {
result += QByteArray("\"") + value.toUtf8() + "\",";
}
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
for (const auto &value : listValue) {
arr.append(QJsonValue(value));
}
static QByteArray serializeBytesList(const QVariant &propertyValue)
return QJsonValue(arr);
}
static QJsonValue serializeBytesList(const QVariant &propertyValue)
{
QByteArrayList listValue = propertyValue.value<QByteArrayList>();
QByteArray result("[");
for (auto value : listValue) {
result += QByteArray("\"") + value.toBase64() + "\",";
}
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
QJsonArray arr;
for (const auto &value : listValue) {
arr.append(QJsonValue(QString::fromUtf8(value.toBase64())));
}
static QByteArray serializeDoubleList(const QVariant &propertyValue)
return QJsonValue(arr);
}
static QJsonValue serializeDoubleList(const QVariant &propertyValue)
{
QtProtobuf::doubleList listValue = propertyValue.value<QtProtobuf::doubleList>();
QByteArray result("[");
for (auto value : listValue) {
if (qIsNaN(value))
return QByteArray("NaN");
result += QByteArray::number(value, 'g', 14) + ",";
QJsonArray arr;
for (const auto &value : listValue) {
arr.append(QJsonValue(value));
}
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
return QJsonValue(arr);
}
QProtobufJsonSerializerPrivate(QProtobufJsonSerializer *q)
@ -194,26 +183,38 @@ public:
{
// TBD Change to assigning the result of a lambda to a static variable
if (handlers.empty()) {
handlers[qMetaTypeId<QtProtobuf::int32>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt32};
handlers[qMetaTypeId<QtProtobuf::sfixed32>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt32};
handlers[qMetaTypeId<QtProtobuf::int32>()] = {
QProtobufJsonSerializerPrivate::serializeVarint<QtProtobuf::int32>,
QProtobufJsonSerializerPrivate::deserializeInt32
};
handlers[qMetaTypeId<QtProtobuf::sfixed32>()] = {
QProtobufJsonSerializerPrivate::serializeVarint<QtProtobuf::sfixed32>,
QProtobufJsonSerializerPrivate::deserializeInt32
};
handlers[qMetaTypeId<QtProtobuf::sint32>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt32};
handlers[qMetaTypeId<QtProtobuf::sint64>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt64};
handlers[qMetaTypeId<QtProtobuf::int64>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt64};
handlers[qMetaTypeId<QtProtobuf::sfixed64>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt64};
= {serializeInt64Int<QtProtobuf::sint64>, QProtobufJsonSerializerPrivate::deserializeInt64};
handlers[qMetaTypeId<QtProtobuf::int64>()] = {
serializeInt64Int<QtProtobuf::int64>,
QProtobufJsonSerializerPrivate::deserializeInt64
};
handlers[qMetaTypeId<QtProtobuf::sfixed64>()] = {
serializeInt64Int<QtProtobuf::sfixed64>,
QProtobufJsonSerializerPrivate::deserializeInt64
};
handlers[qMetaTypeId<QtProtobuf::uint32>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeUInt32};
handlers[qMetaTypeId<QtProtobuf::fixed32>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeUInt32};
handlers[qMetaTypeId<QtProtobuf::fixed32>()] = {
QProtobufJsonSerializerPrivate::serializeVarint<QtProtobuf::fixed32>,
QProtobufJsonSerializerPrivate::deserializeUInt32
};
handlers[qMetaTypeId<QtProtobuf::uint64>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeUInt64};
handlers[qMetaTypeId<QtProtobuf::fixed64>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeUInt64};
= {serializeInt64Int<QtProtobuf::uint64>, QProtobufJsonSerializerPrivate::deserializeUInt64};
handlers[qMetaTypeId<QtProtobuf::fixed64>()] = {
serializeInt64Int<QtProtobuf::fixed64>,
QProtobufJsonSerializerPrivate::deserializeUInt64
};
handlers[qMetaTypeId<bool>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeBool};
handlers[QMetaType::Float] = {QProtobufJsonSerializerPrivate::serializeFloat,
@ -232,33 +233,38 @@ public:
handlers[qMetaTypeId<QtProtobuf::int32List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::int32List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::int32>};
handlers[qMetaTypeId<QtProtobuf::int64List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::int64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::int64>};
handlers[qMetaTypeId<QtProtobuf::int64List>()] = {
QProtobufJsonSerializerPrivate::serializeInt64bitList<QtProtobuf::int64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::int64>
};
handlers[qMetaTypeId<QtProtobuf::sint32List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::sint32List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::sint32>};
handlers[qMetaTypeId<QtProtobuf::sint64List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::sint64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::sint64>};
handlers[qMetaTypeId<QtProtobuf::sint64List>()] = {
QProtobufJsonSerializerPrivate::serializeInt64bitList<QtProtobuf::sint64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::sint64>
};
handlers[qMetaTypeId<QtProtobuf::uint32List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::uint32List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::uint32>};
handlers[qMetaTypeId<QtProtobuf::uint64List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::uint64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::uint64>};
handlers[qMetaTypeId<QtProtobuf::uint64List>()] = {
QProtobufJsonSerializerPrivate::serializeInt64bitList<QtProtobuf::uint64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::uint64>
};
handlers[qMetaTypeId<QtProtobuf::fixed32List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::fixed32List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::fixed32>};
handlers[qMetaTypeId<QtProtobuf::fixed64List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::fixed64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::fixed64>};
handlers[qMetaTypeId<QtProtobuf::fixed64List>()] = {
QProtobufJsonSerializerPrivate::serializeInt64bitList<QtProtobuf::fixed64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::fixed64>
};
handlers[qMetaTypeId<QtProtobuf::sfixed32List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::sfixed32List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::sfixed32>};
handlers[qMetaTypeId<QtProtobuf::sfixed64List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::sfixed64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::sfixed64>};
handlers[qMetaTypeId<QtProtobuf::sfixed64List>()] = {
QProtobufJsonSerializerPrivate::serializeInt64bitList<QtProtobuf::sfixed64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::sfixed64>
};
handlers[qMetaTypeId<QtProtobuf::floatList>()]
= {QProtobufJsonSerializerPrivate::serializeFloatList,
QProtobufJsonSerializerPrivate::deserializeList<float>};
@ -275,42 +281,31 @@ public:
}
~QProtobufJsonSerializerPrivate() = default;
QByteArray serializeValue(const QVariant &propertyValue,
void serializeProperty(const QVariant &propertyValue,
const QProtobufPropertyOrderingInfo &fieldInfo)
{
QByteArray buffer;
QMetaType metaType = propertyValue.metaType();
auto userType = propertyValue.userType();
if (metaType.id() == QMetaType::UnknownType) {
return {};
}
if (metaType.id() == QMetaType::UnknownType)
return;
auto handler = QtProtobufPrivate::findHandler(metaType);
if (handler.serializer) {
handler.serializer(qPtr, propertyValue, fieldInfo, buffer);
handler.serializer(qPtr, propertyValue, fieldInfo);
} else {
QJsonObject activeObject = activeValue.toObject();
auto handler = handlers.find(userType);
if (handler != handlers.end() && handler->second.serializer) {
buffer += handler->second.serializer(propertyValue);
} else {
buffer += propertyValue.toString().toUtf8();
activeObject.insert(fieldInfo.getJsonName().toString(),
handler != handlers.end() && handler->second.serializer
? handler->second.serializer(propertyValue)
: QJsonValue::fromVariant(propertyValue));
activeValue = activeObject;
}
}
return buffer;
}
QByteArray serializeProperty(const QVariant &propertyValue,
const QProtobufPropertyOrderingInfo &fieldInfo)
void serializeObject(const QProtobufMessage *message, const QProtobufPropertyOrdering &ordering)
{
return QByteArray("\"")
+ QByteArrayView(fieldInfo.getJsonName())
+ QByteArray("\":") + serializeValue(propertyValue, fieldInfo);
}
QByteArray serializeObject(const QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering)
{
QByteArray result = "{";
// if a message is not initialized, just return empty { }
if (message) {
for (int index = 0; index < ordering.fieldCount(); ++index) {
@ -320,13 +315,9 @@ public:
"fieldIndex is out of range");
QProtobufPropertyOrderingInfo fieldInfo(ordering, index);
QVariant propertyValue = message->property(fieldInfo);
result.append(serializeProperty(propertyValue, fieldInfo));
result.append(",");
serializeProperty(propertyValue, fieldInfo);
}
result.chop(1);
}
result.append("}");
return result;
}
static QVariant deserializeInt32(const QJsonValue &value, bool &ok)
@ -442,47 +433,31 @@ public:
return QVariant::fromValue(list);
}
QVariant deserializeValue(const QMetaType &metaType,
QProtobufSelfcheckIterator &it,
const QJsonValue &value,
bool &ok)
QVariant deserializeValue(QVariant propertyData, bool &ok)
{
QVariant result;
auto handler = QtProtobufPrivate::findHandler(metaType);
auto handler = QtProtobufPrivate::findHandler(propertyData.metaType());
if (handler.deserializer) {
handler.deserializer(qPtr, it, result);
ok = result.isValid();
handler.deserializer(qPtr, propertyData);
ok = propertyData.isValid();
} else {
auto handler = handlers.find(metaType.id());
int userType = propertyData.userType();
auto handler = handlers.find(propertyData.userType());
if (handler != handlers.end() && handler->second.deserializer) {
result = handler->second.deserializer(value, ok);
propertyData = handler->second.deserializer(activeValue, ok);
activeValue = {};
} else {
QString error = QString::fromUtf8("No deserializer is registered for value %1")
.arg(QString::fromUtf8(metaType.name()));
setDeserializationError(
QAbstractProtobufSerializer::NoDeserializerError,
QCoreApplication::translate("QtProtobuf",
error.toUtf8().data()));
setDeserializationError(QAbstractProtobufSerializer::NoDeserializerError,
QCoreApplication::
translate("QtProtobuf",
"No deserializer is registered for type %1").arg(userType));
}
}
return result;
return propertyData;
}
bool deserializeObject(QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering,
QByteArrayView data)
bool deserializeObject(QProtobufMessage *message, const QProtobufPropertyOrdering &ordering)
{
auto it = QProtobufSelfcheckIterator::fromView(data);
Q_ASSERT(it.isValid() && it.bytesLeft() > 0);
bool ok = false;
// TBD Try fromJson(QBAView) instead of current variant
QJsonDocument document
= QJsonDocument::fromJson(QByteArray(data.data(), static_cast<size_t>(data.size())));
if (!document.isObject())
return false;
std::map<QString, QProtobufPropertyOrderingInfo> msgContainer; // map<key, fieldInfo>
for (int index = 0; index < ordering.fieldCount(); ++index) {
int fieldIndex = ordering.getFieldNumber(index);
@ -492,35 +467,33 @@ public:
msgContainer.insert(std::pair<QString, QProtobufPropertyOrderingInfo>(key, fieldInfo));
}
QByteArray object;
if (!activeValue.isObject()) {
return false;
}
QJsonObject activeObject = activeValue.toObject();
// Go through QJSON doc and find keys that are presented in msgContainer
QJsonObject obj = document.object();
for (auto &key : obj.keys()) {
QJsonValue jsonValue = obj.value(key);
auto iter = msgContainer.find(key);
for (auto &key : activeObject.keys()) {
std::map<QString, QProtobufPropertyOrderingInfo>::iterator iter = msgContainer
.find(key);
if (iter != msgContainer.end()) {
QVariant newPropertyValue = message->property(iter->second);
// Complex message case; move iterator to the deserializing array
if (jsonValue.isArray()) {
QJsonArray array = jsonValue.toArray();
object = QJsonDocument(array).toJson();
it = QProtobufSelfcheckIterator::fromView(object);
auto store = activeValue;
activeValue = activeObject.value(key);
while (!activeValue.isNull()) {
newPropertyValue = deserializeValue(newPropertyValue, ok);
}
// Complex message case; move iterator to the deserializing object
if (jsonValue.isObject()) {
object = QJsonDocument(jsonValue.toObject()).toJson();
it = QProtobufSelfcheckIterator::fromView(object);
}
newPropertyValue = deserializeValue(newPropertyValue.metaType(),
it,
jsonValue,
ok);
activeValue = store;
if (ok) {
message->setProperty(iter->second, std::move(newPropertyValue));
message->setProperty(iter->second, newPropertyValue);
}
}
}
// Once all keys are deserialized we assume that activeValue is empty, nothing left
// to deserialize
activeValue = {};
return ok;
}
@ -543,7 +516,7 @@ public:
QAbstractProtobufSerializer::DeserializationError deserializationError =
QAbstractProtobufSerializer::NoDeserializerError;
QString deserializationErrorString;
QJsonArray activeArray;
QJsonValue activeValue;
private:
static SerializerRegistry handlers;
@ -580,7 +553,12 @@ QByteArray
QProtobufJsonSerializer::serializeMessage(const QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering) const
{
return d_ptr->serializeObject(message, ordering);
d_ptr->activeValue = QJsonObject();
d_ptr->serializeObject(message, ordering);
QJsonDocument doc;
doc.setObject(d_ptr->activeValue.toObject());
d_ptr->activeValue = QJsonObject();
return doc.toJson(QJsonDocument::Compact);
}
bool QProtobufJsonSerializer::deserializeMessage(QProtobufMessage *message,
@ -588,92 +566,83 @@ bool QProtobufJsonSerializer::deserializeMessage(QProtobufMessage *message,
QByteArrayView data) const
{
d_ptr->clearError();
auto it = QProtobufSelfcheckIterator::fromView(data);
if (!d_ptr->deserializeObject(message, ordering, data))
QJsonParseError err;
auto document = QJsonDocument::fromJson(data.toByteArray(), &err);
if (err.error != QJsonParseError::NoError)
return false;
if (!it.isValid())
d_ptr->setUnexpectedEndOfStreamError();
return it.isValid();
if (!document.isObject())
return false;
d_ptr->activeValue = document.object();
return d_ptr->deserializeObject(message, ordering);
}
QByteArray
QProtobufJsonSerializer::serializeObject(const QProtobufMessage *message,
void QProtobufJsonSerializer::serializeObject(const QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
Q_UNUSED(fieldInfo);
return serializeMessage(message, ordering);
auto store = d_ptr->activeValue.toObject();
d_ptr->activeValue = QJsonObject();
d_ptr->serializeObject(message, ordering);
store.insert(fieldInfo.getJsonName().toString(), d_ptr->activeValue);
d_ptr->activeValue = store;
}
QByteArray
QProtobufJsonSerializer::serializeListObject(const QList<const QProtobufMessage*> &messageList,
void QProtobufJsonSerializer::serializeListObject(const QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering,
const QProtobufPropertyOrderingInfo &fieldInfo) const
const QProtobufPropertyOrderingInfo &fieldInfo)
const
{
QByteArray result("[");
for (auto message : messageList) {
result.append(serializeObject(message, ordering, fieldInfo) + ",");
}
if (messageList.size() > 0) {
result.chop(1);
}
result.append("]");
return result;
auto fieldName = fieldInfo.getJsonName().toString();
auto store = d_ptr->activeValue.toObject();
QJsonArray newArrayVal = store.value(fieldName).toArray();
d_ptr->activeValue = {};
d_ptr->serializeObject(message, ordering);
newArrayVal.append(d_ptr->activeValue);
store.insert(fieldName, newArrayVal);
d_ptr->activeValue = store;
}
bool QProtobufJsonSerializer::deserializeObject(QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering,
QProtobufSelfcheckIterator &it) const
const QProtobufPropertyOrdering &ordering) const
{
return deserializeMessage(message, ordering, it.data());
return d_ptr->deserializeObject(message, ordering);
}
QProtobufBaseSerializer::Status
QProtobufJsonSerializer::deserializeListObject(QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering,
QProtobufSelfcheckIterator &it) const
bool QProtobufJsonSerializer::deserializeListObject(QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering) const
{
if (d_ptr->activeArray.empty()) {
QJsonDocument doc = QJsonDocument::fromJson(QByteArray(it.data(), it.bytesLeft()));
if (doc.isArray())
d_ptr->activeArray = doc.array();
QJsonArray array = d_ptr->activeValue.toArray();
if (array.isEmpty()) {
d_ptr->activeValue = {};
return false;
}
auto val = array.takeAt(0);
bool result = false;
if (val.isObject()) {
d_ptr->activeValue = val;
deserializeObject(message, ordering);
result = true;
}
if (!array.isEmpty())
d_ptr->activeValue = array;
else
return QProtobufBaseSerializer::SerializationError;
}
d_ptr->activeValue = {};
// doc.array() is empty
if (d_ptr->activeArray.empty())
return QProtobufBaseSerializer::SerializationError;
const QJsonValue &element = d_ptr->activeArray.takeAt(0);
if (element.isObject()) {
auto newIt
= QProtobufSelfcheckIterator::fromView(QJsonDocument(element.toObject()).toJson());
bool result = deserializeObject(message, ordering, newIt);
if (!d_ptr->activeArray.empty()) {
return QProtobufBaseSerializer::SerializationInProgress;
} else {
return result ? QProtobufBaseSerializer::Serialized
: QProtobufBaseSerializer::SerializationError;
}
}
return QProtobufBaseSerializer::SerializationError;
}
QByteArray QProtobufJsonSerializer::serializeMapPair(const QList<QPair<QVariant, QVariant>> &list,
const QProtobufPropertyOrderingInfo &fieldInfo
) const
{
Q_UNUSED(fieldInfo);
QByteArray result;
for (auto element: list) {
const QVariant &key = element.first;
qProtoWarning() << "Map pair serialization will be done soon:" << key << element.second;
}
return result;
}
void QProtobufJsonSerializer::serializeMapPair(const QVariant &key, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
Q_UNUSED(fieldInfo);
QByteArray result;
qProtoWarning() << "Map pair serialization will be done soon:" << key << value;
}
QT_END_NAMESPACE

View File

@ -10,6 +10,8 @@
#include <QtCore/QMetaObject>
#include <memory>
QT_BEGIN_NAMESPACE
class QProtobufJsonSerializerPrivate;
@ -24,6 +26,7 @@ public:
QAbstractProtobufSerializer::DeserializationError deserializationError() const override;
QString deserializationErrorString() const override;
private:
QByteArray serializeMessage(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering
) const override;
@ -32,74 +35,59 @@ public:
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QByteArrayView data) const override;
QByteArray serializeObject(const QProtobufMessage *message,
void serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
bool deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo)
const override;
bool
deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const override;
void serializeListObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override;
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo)
const override;
QByteArray
serializeListObject(const QList<const QProtobufMessage *> &messageList,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
bool deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering)
const override;
QProtobufBaseSerializer::Status
deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override;
void serializeMapPair(const QVariant &key, const QVariant &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo)
const override;
QByteArray
serializeMapPair(const QList<QPair<QVariant, QVariant>> &list,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
QProtobufBaseSerializer::Status
deserializeMapPair(QVariant &key, QVariant &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override
bool deserializeMapPair(QVariant &key, QVariant &value) const override
{
Q_UNUSED(key);
Q_UNUSED(value);
Q_UNUSED(it);
return QProtobufBaseSerializer::SerializationError;
return false;
}
QByteArray
void
serializeEnum(QtProtobuf::int64 value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const override
{
Q_UNUSED(value);
Q_UNUSED(fieldInfo);
return QByteArray();
}
QByteArray
serializeEnumList(const QList<QtProtobuf::int64> &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override
void serializeEnumList(const QList<QtProtobuf::int64> &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo)
const override
{
Q_UNUSED(value);
Q_UNUSED(fieldInfo);
return QByteArray();
}
Q_REQUIRED_RESULT
bool deserializeEnum(QtProtobuf::int64 &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override
bool deserializeEnum(QtProtobuf::int64 &value) const override
{
Q_UNUSED(value);
Q_UNUSED(it);
return false;
}
Q_REQUIRED_RESULT bool
deserializeEnumList(QList<QtProtobuf::int64> &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override
bool deserializeEnumList(QList<QtProtobuf::int64> &value) const override
{
Q_UNUSED(value);
Q_UNUSED(it);
return false;
}

View File

@ -2,11 +2,22 @@
// Copyright (C) 2019 Alexey Edelev <semlanik@gmail.com>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROTOBUFSELFCHECKITERATOR_H
#define QPROTOBUFSELFCHECKITERATOR_H
#ifndef QPROTOBUFSELFCHECKITERATOR_P_H
#define QPROTOBUFSELFCHECKITERATOR_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtProtobuf/qtprotobufglobal.h>
#include <QtCore/qnumeric.h>
#include <QtProtobuf/qtprotobufglobal.h>
#include <QtCore/QByteArray>
@ -14,7 +25,6 @@
QT_BEGIN_NAMESPACE
namespace QtProtobufPrivate {
class QProtobufSelfcheckIterator
{
public:
@ -24,6 +34,8 @@ public:
using pointer = QByteArray::pointer;
using reference = QByteArray::reference;
QProtobufSelfcheckIterator() = default;
static QProtobufSelfcheckIterator fromView(QByteArrayView container)
{
QProtobufSelfcheckIterator iter(container);
@ -104,8 +116,7 @@ public:
private:
explicit QProtobufSelfcheckIterator(QByteArrayView container)
: m_containerBegin(container.begin()),
m_containerEnd(container.end()),
: m_containerBegin(container.begin()), m_containerEnd(container.end()),
m_it(container.begin())
{
}
@ -162,8 +173,7 @@ inline QProtobufSelfcheckIterator operator-(const QProtobufSelfcheckIterator &it
copy -= length;
return copy;
}
} // namespace QtProtobufPrivate
QT_END_NAMESPACE
#endif // QPROTOBUFSELFCHECKITERATOR_H
#endif // QPROTOBUFSELFCHECKITERATOR_P_H

View File

@ -256,33 +256,33 @@ QProtobufSerializer::QProtobufSerializer() : d_ptr(new QProtobufSerializerPrivat
*/
QProtobufSerializer::~QProtobufSerializer() = default;
/*!
This is called by serialize() to serialize a registered Protobuf message
\a message with \a ordering. \a message must not be
\nullptr.
Returns a QByteArray containing the serialized message.
*/
QByteArray QProtobufSerializer::serializeMessage(
const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const
{
QByteArray result;
d_ptr->result = {};
d_ptr->serializeMessage(message, ordering);
return d_ptr->result;
}
void QProtobufSerializerPrivate::serializeMessage(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering
&ordering)
{
for (int index = 0; index < ordering.fieldCount(); ++index) {
int fieldIndex = ordering.getFieldNumber(index);
Q_ASSERT_X(fieldIndex < 536870912 && fieldIndex > 0, "", "fieldIndex is out of range");
QProtobufPropertyOrderingInfo fieldInfo(ordering, index);
QVariant propertyValue = message->property(fieldInfo);
result.append(d_ptr->serializeProperty(propertyValue, fieldInfo));
serializeProperty(propertyValue, fieldInfo);
}
if (d_ptr->preserveUnknownFields) {
if (preserveUnknownFields) {
// Restore any unknown fields we have stored away:
const QProtobufMessagePrivate *messagePrivate = QProtobufMessagePrivate::get(message);
for (const auto &fields : messagePrivate->unknownEntries)
result += fields.join();
}
return result;
}
void QProtobufSerializerPrivate::setUnexpectedEndOfStreamError()
@ -297,197 +297,131 @@ void QProtobufSerializerPrivate::clearError()
deserializationErrorString.clear();
}
/*!
This is called by deserialize() to deserialize a registered Protobuf message
\a message with \a ordering, from a QByteArrayView \a data. \a message
can be assumed to not be \nullptr.
Returns \c true if deserialization was successful, otherwise \c false.
*/
bool QProtobufSerializer::deserializeMessage(
QProtobufMessage *message, const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QByteArrayView data) const
{
d_ptr->clearError();
auto it = QProtobufSelfcheckIterator::fromView(data);
while (it.isValid() && it != data.end()) {
if (!d_ptr->deserializeProperty(message, ordering, it))
d_ptr->it = QProtobufSelfcheckIterator::fromView(data);
while (d_ptr->it.isValid() && d_ptr->it != data.end()) {
if (!d_ptr->deserializeProperty(message, ordering))
return false;
}
if (!it.isValid())
if (!d_ptr->it.isValid())
d_ptr->setUnexpectedEndOfStreamError();
return it.isValid();
return d_ptr->it.isValid();
}
/*!
Serialize an \a message with \a ordering and \a fieldInfo.
Returns a QByteArray containing the serialized message.
You should not call this function directly.
*/
QByteArray
QProtobufSerializer::serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
void QProtobufSerializer::serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering
&ordering,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
QByteArray result = QProtobufSerializerPrivate::prependLengthDelimitedSize(
serializeMessage(message, ordering));
result.prepend(QProtobufSerializerPrivate::encodeHeader(
fieldInfo.getFieldNumber(), QtProtobuf::WireTypes::LengthDelimited));
return result;
auto store = d_ptr->result;
d_ptr->result = {};
d_ptr->serializeMessage(message, ordering);
store.append(QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(),
QtProtobuf::WireTypes::LengthDelimited));
store.append(QProtobufSerializerPrivate::serializeVarintCommon<uint32_t>(d_ptr->result.size()));
store.append(d_ptr->result);
d_ptr->result = store;
}
/*!
Deserialize an \a message with \a ordering from a QProtobufSelfcheckIterator
\a it. Returns \c true if deserialization was successful, otherwise
\c false.
You should not call this function directly.
*/
bool QProtobufSerializer::deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QProtobufSelfcheckIterator &it) const
const QtProtobufPrivate::QProtobufPropertyOrdering
&ordering) const
{
if (it.bytesLeft() == 0) {
if (d_ptr->it.bytesLeft() == 0) {
d_ptr->setUnexpectedEndOfStreamError();
return false;
}
std::optional<QByteArray> array = QProtobufSerializerPrivate::deserializeLengthDelimited(it);
std::optional<QByteArray>
array = QProtobufSerializerPrivate::deserializeLengthDelimited(d_ptr->it);
if (!array) {
d_ptr->setUnexpectedEndOfStreamError();
return false;
}
return deserializeMessage(message, ordering, array.value());
}
/*!
This function is called to serialize \a messageList as a list of messages one by one
with \a ordering and \a fieldInfo.
You should not call this function directly.
*/
QByteArray QProtobufSerializer::serializeListObject(
const QList<const QProtobufMessage*> &messageList,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
QByteArray result;
for (const auto &message : messageList)
result.append(serializeObject(message, ordering, fieldInfo));
auto store = d_ptr->it;
bool result = deserializeMessage(message, ordering, array.value());
d_ptr->it = store;
return result;
}
/*!
This function deserializes an \a message from byte stream as part of list property, with
\a ordering from a QProtobufSelfcheckIterator \a it.
Returns \c Serialized if deserialization was successful,
otherwise \c SerializationError.
You should not call this function directly.
*/
QProtobufBaseSerializer::Status QProtobufSerializer::deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QProtobufSelfcheckIterator &it) const
{
if (deserializeObject(message, ordering, it))
return QProtobufBaseSerializer::Serialized;
else
return QProtobufBaseSerializer::SerializationError;
}
/*!
This function serializes \a list of pairs, each pair has a key and a value with
\a fieldInfo to a QByteArray
You should not call this function directly.
*/
QByteArray
QProtobufSerializer::serializeMapPair(const QList<QPair<QVariant, QVariant>> &list,
void QProtobufSerializer::serializeListObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering
&ordering,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
serializeObject(message, ordering, fieldInfo);
}
bool QProtobufSerializer::deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering
&ordering) const
{
return deserializeObject(message, ordering);
}
void QProtobufSerializer::serializeMapPair(const QVariant &key, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
QByteArray result;
for (const auto &element : list) {
const QVariant &key = element.first;
auto keyHandler = findIntegratedTypeHandler(key.metaType(), false);
Q_ASSERT_X(keyHandler, "QProtobufSerializer", "Map key is not an integrated type.");
result.append(QProtobufSerializerPrivate::encodeHeader(
fieldInfo.getFieldNumber(), QtProtobuf::WireTypes::LengthDelimited));
result.append(QProtobufSerializerPrivate::prependLengthDelimitedSize(
keyHandler->serializer(
key, QProtobufSerializerPrivate::encodeHeader(1, keyHandler->wireType))
+ d_ptr->serializeProperty(element.second, fieldInfo.infoForMapValue())));
}
return result;
auto store = d_ptr->result;
d_ptr->result = {};
d_ptr->result
.append(keyHandler
->serializer(key,
QProtobufSerializerPrivate::encodeHeader(1,
keyHandler->wireType)));
d_ptr->serializeProperty(value, fieldInfo.infoForMapValue());
store.append(QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(),
QtProtobuf::WireTypes::LengthDelimited));
store.append(QProtobufSerializerPrivate::serializeVarintCommon<uint32_t>(d_ptr->result.size()));
store.append(d_ptr->result);
d_ptr->result = store;
}
/*!
This function deserializes QMap pair of \a key and \a value from a
QProtobufSelfcheckIterator \a it.
Returns \c Serialized if deserialization was successful,
otherwise \c SerializationError.
You should not call this function directly.
*/
QProtobufBaseSerializer::Status QProtobufSerializer::deserializeMapPair(QVariant &key, QVariant &value, QProtobufSelfcheckIterator &it) const
bool QProtobufSerializer::deserializeMapPair(QVariant &key, QVariant &value) const
{
if (d_ptr->deserializeMapPair(key, value, it))
return QProtobufBaseSerializer::Serialized;
else
return QProtobufBaseSerializer::SerializationError;
return d_ptr->deserializeMapPair(key, value);
}
/*!
This function serializes \a value as a QByteArray for enum associated with
property \a fieldInfo.
You should not call this function directly.
*/
QByteArray QProtobufSerializer::serializeEnum(QtProtobuf::int64 value,
void QProtobufSerializer::serializeEnum(QtProtobuf::int64 value,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
if (value == 0 && !isOneofOrOptionalField(fieldInfo))
return {};
return;
QtProtobuf::WireTypes type = QtProtobuf::WireTypes::Varint;
int fieldNumber = fieldInfo.getFieldNumber();
return QProtobufSerializerPrivate::encodeHeader(fieldNumber, type)
+ QProtobufSerializerPrivate::serializeBasic<QtProtobuf::int64>(value);
d_ptr->result.append(QProtobufSerializerPrivate::encodeHeader(fieldNumber, type)
+ QProtobufSerializerPrivate::serializeBasic<QtProtobuf::int64>(value));
}
/*!
This function serializes a list, \a value, as a QByteArray for enum
associated with property \a fieldInfo.
You should not call this function directly.
*/
QByteArray
QProtobufSerializer::serializeEnumList(const QList<QtProtobuf::int64> &value,
void QProtobufSerializer::serializeEnumList(const QList<QtProtobuf::int64> &value,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
if (value.isEmpty()) {
return {};
}
if (value.isEmpty())
return;
auto header = QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(),
QtProtobuf::WireTypes::LengthDelimited);
if (fieldInfo.getFieldFlags() & QtProtobufPrivate::NonPacked)
return QProtobufSerializerPrivate::serializeNonPackedList<QtProtobuf::int64>(value, header);
return header + QProtobufSerializerPrivate::serializeListType<QtProtobuf::int64>(value);
d_ptr->result
.append(QProtobufSerializerPrivate::serializeNonPackedList<QtProtobuf::int64>(value,
header));
else
d_ptr->result
.append(header
+ QProtobufSerializerPrivate::serializeListType<QtProtobuf::int64>(value));
}
/*!
This function deserializes an enum \a value from a QProtobufSelfcheckIterator \a it.
Returns \c true if deserialization was successful, otherwise \c false.
You should not call this function directly.
*/
bool QProtobufSerializer::deserializeEnum(QtProtobuf::int64 &value, QProtobufSelfcheckIterator &it) const
bool QProtobufSerializer::deserializeEnum(QtProtobuf::int64 &value) const
{
QVariant variantValue;
if (!QProtobufSerializerPrivate::deserializeBasic<QtProtobuf::int64>(it, variantValue)) {
if (!QProtobufSerializerPrivate::deserializeBasic<QtProtobuf::int64>(d_ptr->it, variantValue)) {
d_ptr->setUnexpectedEndOfStreamError();
return false;
}
@ -495,16 +429,10 @@ bool QProtobufSerializer::deserializeEnum(QtProtobuf::int64 &value, QProtobufSel
return true;
}
/*!
This function deserializes a list of enum \a value from a QProtobufSelfcheckIterator \a it.
Returns \c true if deserialization was successful, otherwise \c false.
You should not call this function directly.
*/
bool QProtobufSerializer::deserializeEnumList(QList<QtProtobuf::int64> &value, QProtobufSelfcheckIterator &it) const
bool QProtobufSerializer::deserializeEnumList(QList<QtProtobuf::int64> &value) const
{
QVariant variantValue;
if (!QProtobufSerializerPrivate::deserializeList<QtProtobuf::int64>(it, variantValue)) {
if (!QProtobufSerializerPrivate::deserializeList<QtProtobuf::int64>(d_ptr->it, variantValue)) {
d_ptr->setUnexpectedEndOfStreamError();
return false;
}
@ -517,6 +445,7 @@ QProtobufSerializerPrivate::QProtobufSerializerPrivate(QProtobufSerializer *q) :
}
/*!
\internal
Encode a property field index and its type into output bytes.
Header byte
@ -537,13 +466,13 @@ QByteArray QProtobufSerializerPrivate::encodeHeader(int fieldIndex,
}
/*!
\internal
Decode a property field index and its serialization type from input bytes
Iterator: that points to header with encoded field index and serialization type
fieldIndex: Decoded index of a property in parent object
wireType: Decoded serialization type used for the property with index
*
\return true if both decoded wireType and fieldIndex have "allowed" values and false, otherwise
Return true if both decoded wireType and fieldIndex have "allowed" values and false, otherwise
*/
bool QProtobufSerializerPrivate::decodeHeader(QProtobufSelfcheckIterator &it,
int &fieldIndex,
@ -610,8 +539,7 @@ qsizetype QProtobufSerializerPrivate::skipSerializedFieldBytes(QProtobufSelfchec
return std::distance(initialIt, QByteArray::const_iterator(it));
}
QByteArray
QProtobufSerializerPrivate::serializeProperty(const QVariant &propertyValue,
void QProtobufSerializerPrivate::serializeProperty(const QVariant &propertyValue,
const QProtobufPropertyOrderingInfo &fieldInfo)
{
QMetaType metaType = propertyValue.metaType();
@ -621,7 +549,7 @@ QProtobufSerializerPrivate::serializeProperty(const QVariant &propertyValue,
if (metaType.id() == QMetaType::UnknownType || propertyValue.isNull()) {
// Empty value
return {};
return;
}
auto basicHandler = findIntegratedTypeHandler(
@ -629,29 +557,26 @@ QProtobufSerializerPrivate::serializeProperty(const QVariant &propertyValue,
if (basicHandler) {
bool serializeUninitialized = isOneofOrOptionalField(fieldInfo);
if (!basicHandler->isPresent(propertyValue) && !serializeUninitialized) {
return {};
return;
}
QByteArray header = QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(),
basicHandler->wireType);
return basicHandler->serializer(propertyValue, header);
result.append(basicHandler->serializer(propertyValue, header));
return;
}
auto handler = QtProtobufPrivate::findHandler(metaType);
if (!handler.serializer) {
qProtoWarning() << "No serializer for type" << propertyValue.typeName();
return {};
return;
}
QByteArray result;
handler.serializer(q_ptr, propertyValue, fieldInfo, result);
return result;
handler.serializer(q_ptr, propertyValue, fieldInfo);
}
bool QProtobufSerializerPrivate::deserializeProperty(
QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QProtobufSelfcheckIterator &it)
bool QProtobufSerializerPrivate::
deserializeProperty(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering)
{
Q_ASSERT(it.isValid() && it.bytesLeft() > 0);
//Each iteration we expect iterator is setup to beginning of next chunk
@ -739,13 +664,13 @@ bool QProtobufSerializerPrivate::deserializeProperty(
QCoreApplication::translate("QtProtobuf", error.toUtf8().data()));
return false;
}
handler.deserializer(q_ptr, it, newPropertyValue);
handler.deserializer(q_ptr, newPropertyValue);
}
return message->setProperty(fieldInfo, std::move(newPropertyValue));
}
bool QProtobufSerializerPrivate::deserializeMapPair(QVariant &key, QVariant &value, QProtobufSelfcheckIterator &it)
bool QProtobufSerializerPrivate::deserializeMapPair(QVariant &key, QVariant &value)
{
int mapIndex = 0;
QtProtobuf::WireTypes type = QtProtobuf::WireTypes::Unknown;
@ -797,7 +722,7 @@ bool QProtobufSerializerPrivate::deserializeMapPair(QVariant &key, QVariant &val
.arg(QLatin1String(value.typeName())));
return false;
}
handler.deserializer(q_ptr, it, value);
handler.deserializer(q_ptr, value);
}
}
}

View File

@ -14,10 +14,6 @@
QT_BEGIN_NAMESPACE
namespace QtProtobufPrivate {
class QProtobufSelfcheckIterator;
} // namespace QtProtobufPrivate
class QProtobufMessage;
class QProtobufSerializerPrivate;
class Q_PROTOBUF_EXPORT QProtobufSerializer : public QProtobufBaseSerializer
@ -30,6 +26,8 @@ public:
QProtobufSerializer::DeserializationError deserializationError() const override;
QString deserializationErrorString() const override;
void shouldPreserveUnknownFields(bool preserveUnknownFields);
private:
QByteArray
serializeMessage(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering
@ -38,50 +36,36 @@ public:
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QByteArrayView data) const override;
QByteArray
serializeObject(const QProtobufMessage *message,
void serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
bool deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override;
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo)
const override;
bool
deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const override;
QByteArray
serializeListObject(const QList<const QProtobufMessage *> &messageList,
void serializeListObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
QProtobufBaseSerializer::Status deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it
) const override;
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo)
const override;
bool deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering)
const override;
QByteArray
serializeMapPair(const QList<QPair<QVariant, QVariant> > &list,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
QProtobufBaseSerializer::Status deserializeMapPair(QVariant &key, QVariant &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it
) const override;
void serializeMapPair(const QVariant &key, const QVariant &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo)
const override;
bool deserializeMapPair(QVariant &key, QVariant &value) const override;
QByteArray
void
serializeEnum(QtProtobuf::int64 value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
QByteArray
serializeEnumList(const QList<QtProtobuf::int64> &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const override;
void serializeEnumList(const QList<QtProtobuf::int64> &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo)
const override;
Q_REQUIRED_RESULT
bool deserializeEnum(QtProtobuf::int64 &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override;
Q_REQUIRED_RESULT bool
deserializeEnumList(QList<QtProtobuf::int64> &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override;
void shouldPreserveUnknownFields(bool preserveUnknownFields);
bool deserializeEnum(QtProtobuf::int64 &value) const override;
bool deserializeEnumList(QList<QtProtobuf::int64> &value) const override;
private:
std::unique_ptr<QProtobufSerializerPrivate> d_ptr;
};

View File

@ -23,19 +23,17 @@
#include <QtCore/qendian.h>
#include <QtCore/qvariant.h>
#include <QtProtobuf/qprotobufselfcheckiterator.h>
#include <QtProtobuf/qprotobufserializer.h>
#include <QtProtobuf/qtprotobuftypes.h>
#include <QtProtobuf/private/qprotobufselfcheckiterator_p.h>
#include <QtProtobuf/private/qtprotobuflogging_p.h>
#include <QtProtobuf/qabstractprotobufserializer.h>
#include <QtProtobuf/qprotobufserializer.h>
#include <QtProtobuf/qtprotobuftypes.h>
#include <optional>
#include <type_traits>
QT_BEGIN_NAMESPACE
using QtProtobufPrivate::QProtobufSelfcheckIterator;
class QProtobufSerializerPrivate
{
// The below type trait structures help to determine the required encoding method for protobuf
@ -500,12 +498,14 @@ public:
static void skipVarint(QProtobufSelfcheckIterator &it);
static void skipLengthDelimited(QProtobufSelfcheckIterator &it);
QByteArray serializeProperty(const QVariant &propertyValue,
void serializeMessage(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering);
void serializeProperty(const QVariant &propertyValue,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo);
Q_REQUIRED_RESULT
bool deserializeProperty(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QProtobufSelfcheckIterator &it);
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering);
void setDeserializationError(QAbstractProtobufSerializer::DeserializationError error,
const QString &errorString);
@ -513,12 +513,15 @@ public:
void setUnexpectedEndOfStreamError();
Q_REQUIRED_RESULT
bool deserializeMapPair(QVariant &key, QVariant &value, QProtobufSelfcheckIterator &it);
bool deserializeMapPair(QVariant &key, QVariant &value);
QAbstractProtobufSerializer::DeserializationError deserializationError =
QAbstractProtobufSerializer::NoDeserializerError;
QString deserializationErrorString;
QProtobufSelfcheckIterator it;
QByteArray result;
bool preserveUnknownFields = true;
private:
Q_DISABLE_COPY_MOVE(QProtobufSerializerPrivate)

View File

@ -39,10 +39,9 @@ constexpr inline bool is_optional_v<std::optional<T>> = true;
template<typename QType, typename PType>
void registerQtTypeHandler()
{
registerHandler(
QMetaType::fromType<QType>(),
registerHandler(QMetaType::fromType<QType>(),
{ [](const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &info, QByteArray &buffer) {
const QProtobufPropertyOrderingInfo &info) {
auto do_convert = [](const QType &qtype) {
auto res = convert(qtype);
if constexpr (is_optional_v<decltype(res)>) {
@ -54,16 +53,15 @@ void registerQtTypeHandler()
std::optional<PType> object = do_convert(value.value<QType>());
if (object) {
buffer.append(serializer->serializeObject(&(object.value()),
PType::propertyOrdering, info));
serializer->serializeObject(&(object.value()), PType::propertyOrdering,
info);
} else {
warnTypeConversionError();
}
},
[](const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &value) {
[](const QProtobufBaseSerializer *serializer, QVariant &value) {
PType object;
serializer->deserializeObject(&object, PType::propertyOrdering, it);
serializer->deserializeObject(&object, PType::propertyOrdering);
auto res = convert(object);
if constexpr (is_optional_v<decltype(res)>) {
if (!res)
@ -73,8 +71,7 @@ void registerQtTypeHandler()
} else {
value = QVariant::fromValue<QType>(res);
}
}
});
} });
}
} // namespace QtProtobufPrivate

View File

@ -3,7 +3,7 @@
#include <QtProtobufWellKnownTypes/qtprotobufwellknowntypesglobal.h>
#include <QtProtobuf/qprotobufserializer.h>
#include <QtProtobuf/qprotobufbaseserializer.h>
#include <QtProtobuf/private/qprotobufserializer_p.h>
#include "qprotobufanysupport.h"
@ -25,7 +25,7 @@ public:
};
static void serializerProxy(const QProtobufBaseSerializer *serializer, const QVariant &object,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &output)
const QProtobufPropertyOrderingInfo &fieldInfo)
{
if (object.isNull())
return;
@ -37,41 +37,28 @@ static void serializerProxy(const QProtobufBaseSerializer *serializer, const QVa
google::protobuf::Any realAny;
realAny.setValue(any.value());
realAny.setTypeUrl(any.typeUrl());
output.append(serializer->serializeObject(&realAny, google::protobuf::Any::propertyOrdering,
fieldInfo));
serializer->serializeObject(&realAny, google::protobuf::Any::propertyOrdering, fieldInfo);
}
static void listSerializerProxy(const QProtobufBaseSerializer *serializer,
const QVariant &object,
const QProtobufPropertyOrderingInfo &fieldInfo,
QByteArray &output)
static void listSerializerProxy(const QProtobufBaseSerializer *serializer, const QVariant &object,
const QProtobufPropertyOrderingInfo &fieldInfo)
{
const QList<Any> anyList = object.value<QList<Any>>();
QList<const QProtobufMessage*> msgList;
msgList.reserve(anyList.size());
QList<google::protobuf::Any> msgAny;
msgAny.reserve(anyList.size());
const auto anyList = object.value<QList<Any>>();
for (const Any &any : anyList) {
google::protobuf::Any realAny;
realAny.setValue(any.value());
realAny.setTypeUrl(any.typeUrl());
msgAny.append(realAny);
serializer->serializeListObject(&realAny, google::protobuf::Any::propertyOrdering,
fieldInfo);
}
for (const google::protobuf::Any &any : msgAny) {
msgList.append(&any);
}
output.append(serializer->serializeListObject(msgList,
google::protobuf::Any::propertyOrdering,
fieldInfo));
}
static void listDeserializerProxy(const QProtobufBaseSerializer *deserializer,
QProtobufSelfcheckIterator &it, QVariant &object)
static void listDeserializerProxy(const QProtobufBaseSerializer *deserializer, QVariant &object)
{
auto anyList = object.value<QList<Any>>();
const auto &ordering = google::protobuf::Any::propertyOrdering;
google::protobuf::Any realAny;
if (deserializer->deserializeObject(&realAny, ordering, it)) {
if (deserializer->deserializeObject(&realAny, ordering)) {
Any any;
any.setTypeUrl(realAny.typeUrl());
any.setValue(realAny.value());
@ -82,11 +69,10 @@ static void listDeserializerProxy(const QProtobufBaseSerializer *deserializer,
object.setValue(std::move(anyList));
}
static void deserializerProxy(const QProtobufBaseSerializer *deserializer,
QProtobufSelfcheckIterator &it, QVariant &object)
static void deserializerProxy(const QProtobufBaseSerializer *deserializer, QVariant &object)
{
google::protobuf::Any realAny;
if (deserializer->deserializeObject(&realAny, google::protobuf::Any::propertyOrdering, it)) {
if (deserializer->deserializeObject(&realAny, google::protobuf::Any::propertyOrdering)) {
Any any;
any.setTypeUrl(realAny.typeUrl());
any.setValue(realAny.value());
@ -210,10 +196,10 @@ void Any::setValue(const QByteArray &value)
}
/*!
\fn template <typename T> std::optional<T> Any::as() const
\fn template <typename T> std::optional<T> Any::as(QAbstractProtobufSerializer *serializer) const
This function compares the message name of T with the value of typeUrl()
before deserializing the data.
before deserializing the data using \a serializer.
If the verification or deserialization fails it will return
\c{std::nullopt}.
@ -222,21 +208,21 @@ void Any::setValue(const QByteArray &value)
\c{Q_PROTOBUF_OBJECT} macro or (for a nested Any message) be Any itself.
*/
bool Any::asImpl(QProtobufMessage *message,
bool Any::asImpl(QAbstractProtobufSerializer *serializer, QProtobufMessage *message,
QtProtobufPrivate::QProtobufPropertyOrdering ordering) const
{
QProtobufSerializer serializer;
Q_ASSERT_X(serializer != nullptr, "Any::asImpl", "serializer is null");
QString tUrl = typeUrl();
qsizetype lastSegmentIndex = tUrl.lastIndexOf(u'/') + 1;
if (QStringView(tUrl).mid(lastSegmentIndex).compare(ordering.getMessageFullName()) != 0)
return false;
return serializer.deserializeMessage(message, ordering, value());
return serializer->deserializeMessage(message, ordering, value());
}
std::optional<Any> Any::asAnyImpl() const
std::optional<Any> Any::asAnyImpl(QAbstractProtobufSerializer *serializer) const
{
google::protobuf::Any realAny;
if (!asImpl(&realAny, google::protobuf::Any::propertyOrdering))
if (!asImpl(serializer, &realAny, google::protobuf::Any::propertyOrdering))
return std::nullopt;
Any any;
any.setTypeUrl(realAny.typeUrl());
@ -245,37 +231,39 @@ std::optional<Any> Any::asAnyImpl() const
}
/*!
\fn template <typename T> static Any Any::fromMessage(const T &message, QAnyStringView typeUrlPrefix)
\fn template <typename T> static Any Any::fromMessage(QAbstractProtobufSerializer *serializer,
const T &message, QAnyStringView typeUrlPrefix)
This function serializes the given \a message as the value of the returned
Any instance. This instance's typeUrl() is constructed from a prefix, a
forward slash and the message name obtained from
\c{T::propertyOrdering.getMessageFullName()}. If \a typeUrlPrefix is
supplied, it is used as prefix, otherwise \c{"type.googleapis.com"} is used.
\c{T::propertyOrdering.getMessageFullName()} using \a serializer. If \a
typeUrlPrefix is supplied, it is used as prefix, otherwise
\c{"type.googleapis.com"} is used.
\note T must be a class derived from QProtobufMessage with the
\c{Q_PROTOBUF_OBJECT} macro or (for a nested Any message) be Any itself.
*/
Any Any::fromMessageImpl(const QProtobufMessage *message,
Any Any::fromMessageImpl(QAbstractProtobufSerializer *serializer, const QProtobufMessage *message,
QtProtobufPrivate::QProtobufPropertyOrdering ordering,
QAnyStringView typeUrlPrefix)
{
QProtobufSerializer serializer;
Any any;
any.setValue(serializer.serializeMessage(message, ordering));
any.setValue(serializer->serializeMessage(message, ordering));
any.setTypeUrl(typeUrlPrefix.toString() + u'/' + ordering.getMessageFullName().toString());
return { any };
}
// Used to handle nested Any messages.
Any Any::fromAnyMessageImpl(const Any *message, QAnyStringView typeUrlPrefix)
Any Any::fromAnyMessageImpl(QAbstractProtobufSerializer *serializer,
const Any *message, QAnyStringView typeUrlPrefix)
{
using RealAny = google::protobuf::Any;
RealAny realAny;
realAny.setTypeUrl(message->typeUrl());
realAny.setValue(message->value());
return fromMessageImpl(&realAny, RealAny::propertyOrdering, typeUrlPrefix);
return fromMessageImpl(serializer, &realAny, RealAny::propertyOrdering, typeUrlPrefix);
}
QAnyStringView Any::defaultUrlPrefix()

View File

@ -17,6 +17,8 @@
QT_BEGIN_NAMESPACE
class QAbstractProtobufSerializer;
namespace QtProtobuf {
class AnyPrivate;
class Q_PROTOBUFWELLKNOWNTYPES_EXPORT Any : public QProtobufMessage
@ -48,42 +50,45 @@ public:
void setValue(const QByteArray &value);
template <typename T>
std::optional<T> as() const
std::optional<T> as(QAbstractProtobufSerializer *serializer) const
{
if constexpr (std::is_same_v<T, Any>) {
return asAnyImpl();
return asAnyImpl(serializer);
} else {
static_assert(QtProtobufPrivate::HasProtobufPropertyOrdering<T>,
"T must have the Q_PROTOBUF_OBJECT macro");
T obj;
if (asImpl(&obj, T::propertyOrdering))
if (asImpl(serializer, &obj, T::propertyOrdering))
return { std::move(obj) };
}
return std::nullopt;
}
template <typename T>
static Any fromMessage(const T &message, QAnyStringView typeUrlPrefix = defaultUrlPrefix())
static Any fromMessage(QAbstractProtobufSerializer *serializer, const T &message,
QAnyStringView typeUrlPrefix = defaultUrlPrefix())
{
if constexpr (std::is_same_v<T, Any>)
return fromAnyMessageImpl(&message, typeUrlPrefix);
return fromAnyMessageImpl(serializer, &message, typeUrlPrefix);
static_assert(QtProtobufPrivate::HasProtobufPropertyOrdering<T>,
"T must have the Q_PROTOBUF_OBJECT macro");
return fromMessageImpl(&message, T::propertyOrdering, typeUrlPrefix);
return fromMessageImpl(serializer, &message, T::propertyOrdering, typeUrlPrefix);
}
private:
AnyPrivate *d_ptr;
Q_DECLARE_PRIVATE(Any)
bool asImpl(QProtobufMessage *message,
bool asImpl(QAbstractProtobufSerializer *serializer, QProtobufMessage *message,
QtProtobufPrivate::QProtobufPropertyOrdering ordering) const;
std::optional<Any> asAnyImpl() const;
static Any fromMessageImpl(const QProtobufMessage *message,
std::optional<Any> asAnyImpl(QAbstractProtobufSerializer *serializer) const;
static Any fromMessageImpl(QAbstractProtobufSerializer *serializer,
const QProtobufMessage *message,
QtProtobufPrivate::QProtobufPropertyOrdering ordering,
QAnyStringView typeUrlPrefix);
static Any fromAnyMessageImpl(const Any *message, QAnyStringView typeUrlPrefix);
static Any fromAnyMessageImpl(QAbstractProtobufSerializer *serializer,
const Any *message, QAnyStringView typeUrlPrefix);
static QAnyStringView defaultUrlPrefix();

View File

@ -4,9 +4,9 @@
//#include "basicmessages.qpb.h"
#include "repeatedmessages.qpb.h"
#include <QObject>
#include <QTest>
#include <QJsonDocument>
#include <QProtobufJsonSerializer>
#include <QTest>
using namespace Qt::Literals::StringLiterals;
@ -215,10 +215,6 @@ void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedComplexMessageTest(
"{\"testFieldString\":\"\"}}]}"_ba);
QCOMPARE(test.testRepeatedComplex().count(), 3);
for (auto element: test.testRepeatedComplex()) {
qWarning() << "testFieldInt = " << element.testFieldInt()
<< "testFieldString = " << element.testComplexField().testFieldString();
}
QCOMPARE(test.testRepeatedComplex().at(0).testFieldInt(), 21);
QCOMPARE(test.testRepeatedComplex().at(0).testComplexField().testFieldString(), QString("12345"));
QCOMPARE(test.testRepeatedComplex().at(1).testFieldInt(), 22);

View File

@ -66,23 +66,20 @@ using namespace qtprotobufnamespace::tests;
void QtProtobufTypesJsonSerializationTest::BoolMessageSerializeTest_data()
{
QTest::addColumn<bool>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("True") << true << qsizetype(22) << "{\"testFieldBool\":true}"_ba;
QTest::newRow("False") << false << qsizetype(23) << "{\"testFieldBool\":false}"_ba;
QTest::newRow("True") << true << "{\"testFieldBool\":true}"_ba;
QTest::newRow("False") << false << "{\"testFieldBool\":false}"_ba;
}
void QtProtobufTypesJsonSerializationTest::BoolMessageSerializeTest()
{
QFETCH(const bool, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleBoolMessage test;
test.setTestFieldBool(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -90,23 +87,20 @@ void QtProtobufTypesJsonSerializationTest::BoolMessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::IntMessageSerializeTest_data()
{
QTest::addColumn<int32_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("555") << 555 << qsizetype(20) << "{\"testFieldInt\":555}"_ba;
QTest::newRow("0") << 0 << qsizetype(18) << "{\"testFieldInt\":0}"_ba;
QTest::newRow("555") << 555 << "{\"testFieldInt\":555}"_ba;
QTest::newRow("0") << 0 << "{\"testFieldInt\":0}"_ba;
}
void QtProtobufTypesJsonSerializationTest::IntMessageSerializeTest()
{
QFETCH(const int32_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleIntMessage test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -114,24 +108,21 @@ void QtProtobufTypesJsonSerializationTest::IntMessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::UIntMessageSerializeTest_data()
{
QTest::addColumn<uint32_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (uint32_t)15 << qsizetype(19) << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (uint32_t)300 << qsizetype(20) << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (uint32_t)65545 << qsizetype(22) << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("15") << (uint32_t)15 << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (uint32_t)300 << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (uint32_t)65545 << "{\"testFieldInt\":65545}"_ba;
}
void QtProtobufTypesJsonSerializationTest::UIntMessageSerializeTest()
{
QFETCH(const uint32_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleUIntMessage test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -139,28 +130,25 @@ void QtProtobufTypesJsonSerializationTest::UIntMessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::SIntMessageSerializeTest_data()
{
QTest::addColumn<int32_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (int32_t)15 << qsizetype(19) << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (int32_t)300 << qsizetype(20) << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (int32_t)65545 << qsizetype(22) << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("15") << (int32_t)15 << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (int32_t)300 << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (int32_t)65545 << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("-1") << (int32_t)-1 << qsizetype(19) << "{\"testFieldInt\":-1}"_ba;
QTest::newRow("-462") << (int32_t)-462 << qsizetype(21) << "{\"testFieldInt\":-462}"_ba;
QTest::newRow("-63585") << (int32_t)-63585 << qsizetype(23) << "{\"testFieldInt\":-63585}"_ba;
QTest::newRow("-1") << (int32_t)-1 << "{\"testFieldInt\":-1}"_ba;
QTest::newRow("-462") << (int32_t)-462 << "{\"testFieldInt\":-462}"_ba;
QTest::newRow("-63585") << (int32_t)-63585 << "{\"testFieldInt\":-63585}"_ba;
}
void QtProtobufTypesJsonSerializationTest::SIntMessageSerializeTest()
{
QFETCH(const int32_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleSIntMessage test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -168,28 +156,25 @@ void QtProtobufTypesJsonSerializationTest::SIntMessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::Int64MessageSerializeTest_data()
{
QTest::addColumn<int64_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (int64_t)15 << qsizetype(19) << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (int64_t)300 << qsizetype(20) << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (int64_t)65545 << qsizetype(22) << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("15") << (int64_t)15 << "{\"testFieldInt\":\"15\"}"_ba;
QTest::newRow("300") << (int64_t)300 << "{\"testFieldInt\":\"300\"}"_ba;
QTest::newRow("65545") << (int64_t)65545 << "{\"testFieldInt\":\"65545\"}"_ba;
QTest::newRow("-1") << (int64_t)-1 << qsizetype(19) << "{\"testFieldInt\":-1}"_ba;
QTest::newRow("-462") << (int64_t)-462 << qsizetype(21) << "{\"testFieldInt\":-462}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << qsizetype(23) << "{\"testFieldInt\":-63585}"_ba;
QTest::newRow("-1") << (int64_t)-1 << "{\"testFieldInt\":\"-1\"}"_ba;
QTest::newRow("-462") << (int64_t)-462 << "{\"testFieldInt\":\"-462\"}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << "{\"testFieldInt\":\"-63585\"}"_ba;
}
void QtProtobufTypesJsonSerializationTest::Int64MessageSerializeTest()
{
QFETCH(const int64_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleInt64Message test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -197,24 +182,21 @@ void QtProtobufTypesJsonSerializationTest::Int64MessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::UInt64MessageSerializeTest_data()
{
QTest::addColumn<uint64_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (uint64_t)15 << qsizetype(19) << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (uint64_t)300 << qsizetype(20) << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (uint64_t)65545 << qsizetype(22) << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("15") << (uint64_t)15 << "{\"testFieldInt\":\"15\"}"_ba;
QTest::newRow("300") << (uint64_t)300 << "{\"testFieldInt\":\"300\"}"_ba;
QTest::newRow("65545") << (uint64_t)65545 << "{\"testFieldInt\":\"65545\"}"_ba;
}
void QtProtobufTypesJsonSerializationTest::UInt64MessageSerializeTest()
{
QFETCH(const QtProtobuf::uint64, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleUInt64Message test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -222,28 +204,25 @@ void QtProtobufTypesJsonSerializationTest::UInt64MessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::SInt64MessageSerializeTest_data()
{
QTest::addColumn<int64_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (int64_t)15 << qsizetype(19) << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (int64_t)300 << qsizetype(20) << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (int64_t)65545 << qsizetype(22) << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("15") << (int64_t)15 << "{\"testFieldInt\":\"15\"}"_ba;
QTest::newRow("300") << (int64_t)300 << "{\"testFieldInt\":\"300\"}"_ba;
QTest::newRow("65545") << (int64_t)65545 << "{\"testFieldInt\":\"65545\"}"_ba;
QTest::newRow("-1") << (int64_t)-1 << qsizetype(19) << "{\"testFieldInt\":-1}"_ba;
QTest::newRow("-462") << (int64_t)-462 << qsizetype(21) << "{\"testFieldInt\":-462}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << qsizetype(23) << "{\"testFieldInt\":-63585}"_ba;
QTest::newRow("-1") << (int64_t)-1 << "{\"testFieldInt\":\"-1\"}"_ba;
QTest::newRow("-462") << (int64_t)-462 << "{\"testFieldInt\":\"-462\"}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << "{\"testFieldInt\":\"-63585\"}"_ba;
}
void QtProtobufTypesJsonSerializationTest::SInt64MessageSerializeTest()
{
QFETCH(const int64_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleSInt64Message test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -251,25 +230,21 @@ void QtProtobufTypesJsonSerializationTest::SInt64MessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::FixedInt32MessageSerializeTest_data()
{
QTest::addColumn<uint32_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (uint32_t)15 << qsizetype(26) << "{\"testFieldFixedInt32\":15}"_ba;
QTest::newRow("300") << (uint32_t)300 << qsizetype(27) << "{\"testFieldFixedInt32\":300}"_ba;
QTest::newRow("65545")
<< (uint32_t)65545 << qsizetype(29) << "{\"testFieldFixedInt32\":65545}"_ba;
QTest::newRow("15") << (uint32_t)15 << "{\"testFieldFixedInt32\":15}"_ba;
QTest::newRow("300") << (uint32_t)300 << "{\"testFieldFixedInt32\":300}"_ba;
QTest::newRow("65545") << (uint32_t)65545 << "{\"testFieldFixedInt32\":65545}"_ba;
}
void QtProtobufTypesJsonSerializationTest::FixedInt32MessageSerializeTest()
{
QFETCH(const uint32_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleFixedInt32Message test;
test.setTestFieldFixedInt32(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -277,25 +252,21 @@ void QtProtobufTypesJsonSerializationTest::FixedInt32MessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::FixedInt64MessageSerializeTest_data()
{
QTest::addColumn<uint64_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (uint64_t)15 << qsizetype(26) << "{\"testFieldFixedInt64\":15}"_ba;
QTest::newRow("300") << (uint64_t)300 << qsizetype(27) << "{\"testFieldFixedInt64\":300}"_ba;
QTest::newRow("65545")
<< (uint64_t)65545 << qsizetype(29) << "{\"testFieldFixedInt64\":65545}"_ba;
QTest::newRow("15") << (uint64_t)15 << "{\"testFieldFixedInt64\":\"15\"}"_ba;
QTest::newRow("300") << (uint64_t)300 << "{\"testFieldFixedInt64\":\"300\"}"_ba;
QTest::newRow("65545") << (uint64_t)65545 << "{\"testFieldFixedInt64\":\"65545\"}"_ba;
}
void QtProtobufTypesJsonSerializationTest::FixedInt64MessageSerializeTest()
{
QFETCH(const uint64_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleFixedInt64Message test;
test.setTestFieldFixedInt64(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -303,29 +274,24 @@ void QtProtobufTypesJsonSerializationTest::FixedInt64MessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::SFixedInt32MessageSerializeTest_data()
{
QTest::addColumn<int32_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (int32_t)15 << qsizetype(26) << "{\"testFieldFixedInt32\":15}"_ba;
QTest::newRow("300") << (int32_t)300 << qsizetype(27) << "{\"testFieldFixedInt32\":300}"_ba;
QTest::newRow("65545")
<< (int32_t)65545 << qsizetype(29) << "{\"testFieldFixedInt32\":65545}"_ba;
QTest::newRow("15") << (int32_t)15 << "{\"testFieldFixedInt32\":15}"_ba;
QTest::newRow("300") << (int32_t)300 << "{\"testFieldFixedInt32\":300}"_ba;
QTest::newRow("65545") << (int32_t)65545 << "{\"testFieldFixedInt32\":65545}"_ba;
QTest::newRow("-1") << (int32_t)-1 << qsizetype(26) << "{\"testFieldFixedInt32\":-1}"_ba;
QTest::newRow("-462") << (int32_t)-462 << qsizetype(28) << "{\"testFieldFixedInt32\":-462}"_ba;
QTest::newRow("-63585")
<< (int32_t)-63585 << qsizetype(30) << "{\"testFieldFixedInt32\":-63585}"_ba;
QTest::newRow("-1") << (int32_t)-1 << "{\"testFieldFixedInt32\":-1}"_ba;
QTest::newRow("-462") << (int32_t)-462 << "{\"testFieldFixedInt32\":-462}"_ba;
QTest::newRow("-63585") << (int32_t)-63585 << "{\"testFieldFixedInt32\":-63585}"_ba;
}
void QtProtobufTypesJsonSerializationTest::SFixedInt32MessageSerializeTest()
{
QFETCH(const int32_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleSFixedInt32Message test;
test.setTestFieldFixedInt32(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -333,30 +299,25 @@ void QtProtobufTypesJsonSerializationTest::SFixedInt32MessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::SFixedInt64MessageSerializeTest_data()
{
QTest::addColumn<int64_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (int64_t)15 << qsizetype(26) << "{\"testFieldFixedInt64\":15}"_ba;
QTest::newRow("300") << (int64_t)300 << qsizetype(27) << "{\"testFieldFixedInt64\":300}"_ba;
QTest::newRow("65545")
<< (int64_t)65545 << qsizetype(29) << "{\"testFieldFixedInt64\":65545}"_ba;
QTest::newRow("15") << (int64_t)15 << "{\"testFieldFixedInt64\":\"15\"}"_ba;
QTest::newRow("300") << (int64_t)300 << "{\"testFieldFixedInt64\":\"300\"}"_ba;
QTest::newRow("65545") << (int64_t)65545 << "{\"testFieldFixedInt64\":\"65545\"}"_ba;
QTest::newRow("-1") << (int64_t)-1 << qsizetype(26) << "{\"testFieldFixedInt64\":-1}"_ba;
QTest::newRow("-462") << (int64_t)-462 << qsizetype(28) << "{\"testFieldFixedInt64\":-462}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << qsizetype(30)
<< "{\"testFieldFixedInt64\":-63585}"_ba;
QTest::newRow("-1") << (int64_t)-1 << "{\"testFieldFixedInt64\":\"-1\"}"_ba;
QTest::newRow("-462") << (int64_t)-462 << "{\"testFieldFixedInt64\":\"-462\"}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << "{\"testFieldFixedInt64\":\"-63585\"}"_ba;
}
void QtProtobufTypesJsonSerializationTest::SFixedInt64MessageSerializeTest()
{
QFETCH(const int64_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleSFixedInt64Message test;
test.setTestFieldFixedInt64(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -364,30 +325,25 @@ void QtProtobufTypesJsonSerializationTest::SFixedInt64MessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::FloatMessageSerializeTest_data()
{
QTest::addColumn<float>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("float_value_0_1") << 0.1f << qsizetype(22) << "{\"testFieldFloat\":0.1}"_ba;
QTest::newRow("float_value_min") << std::numeric_limits<float>::min() << qsizetype(31)
<< "{\"testFieldFloat\":1.175494e-38}"_ba;
QTest::newRow("float_value_max") << std::numeric_limits<float>::max() << qsizetype(31)
<< "{\"testFieldFloat\":3.402823e+38}"_ba;
QTest::newRow("float_neg_value_4_2")
<< -4.2f << qsizetype(23) << "{\"testFieldFloat\":-4.2}"_ba;
QTest::newRow("float_neg_value_0_0")
<< (float)-0.0f << qsizetype(20) << "{\"testFieldFloat\":0}"_ba;
QTest::newRow("float_value_0_1") << 0.1f << "{\"testFieldFloat\":0.1}"_ba;
QTest::newRow("float_value_min")
<< std::numeric_limits<float>::min() << "{\"testFieldFloat\":1.17549e-38}"_ba;
QTest::newRow("float_value_max")
<< std::numeric_limits<float>::max() << "{\"testFieldFloat\":3.40282e+38}"_ba;
QTest::newRow("float_neg_value_4_2") << -4.2f << "{\"testFieldFloat\":-4.2}"_ba;
QTest::newRow("float_neg_value_0_0") << (float)-0.0f << "{\"testFieldFloat\":0}"_ba;
}
void QtProtobufTypesJsonSerializationTest::FloatMessageSerializeTest()
{
QFETCH(const float, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleFloatMessage test;
test.setTestFieldFloat(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -395,33 +351,30 @@ void QtProtobufTypesJsonSerializationTest::FloatMessageSerializeTest()
void QtProtobufTypesJsonSerializationTest::DoubleMessageSerializeTest_data()
{
QTest::addColumn<double>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("double_value_0_1") << 0.1 << qsizetype(23)
QTest::newRow("double_value_0_1") << 0.1
<< "{\"testFieldDouble\":0.1}"_ba;
QTest::newRow("double_value_min")
<< std::numeric_limits<double>::min() << qsizetype(40)
<< "{\"testFieldDouble\":2.2250738585072e-308}"_ba;
<< std::numeric_limits<double>::min()
<< "{\"testFieldDouble\":2.2250738585072014e-308}"_ba;
QTest::newRow("double_value_max")
<< std::numeric_limits<double>::max() << qsizetype(40)
<< "{\"testFieldDouble\":1.7976931348623e+308}"_ba;
QTest::newRow("double_neg_value_4_2") << -4.2 << qsizetype(24)
<< std::numeric_limits<double>::max()
<< "{\"testFieldDouble\":1.7976931348623157e+308}"_ba;
QTest::newRow("double_neg_value_4_2") << -4.2
<< "{\"testFieldDouble\":-4.2}"_ba;
QTest::newRow("double_value_0_0") << 0.0 << qsizetype(21)
QTest::newRow("double_value_0_0") << 0.0
<< "{\"testFieldDouble\":0}"_ba;
}
void QtProtobufTypesJsonSerializationTest::DoubleMessageSerializeTest()
{
QFETCH(const double, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleDoubleMessage test;
test.setTestFieldDouble(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
@ -469,16 +422,16 @@ void QtProtobufTypesJsonSerializationTest::ComplexTypeSerializeTest_data()
QTest::newRow("empty_value")
<< 0 << ""
<< "{\"testFieldInt\":0,\"testComplexField\":{\"testFieldString\":\"\"}}"_ba;
<< "{\"testComplexField\":{\"testFieldString\":\"\"},\"testFieldInt\":0}"_ba;
QTest::newRow("value_only_int")
<< 42 << ""
<< "{\"testFieldInt\":42,\"testComplexField\":{\"testFieldString\":\"\"}}"_ba;
<< "{\"testComplexField\":{\"testFieldString\":\"\"},\"testFieldInt\":42}"_ba;
QTest::newRow("value_only_string")
<< 0 << "qwerty"
<< "{\"testFieldInt\":0,\"testComplexField\":{\"testFieldString\":\"qwerty\"}}"_ba;
<< "{\"testComplexField\":{\"testFieldString\":\"qwerty\"},\"testFieldInt\":0}"_ba;
QTest::newRow("int_and_string")
<< 42 << "qwerty"
<< "{\"testFieldInt\":42,\"testComplexField\":{\"testFieldString\":\"qwerty\"}}"_ba;
<< "{\"testComplexField\":{\"testFieldString\":\"qwerty\"},\"testFieldInt\":42}"_ba;
QTest::newRow("int_and_big_string")
<< 42
<< "YVRfJvjxqbgvFwS1YvOZXgtj5ffGLS7AiNHz9oZIoKbm7z8H79xBuyPkpQXvGoO09OY9xRawx3eOAs9xjo"
@ -488,17 +441,17 @@ void QtProtobufTypesJsonSerializationTest::ComplexTypeSerializeTest_data()
"5gVS2g7AQ7rkm72cBdnW9sCEyGabeXAuH5j4GRbuLT7qBZWDcFLF4SsCdS3WfFGdNHfwaijzykByo71PvF"
"VlTXH2WJWoFvR5FALjBTn7bCdP0pAiSbLCY8Xz2Msc3dBb5Ff9GISPbUpNmUvBdMZMHQvqOmTNXEPpN0b7"
"4MDOMQfWJShOo3NkAvMjs"
<< "{\"testFieldInt\":42,\"testComplexField\":{\"testFieldString\":\"YVRfJvjxqbgvFwS1Y"
<< "{\"testComplexField\":{\"testFieldString\":\"YVRfJvjxqbgvFwS1Y"
"vOZXgtj5ffGLS7AiNHz9oZIoKbm7z8H79xBuyPkpQXvGoO09OY9xRawx3eOAs9xjoTA1xJhrw28TAcq1Ce"
"bYlC9WUfQC6hIantaNdyHiKToffi0Zt7la42SRxXZSP4GuxbcZIp53pJnyCwfCy1qdFczT0dmn7h8fpyAd"
"emEavwFeda4d0PApGfSU2jLt39X8kYUBxNM2WgALRBgHdVde87q6Pi5U69TjhMd28W1SFD1DxyogCCrqOc"
"t2ZPICoLnrqdF3OdNzjRVLfeyvQ8LgLvRNFR9WfWAyAz79nKgBamd8Ntlvt4Mg35E5gVS2g7AQ7rkm72cB"
"dnW9sCEyGabeXAuH5j4GRbuLT7qBZWDcFLF4SsCdS3WfFGdNHfwaijzykByo71PvFVlTXH2WJWoFvR5FAL"
"jBTn7bCdP0pAiSbLCY8Xz2Msc3dBb5Ff9GISPbUpNmUvBdMZMHQvqOmTNXEPpN0b74MDOMQfWJShOo3NkA"
"vMjs\"}}"_ba;
"vMjs\"},\"testFieldInt\":42}"_ba;
QTest::newRow("neg_int_and_string")
<< -45 << "qwerty"
<< "{\"testFieldInt\":-45,\"testComplexField\":{\"testFieldString\":\"qwerty\"}}"_ba;
<< "{\"testComplexField\":{\"testFieldString\":\"qwerty\"},\"testFieldInt\":-45}"_ba;
}
void QtProtobufTypesJsonSerializationTest::ComplexTypeSerializeTest()
@ -528,14 +481,13 @@ void QtProtobufTypesJsonSerializationTest::ResetComplexTypeSerializeTest_data()
QTest::addColumn<QString>("stringField");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("empty_value")
<< 0 << u""_s << "{\"testFieldInt\":0,\"testComplexField\":{}}"_ba;
QTest::newRow("empty_value") << 0 << u""_s << "{\"testComplexField\":{},\"testFieldInt\":0}"_ba;
QTest::newRow("value_only_int")
<< 42 << u""_s << "{\"testFieldInt\":42,\"testComplexField\":{}}"_ba;
<< 42 << u""_s << "{\"testComplexField\":{},\"testFieldInt\":42}"_ba;
QTest::newRow("value_only_string")
<< 0 << u"qwerty"_s << "{\"testFieldInt\":0,\"testComplexField\":{}}"_ba;
<< 0 << u"qwerty"_s << "{\"testComplexField\":{},\"testFieldInt\":0}"_ba;
QTest::newRow("int_and_string")
<< 42 << u"qwerty"_s << "{\"testFieldInt\":42,\"testComplexField\":{}}"_ba;
<< 42 << u"qwerty"_s << "{\"testComplexField\":{},\"testFieldInt\":42}"_ba;
}
void QtProtobufTypesJsonSerializationTest::ResetComplexTypeSerializeTest()
@ -561,7 +513,7 @@ void QtProtobufTypesJsonSerializationTest::DefaultConstructedComplexTypeSerializ
{
ComplexMessage test;
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testFieldInt\":0,\"testComplexField\":{}}"_ba);
QCOMPARE(result, "{\"testComplexField\":{},\"testFieldInt\":0}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}

View File

@ -87,7 +87,9 @@ void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedInt64MessageTest()
RepeatedInt64Message test;
test.setTestRepeatedInt({1, 321, -65999, 12324523123123, -3, 0, 3});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,-65999,12324523123123,-3,0,3]}"_ba);
QCOMPARE(
result,
"{\"testRepeatedInt\":[\"1\",\"321\",\"-65999\",\"12324523123123\",\"-3\",\"0\",\"3\"]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::int64List());
@ -101,7 +103,9 @@ void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedSInt64MessageTest()
RepeatedSInt64Message test;
test.setTestRepeatedInt({1, 321, -65999, 12324523123123, 0, -3, 3});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,-65999,12324523123123,0,-3,3]}"_ba);
QCOMPARE(
result,
"{\"testRepeatedInt\":[\"1\",\"321\",\"-65999\",\"12324523123123\",\"0\",\"-3\",\"3\"]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::sint64List());
@ -115,7 +119,9 @@ void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedUInt64MessageTest()
RepeatedUInt64Message test;
test.setTestRepeatedInt({1, 321, 0, 65999, 123245, 123245324235425234, 3});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,0,65999,123245,123245324235425234,3]}"_ba);
QCOMPARE(
result,
"{\"testRepeatedInt\":[\"1\",\"321\",\"0\",\"65999\",\"123245\",\"123245324235425234\",\"3\"]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::uint64List());
@ -157,7 +163,9 @@ void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedFixedInt64MessageTest
RepeatedFixedInt64Message test;
test.setTestRepeatedInt({1, 321, 65999, 123245324235425234, 3, 3, 0});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,65999,123245324235425234,3,3,0]}"_ba);
QCOMPARE(
result,
"{\"testRepeatedInt\":[\"1\",\"321\",\"65999\",\"123245324235425234\",\"3\",\"3\",\"0\"]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::fixed64List());
@ -171,7 +179,9 @@ void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedSFixedInt64MessageTes
RepeatedSFixedInt64Message test;
test.setTestRepeatedInt({1, 321, -65999, 123245324235425234, -3, 3, 0});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,-65999,123245324235425234,-3,3,0]}"_ba);
QCOMPARE(
result,
"{\"testRepeatedInt\":[\"1\",\"321\",\"-65999\",\"123245324235425234\",\"-3\",\"3\",\"0\"]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::sfixed64List());
@ -198,10 +208,10 @@ void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedStringMessageTest()
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedFloatMessageTest()
{
RepeatedFloatMessage test;
test.setTestRepeatedFloat({0.4f, 1.2f, 0.5f, 3.912348f, 0.6f});
test.setTestRepeatedFloat({ 0.4f, 1.2f, 0.5f, 3.91235f, 0.6f });
QByteArray result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result, "{\"testRepeatedFloat\":[0.4,1.2,0.5,3.912348,0.6]}"_ba);
QCOMPARE(result, "{\"testRepeatedFloat\":[0.4,1.2,0.5,3.91235,0.6]}"_ba);
test.setTestRepeatedFloat(QtProtobuf::floatList());
result = test.serialize(m_serializer.get());
@ -261,16 +271,14 @@ void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedComplexMessageTest()
test.setTestRepeatedComplex({msg, msg, msg});
QByteArray result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result,
"{\"testRepeatedComplex\":[{\"testFieldInt\":25,\"testComplexField\":"
"{\"testFieldString\":\"qwerty\"}},{\"testFieldInt\":25,\"testComplexField\":"
"{\"testFieldString\":\"qwerty\"}},{\"testFieldInt\":25,\"testComplexField\":"
"{\"testFieldString\":\"qwerty\"}}]}"_ba);
QCOMPARE(
result,
"{\"testRepeatedComplex\":[{\"testComplexField\":{\"testFieldString\":\"qwerty\"},\"testFieldInt\":25},{\"testComplexField\":{\"testFieldString\":\"qwerty\"},\"testFieldInt\":25},{\"testComplexField\":{\"testFieldString\":\"qwerty\"},\"testFieldInt\":25}]}"_ba);
test.setTestRepeatedComplex({});
result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result, "{\"testRepeatedComplex\":[]}"_ba);
QCOMPARE(result, "{}"_ba);
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedBoolMessageTest()

View File

@ -49,7 +49,7 @@ void tst_protobuf_any::simpleMessage()
payload.setI(42);
AnyMessage message;
message.setField(QtProtobuf::Any::fromMessage(payload));
message.setField(QtProtobuf::Any::fromMessage(&serializer, payload));
QByteArray serialized = message.serialize(&serializer);
QCOMPARE_EQ(serialized.toHex(),
"0a380a2f747970652e676f6f676c65617069732e636f6d2f717470726f74"
@ -58,7 +58,7 @@ void tst_protobuf_any::simpleMessage()
AnyMessage message2;
message2.deserialize(&serializer, serialized);
auto result = message2.field().as<SimpleMessage>();
auto result = message2.field().as<SimpleMessage>(&serializer);
QVERIFY(result.has_value());
QCOMPARE_EQ(result.value(), payload);
}
@ -97,7 +97,7 @@ void tst_protobuf_any::anyMessage()
message.deserialize(&serializer, input);
QCOMPARE_EQ(serializer.deserializationError(), QAbstractProtobufSerializer::NoError);
std::optional<Example> opt = message.field().as<Example>();
std::optional<Example> opt = message.field().as<Example>(&serializer);
QVERIFY(opt.has_value());
Example ex = std::move(opt).value();
QTEST(ex.str(), "str");
@ -124,7 +124,7 @@ void tst_protobuf_any::repeatedAnyMessage()
QCOMPARE_EQ(message.anys().size(), 3);
for (const QtProtobuf::Any &any : message.anys()) {
std::optional<Example> opt = any.as<Example>();
std::optional<Example> opt = any.as<Example>(&serializer);
QVERIFY(opt.has_value());
Example ex = std::move(opt).value();
QCOMPARE_EQ(ex.str(), "Hello");
@ -177,7 +177,7 @@ void tst_protobuf_any::twoAnyMessage()
TwoAnyMessage message;
message.deserialize(&serializer, serializedData);
std::optional<Example> opt = message.two().as<Example>();
std::optional<Example> opt = message.two().as<Example>(&serializer);
QVERIFY(opt);
const Example &ex = opt.value();
QCOMPARE_EQ(ex.str(), "Hello");
@ -188,12 +188,12 @@ void tst_protobuf_any::twoAnyMessage()
if (nested) {
// The Any-message contains another Any inside:
std::optional<QtProtobuf::Any> anyOpt = message.one().as<QtProtobuf::Any>();
std::optional<QtProtobuf::Any> anyOpt = message.one().as<QtProtobuf::Any>(&serializer);
QVERIFY(anyOpt);
// But the nested Any-message is empty:
QCOMPARE_EQ(anyOpt->value(), QByteArray());
} else {
std::optional<QtProtobuf::Any> nestedAny = message.one().as<QtProtobuf::Any>();
std::optional<QtProtobuf::Any> nestedAny = message.one().as<QtProtobuf::Any>(&serializer);
QVERIFY(!nestedAny); // not nested
// and the value of the field is empty:
QCOMPARE_EQ(message.one().value(), QByteArray());
@ -202,11 +202,12 @@ void tst_protobuf_any::twoAnyMessage()
void tst_protobuf_any::fromMessage()
{
QProtobufSerializer serializer;
Example ex;
ex.setH(242);
AnyMessage message;
message.setField(QtProtobuf::Any::fromMessage(ex));
std::optional<Example> exop = message.field().as<Example>();
message.setField(QtProtobuf::Any::fromMessage(&serializer, ex));
std::optional<Example> exop = message.field().as<Example>(&serializer);
QVERIFY(exop.has_value());
QCOMPARE(exop->h(), 242);
QCOMPARE(*exop, ex);