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 qprotobufmessage.cpp qprotobufmessage.h qprotobufmessage_p.h
qprotobuflazymessagepointer.h qprotobuflazymessagepointer.h
qprotobufobject.h qprotobufobject.h
qprotobufselfcheckiterator.h qprotobufselfcheckiterator_p.h
qprotobufserializer.cpp qprotobufserializer.h qprotobufserializer_p.h qprotobufserializer.cpp qprotobufserializer.h qprotobufserializer_p.h
qprotobufjsonserializer.cpp qprotobufjsonserializer.h qprotobufjsonserializer.cpp qprotobufjsonserializer.h
qtprotobuflogging.cpp qtprotobuflogging_p.h qtprotobuflogging.cpp qtprotobuflogging_p.h

View File

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

View File

@ -27,12 +27,7 @@ QT_BEGIN_NAMESPACE
*/ */
/*! /*!
Destroys this QProtobufBaseSerializer. \fn void QProtobufBaseSerializer::serializeObject(const QProtobufMessage *message,
*/
QProtobufBaseSerializer::~QProtobufBaseSerializer() = default;
/*!
\fn QByteArray QProtobufBaseSerializer::serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const
@ -40,19 +35,115 @@ QProtobufBaseSerializer::~QProtobufBaseSerializer() = default;
with defined \a ordering and \a fieldInfo, that is recognized with defined \a ordering and \a fieldInfo, that is recognized
like an object, into a QByteArray. \a message must not be \nullptr. 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, \fn bool QProtobufBaseSerializer::deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const
This function deserializes a registered Protobuf message \a message 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. 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 #define QPROTOBUFSBASEERIALIZER_H
#include <QtProtobuf/qabstractprotobufserializer.h> #include <QtProtobuf/qabstractprotobufserializer.h>
#include <QtProtobuf/qprotobufselfcheckiterator.h>
#include <QtCore/QList> #include <QtCore/QList>
#include <QtCore/QMetaObject> #include <QtCore/QMetaObject>
@ -16,58 +15,44 @@ QT_BEGIN_NAMESPACE
class Q_PROTOBUF_EXPORT QProtobufBaseSerializer: public QAbstractProtobufSerializer class Q_PROTOBUF_EXPORT QProtobufBaseSerializer: public QAbstractProtobufSerializer
{ {
public: public:
enum Status { virtual void
Serialized = 0,
SerializationInProgress,
SerializationError
};
virtual ~QProtobufBaseSerializer();
virtual QByteArray
serializeObject(const QProtobufMessage *message, serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0; const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual bool deserializeObject(QProtobufMessage *message, virtual bool
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, deserializeObject(QProtobufMessage *message,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0; const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const = 0;
virtual QByteArray virtual void serializeListObject(const QProtobufMessage *message,
serializeListObject(const QList<const QProtobufMessage*> &messageList,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0; const QtProtobufPrivate::QProtobufPropertyOrderingInfo
virtual Status &fieldInfo) const = 0;
virtual bool
deserializeListObject(QProtobufMessage *message, deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const = 0;
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
virtual QByteArray virtual void
serializeMapPair(const QList<QPair<QVariant, QVariant>> &list, serializeMapPair(const QVariant &key, const QVariant &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0; const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual Status deserializeMapPair(QVariant &key, QVariant &value, virtual bool deserializeMapPair(QVariant &key, QVariant &value) const = 0;
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
virtual QByteArray virtual void
serializeEnum(QtProtobuf::int64 value, serializeEnum(QtProtobuf::int64 value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0; const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual QByteArray virtual void
serializeEnumList(const QList<QtProtobuf::int64> &value, serializeEnumList(const QList<QtProtobuf::int64> &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0; const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual bool deserializeEnum(QtProtobuf::int64 &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0; virtual bool deserializeEnum(QtProtobuf::int64 &value) const = 0;
virtual bool virtual bool deserializeEnumList(QList<QtProtobuf::int64> &value) const = 0;
deserializeEnumList(QList<QtProtobuf::int64> &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
}; };
namespace QtProtobufPrivate { namespace QtProtobufPrivate {
using Serializer = void (*)(const QProtobufBaseSerializer *, const QVariant &, using Serializer = void (*)(const QProtobufBaseSerializer *, const QVariant &,
const QProtobufPropertyOrderingInfo &, QByteArray &); const QProtobufPropertyOrderingInfo &);
using Deserializer = void (*)(const QProtobufBaseSerializer *, QProtobufSelfcheckIterator &, using Deserializer = void (*)(const QProtobufBaseSerializer *, QVariant &);
QVariant &);
/*! /*!
\private \private
@ -90,10 +75,10 @@ extern Q_PROTOBUF_EXPORT void registerHandler(QMetaType type, const Serializatio
template <typename T, template <typename T,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, T>::value, int> = 0> typename std::enable_if_t<std::is_base_of<QProtobufMessage, T>::value, int> = 0>
void serializeObject(const QProtobufBaseSerializer *serializer, const QVariant &value, 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"); 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, template <typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0> typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeList(const QProtobufBaseSerializer *serializer, const QVariant &listValue, 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"); Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
QList<V> objList = listValue.value<QList<V>>(); for (const auto &value : listValue.value<QList<V>>()) {
QList<const QProtobufMessage*> messageList; serializer->serializeListObject(&value, V::propertyOrdering, fieldInfo);
for (const auto &value : objList) }
messageList.append(&value);
buffer.append(serializer->serializeListObject(messageList, V::propertyOrdering, fieldInfo));
} }
/*! /*!
@ -120,17 +103,13 @@ void serializeList(const QProtobufBaseSerializer *serializer, const QVariant &li
template <typename K, typename V, template <typename K, typename V,
typename std::enable_if_t<!std::is_base_of<QProtobufMessage, V>::value, int> = 0> typename std::enable_if_t<!std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeMap(const QProtobufBaseSerializer *serializer, const QVariant &value, 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"); Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
QHash<K, V> original = value.value<QHash<K, V>>(); for (const auto &[k, v] : value.value<QHash<K, V>>().asKeyValueRange()) {
QList<QPair<QVariant, QVariant>> variantContainer; serializer->serializeMapPair(QVariant::fromValue<K>(k), QVariant::fromValue<V>(v),
for (const auto &[k, v] : original.asKeyValueRange()) { fieldInfo);
variantContainer.append(qMakePair(QVariant::fromValue<K>(k),
QVariant::fromValue<V>(v)));
} }
buffer.append(serializer->serializeMapPair(variantContainer, fieldInfo));
} }
/*! /*!
@ -141,17 +120,13 @@ void serializeMap(const QProtobufBaseSerializer *serializer, const QVariant &val
template <typename K, typename V, template <typename K, typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0> typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeMap(const QProtobufBaseSerializer *serializer, const QVariant &value, 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"); Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
QHash<K, V> original = value.value<QHash<K, V>>(); for (const auto &[k, v] : value.value<QHash<K, V>>().asKeyValueRange()) {
QList<QPair<QVariant, QVariant>> variantContainer; serializer->serializeMapPair(QVariant::fromValue<K>(k), QVariant::fromValue<V *>(&v),
for (const auto &[k, v] : original.asKeyValueRange()) { fieldInfo);
variantContainer.append(qMakePair(QVariant::fromValue<K>(k),
QVariant::fromValue<V *>(&v)));
} }
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> template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void serializeEnum(const QProtobufBaseSerializer *serializer, const QVariant &value, 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"); 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> template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void serializeEnumList(const QProtobufBaseSerializer *serializer, const QVariant &value, 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"); Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QList<QtProtobuf::int64> intList; QList<QtProtobuf::int64> intList;
for (auto enumValue : value.value<QList<T>>()) { for (auto enumValue : value.value<QList<T>>()) {
intList.append(QtProtobuf::int64(enumValue)); 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, template <typename T,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, T>::value, int> = 0> typename std::enable_if_t<std::is_base_of<QProtobufMessage, T>::value, int> = 0>
void deserializeObject(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it, void deserializeObject(const QProtobufBaseSerializer *serializer, QVariant &to)
QVariant &to)
{ {
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null"); Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
Q_ASSERT_X(to.isNull() || to.metaType() == QMetaType::fromType<T *>(), Q_ASSERT_X(to.isNull() || to.metaType() == QMetaType::fromType<T *>(),
@ -201,7 +175,7 @@ void deserializeObject(const QProtobufBaseSerializer *serializer, QProtobufSelfc
value = new T; value = new T;
to = QVariant::fromValue<T *>(value); 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, template <typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0> typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeList(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it, void deserializeList(const QProtobufBaseSerializer *serializer, QVariant &previous)
QVariant &previous)
{ {
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null"); Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
V newValue; V newValue;
QProtobufBaseSerializer::Status result = QProtobufBaseSerializer::SerializationError; serializer->deserializeListObject(&newValue, V::propertyOrdering);
do {
result = serializer->deserializeListObject(&newValue, V::propertyOrdering, it);
QList<V> list = previous.value<QList<V>>(); QList<V> list = previous.value<QList<V>>();
list.append(newValue); list.append(newValue);
previous.setValue(list); previous.setValue(list);
} while (result == QProtobufBaseSerializer::SerializationInProgress);
} }
/*! /*!
@ -232,8 +202,7 @@ void deserializeList(const QProtobufBaseSerializer *serializer, QProtobufSelfche
*/ */
template <typename K, typename V, template <typename K, typename V,
typename std::enable_if_t<!std::is_base_of<QProtobufMessage, V>::value, int> = 0> typename std::enable_if_t<!std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it, void deserializeMap(const QProtobufBaseSerializer *serializer, QVariant &previous)
QVariant &previous)
{ {
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null"); 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 key = QVariant::fromValue<K>(K());
QVariant value = QVariant::fromValue<V>(V()); 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>(); out[key.value<K>()] = value.value<V>();
previous = QVariant::fromValue<QHash<K, V>>(out); previous = QVariant::fromValue<QHash<K, V>>(out);
} }
@ -255,8 +224,7 @@ void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfchec
*/ */
template <typename K, typename V, template <typename K, typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0> typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it, void deserializeMap(const QProtobufBaseSerializer *serializer, QVariant &previous)
QVariant &previous)
{ {
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null"); 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 key = QVariant::fromValue<K>(K());
QVariant value = QVariant::fromValue<V *>(nullptr); 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 *>(); const auto valuePtr = value.value<V *>();
out[key.value<K>()] = valuePtr ? *valuePtr : V(); out[key.value<K>()] = valuePtr ? *valuePtr : V();
previous = QVariant::fromValue<QHash<K, V>>(out); 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 \brief default deserializer template for enum type T
*/ */
template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0> template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void deserializeEnum(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it, void deserializeEnum(const QProtobufBaseSerializer *serializer, QVariant &to)
QVariant &to)
{ {
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null"); Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QtProtobuf::int64 intValue; QtProtobuf::int64 intValue;
if (serializer->deserializeEnum(intValue, it)) if (serializer->deserializeEnum(intValue))
to = QVariant::fromValue<T>(static_cast<T>(intValue._t)); 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 \brief default deserializer template for enumList type T
*/ */
template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0> template <typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void deserializeEnumList(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it, void deserializeEnumList(const QProtobufBaseSerializer *serializer, QVariant &previous)
QVariant &previous)
{ {
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null"); Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QList<QtProtobuf::int64> intList; QList<QtProtobuf::int64> intList;
if (!serializer->deserializeEnumList(intList, it)) if (!serializer->deserializeEnumList(intList))
return; return;
QList<T> enumList = previous.value<QList<T>>(); QList<T> enumList = previous.value<QList<T>>();
for (auto intValue : intList) for (auto intValue : intList)

View File

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

View File

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

View File

@ -2,11 +2,22 @@
// Copyright (C) 2019 Alexey Edelev <semlanik@gmail.com> // 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 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROTOBUFSELFCHECKITERATOR_H #ifndef QPROTOBUFSELFCHECKITERATOR_P_H
#define QPROTOBUFSELFCHECKITERATOR_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 <QtCore/qnumeric.h>
#include <QtProtobuf/qtprotobufglobal.h>
#include <QtCore/QByteArray> #include <QtCore/QByteArray>
@ -14,7 +25,6 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace QtProtobufPrivate {
class QProtobufSelfcheckIterator class QProtobufSelfcheckIterator
{ {
public: public:
@ -24,6 +34,8 @@ public:
using pointer = QByteArray::pointer; using pointer = QByteArray::pointer;
using reference = QByteArray::reference; using reference = QByteArray::reference;
QProtobufSelfcheckIterator() = default;
static QProtobufSelfcheckIterator fromView(QByteArrayView container) static QProtobufSelfcheckIterator fromView(QByteArrayView container)
{ {
QProtobufSelfcheckIterator iter(container); QProtobufSelfcheckIterator iter(container);
@ -104,8 +116,7 @@ public:
private: private:
explicit QProtobufSelfcheckIterator(QByteArrayView container) explicit QProtobufSelfcheckIterator(QByteArrayView container)
: m_containerBegin(container.begin()), : m_containerBegin(container.begin()), m_containerEnd(container.end()),
m_containerEnd(container.end()),
m_it(container.begin()) m_it(container.begin())
{ {
} }
@ -162,8 +173,7 @@ inline QProtobufSelfcheckIterator operator-(const QProtobufSelfcheckIterator &it
copy -= length; copy -= length;
return copy; return copy;
} }
} // namespace QtProtobufPrivate
QT_END_NAMESPACE 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; 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( QByteArray QProtobufSerializer::serializeMessage(
const QProtobufMessage *message, const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const 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) { for (int index = 0; index < ordering.fieldCount(); ++index) {
int fieldIndex = ordering.getFieldNumber(index); int fieldIndex = ordering.getFieldNumber(index);
Q_ASSERT_X(fieldIndex < 536870912 && fieldIndex > 0, "", "fieldIndex is out of range"); Q_ASSERT_X(fieldIndex < 536870912 && fieldIndex > 0, "", "fieldIndex is out of range");
QProtobufPropertyOrderingInfo fieldInfo(ordering, index); QProtobufPropertyOrderingInfo fieldInfo(ordering, index);
QVariant propertyValue = message->property(fieldInfo); 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: // Restore any unknown fields we have stored away:
const QProtobufMessagePrivate *messagePrivate = QProtobufMessagePrivate::get(message); const QProtobufMessagePrivate *messagePrivate = QProtobufMessagePrivate::get(message);
for (const auto &fields : messagePrivate->unknownEntries) for (const auto &fields : messagePrivate->unknownEntries)
result += fields.join(); result += fields.join();
} }
return result;
} }
void QProtobufSerializerPrivate::setUnexpectedEndOfStreamError() void QProtobufSerializerPrivate::setUnexpectedEndOfStreamError()
@ -297,197 +297,131 @@ void QProtobufSerializerPrivate::clearError()
deserializationErrorString.clear(); 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( bool QProtobufSerializer::deserializeMessage(
QProtobufMessage *message, const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, QProtobufMessage *message, const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QByteArrayView data) const QByteArrayView data) const
{ {
d_ptr->clearError(); d_ptr->clearError();
auto it = QProtobufSelfcheckIterator::fromView(data); d_ptr->it = QProtobufSelfcheckIterator::fromView(data);
while (it.isValid() && it != data.end()) { while (d_ptr->it.isValid() && d_ptr->it != data.end()) {
if (!d_ptr->deserializeProperty(message, ordering, it)) if (!d_ptr->deserializeProperty(message, ordering))
return false; return false;
} }
if (!it.isValid()) if (!d_ptr->it.isValid())
d_ptr->setUnexpectedEndOfStreamError(); d_ptr->setUnexpectedEndOfStreamError();
return it.isValid(); return d_ptr->it.isValid();
} }
/*! void QProtobufSerializer::serializeObject(const QProtobufMessage *message,
Serialize an \a message with \a ordering and \a fieldInfo. const QtProtobufPrivate::QProtobufPropertyOrdering
Returns a QByteArray containing the serialized message. &ordering,
You should not call this function directly.
*/
QByteArray
QProtobufSerializer::serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QProtobufPropertyOrderingInfo &fieldInfo) const const QProtobufPropertyOrderingInfo &fieldInfo) const
{ {
QByteArray result = QProtobufSerializerPrivate::prependLengthDelimitedSize( auto store = d_ptr->result;
serializeMessage(message, ordering)); d_ptr->result = {};
result.prepend(QProtobufSerializerPrivate::encodeHeader( d_ptr->serializeMessage(message, ordering);
fieldInfo.getFieldNumber(), QtProtobuf::WireTypes::LengthDelimited)); store.append(QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(),
return result; 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, bool QProtobufSerializer::deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, const QtProtobufPrivate::QProtobufPropertyOrdering
QProtobufSelfcheckIterator &it) const &ordering) const
{ {
if (it.bytesLeft() == 0) { if (d_ptr->it.bytesLeft() == 0) {
d_ptr->setUnexpectedEndOfStreamError(); d_ptr->setUnexpectedEndOfStreamError();
return false; return false;
} }
std::optional<QByteArray> array = QProtobufSerializerPrivate::deserializeLengthDelimited(it); std::optional<QByteArray>
array = QProtobufSerializerPrivate::deserializeLengthDelimited(d_ptr->it);
if (!array) { if (!array) {
d_ptr->setUnexpectedEndOfStreamError(); d_ptr->setUnexpectedEndOfStreamError();
return false; return false;
} }
return deserializeMessage(message, ordering, array.value()); auto store = d_ptr->it;
} bool result = deserializeMessage(message, ordering, array.value());
d_ptr->it = store;
/*!
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));
return result; return result;
} }
/*! void QProtobufSerializer::serializeListObject(const QProtobufMessage *message,
This function deserializes an \a message from byte stream as part of list property, with const QtProtobufPrivate::QProtobufPropertyOrdering
\a ordering from a QProtobufSelfcheckIterator \a it. &ordering,
Returns \c Serialized if deserialization was successful, const QProtobufPropertyOrderingInfo &fieldInfo) const
otherwise \c SerializationError. {
serializeObject(message, ordering, fieldInfo);
You should not call this function directly. }
*/
QProtobufBaseSerializer::Status QProtobufSerializer::deserializeListObject(QProtobufMessage *message, bool QProtobufSerializer::deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, const QtProtobufPrivate::QProtobufPropertyOrdering
QProtobufSelfcheckIterator &it) const &ordering) const
{ {
if (deserializeObject(message, ordering, it)) return deserializeObject(message, ordering);
return QProtobufBaseSerializer::Serialized; }
else
return QProtobufBaseSerializer::SerializationError; void QProtobufSerializer::serializeMapPair(const QVariant &key, const QVariant &value,
}
/*!
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,
const QProtobufPropertyOrderingInfo &fieldInfo) const const QProtobufPropertyOrderingInfo &fieldInfo) const
{ {
QByteArray result;
for (const auto &element : list) {
const QVariant &key = element.first;
auto keyHandler = findIntegratedTypeHandler(key.metaType(), false); auto keyHandler = findIntegratedTypeHandler(key.metaType(), false);
Q_ASSERT_X(keyHandler, "QProtobufSerializer", "Map key is not an integrated type."); Q_ASSERT_X(keyHandler, "QProtobufSerializer", "Map key is not an integrated type.");
auto store = d_ptr->result;
result.append(QProtobufSerializerPrivate::encodeHeader( d_ptr->result = {};
fieldInfo.getFieldNumber(), QtProtobuf::WireTypes::LengthDelimited)); d_ptr->result
.append(keyHandler
result.append(QProtobufSerializerPrivate::prependLengthDelimitedSize( ->serializer(key,
keyHandler->serializer( QProtobufSerializerPrivate::encodeHeader(1,
key, QProtobufSerializerPrivate::encodeHeader(1, keyHandler->wireType)) keyHandler->wireType)));
+ d_ptr->serializeProperty(element.second, fieldInfo.infoForMapValue()))); d_ptr->serializeProperty(value, fieldInfo.infoForMapValue());
} store.append(QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(),
return result; QtProtobuf::WireTypes::LengthDelimited));
store.append(QProtobufSerializerPrivate::serializeVarintCommon<uint32_t>(d_ptr->result.size()));
store.append(d_ptr->result);
d_ptr->result = store;
} }
/*! bool QProtobufSerializer::deserializeMapPair(QVariant &key, QVariant &value) const
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
{ {
if (d_ptr->deserializeMapPair(key, value, it)) return d_ptr->deserializeMapPair(key, value);
return QProtobufBaseSerializer::Serialized;
else
return QProtobufBaseSerializer::SerializationError;
} }
/*! void QProtobufSerializer::serializeEnum(QtProtobuf::int64 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,
const QProtobufPropertyOrderingInfo &fieldInfo) const const QProtobufPropertyOrderingInfo &fieldInfo) const
{ {
if (value == 0 && !isOneofOrOptionalField(fieldInfo)) if (value == 0 && !isOneofOrOptionalField(fieldInfo))
return {}; return;
QtProtobuf::WireTypes type = QtProtobuf::WireTypes::Varint; QtProtobuf::WireTypes type = QtProtobuf::WireTypes::Varint;
int fieldNumber = fieldInfo.getFieldNumber(); int fieldNumber = fieldInfo.getFieldNumber();
return QProtobufSerializerPrivate::encodeHeader(fieldNumber, type) d_ptr->result.append(QProtobufSerializerPrivate::encodeHeader(fieldNumber, type)
+ QProtobufSerializerPrivate::serializeBasic<QtProtobuf::int64>(value); + QProtobufSerializerPrivate::serializeBasic<QtProtobuf::int64>(value));
} }
/*! void QProtobufSerializer::serializeEnumList(const QList<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,
const QProtobufPropertyOrderingInfo &fieldInfo) const const QProtobufPropertyOrderingInfo &fieldInfo) const
{ {
if (value.isEmpty()) { if (value.isEmpty())
return {}; return;
}
auto header = QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(), auto header = QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(),
QtProtobuf::WireTypes::LengthDelimited); QtProtobuf::WireTypes::LengthDelimited);
if (fieldInfo.getFieldFlags() & QtProtobufPrivate::NonPacked) if (fieldInfo.getFieldFlags() & QtProtobufPrivate::NonPacked)
return QProtobufSerializerPrivate::serializeNonPackedList<QtProtobuf::int64>(value, header); d_ptr->result
.append(QProtobufSerializerPrivate::serializeNonPackedList<QtProtobuf::int64>(value,
return header + QProtobufSerializerPrivate::serializeListType<QtProtobuf::int64>(value); header));
else
d_ptr->result
.append(header
+ QProtobufSerializerPrivate::serializeListType<QtProtobuf::int64>(value));
} }
/*! bool QProtobufSerializer::deserializeEnum(QtProtobuf::int64 &value) const
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
{ {
QVariant variantValue; QVariant variantValue;
if (!QProtobufSerializerPrivate::deserializeBasic<QtProtobuf::int64>(it, variantValue)) { if (!QProtobufSerializerPrivate::deserializeBasic<QtProtobuf::int64>(d_ptr->it, variantValue)) {
d_ptr->setUnexpectedEndOfStreamError(); d_ptr->setUnexpectedEndOfStreamError();
return false; return false;
} }
@ -495,16 +429,10 @@ bool QProtobufSerializer::deserializeEnum(QtProtobuf::int64 &value, QProtobufSel
return true; return true;
} }
/*! bool QProtobufSerializer::deserializeEnumList(QList<QtProtobuf::int64> &value) const
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
{ {
QVariant variantValue; QVariant variantValue;
if (!QProtobufSerializerPrivate::deserializeList<QtProtobuf::int64>(it, variantValue)) { if (!QProtobufSerializerPrivate::deserializeList<QtProtobuf::int64>(d_ptr->it, variantValue)) {
d_ptr->setUnexpectedEndOfStreamError(); d_ptr->setUnexpectedEndOfStreamError();
return false; return false;
} }
@ -517,6 +445,7 @@ QProtobufSerializerPrivate::QProtobufSerializerPrivate(QProtobufSerializer *q) :
} }
/*! /*!
\internal
Encode a property field index and its type into output bytes. Encode a property field index and its type into output bytes.
Header byte Header byte
@ -537,13 +466,13 @@ QByteArray QProtobufSerializerPrivate::encodeHeader(int fieldIndex,
} }
/*! /*!
\internal
Decode a property field index and its serialization type from input bytes Decode a property field index and its serialization type from input bytes
Iterator: that points to header with encoded field index and serialization type Iterator: that points to header with encoded field index and serialization type
fieldIndex: Decoded index of a property in parent object fieldIndex: Decoded index of a property in parent object
wireType: Decoded serialization type used for the property with index 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, bool QProtobufSerializerPrivate::decodeHeader(QProtobufSelfcheckIterator &it,
int &fieldIndex, int &fieldIndex,
@ -610,8 +539,7 @@ qsizetype QProtobufSerializerPrivate::skipSerializedFieldBytes(QProtobufSelfchec
return std::distance(initialIt, QByteArray::const_iterator(it)); return std::distance(initialIt, QByteArray::const_iterator(it));
} }
QByteArray void QProtobufSerializerPrivate::serializeProperty(const QVariant &propertyValue,
QProtobufSerializerPrivate::serializeProperty(const QVariant &propertyValue,
const QProtobufPropertyOrderingInfo &fieldInfo) const QProtobufPropertyOrderingInfo &fieldInfo)
{ {
QMetaType metaType = propertyValue.metaType(); QMetaType metaType = propertyValue.metaType();
@ -621,7 +549,7 @@ QProtobufSerializerPrivate::serializeProperty(const QVariant &propertyValue,
if (metaType.id() == QMetaType::UnknownType || propertyValue.isNull()) { if (metaType.id() == QMetaType::UnknownType || propertyValue.isNull()) {
// Empty value // Empty value
return {}; return;
} }
auto basicHandler = findIntegratedTypeHandler( auto basicHandler = findIntegratedTypeHandler(
@ -629,29 +557,26 @@ QProtobufSerializerPrivate::serializeProperty(const QVariant &propertyValue,
if (basicHandler) { if (basicHandler) {
bool serializeUninitialized = isOneofOrOptionalField(fieldInfo); bool serializeUninitialized = isOneofOrOptionalField(fieldInfo);
if (!basicHandler->isPresent(propertyValue) && !serializeUninitialized) { if (!basicHandler->isPresent(propertyValue) && !serializeUninitialized) {
return {}; return;
} }
QByteArray header = QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(), QByteArray header = QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(),
basicHandler->wireType); basicHandler->wireType);
return basicHandler->serializer(propertyValue, header); result.append(basicHandler->serializer(propertyValue, header));
return;
} }
auto handler = QtProtobufPrivate::findHandler(metaType); auto handler = QtProtobufPrivate::findHandler(metaType);
if (!handler.serializer) { if (!handler.serializer) {
qProtoWarning() << "No serializer for type" << propertyValue.typeName(); qProtoWarning() << "No serializer for type" << propertyValue.typeName();
return {}; return;
} }
QByteArray result; handler.serializer(q_ptr, propertyValue, fieldInfo);
handler.serializer(q_ptr, propertyValue, fieldInfo, result);
return result;
} }
bool QProtobufSerializerPrivate::deserializeProperty( bool QProtobufSerializerPrivate::
QProtobufMessage *message, deserializeProperty(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, const QtProtobufPrivate::QProtobufPropertyOrdering &ordering)
QProtobufSelfcheckIterator &it)
{ {
Q_ASSERT(it.isValid() && it.bytesLeft() > 0); Q_ASSERT(it.isValid() && it.bytesLeft() > 0);
//Each iteration we expect iterator is setup to beginning of next chunk //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())); QCoreApplication::translate("QtProtobuf", error.toUtf8().data()));
return false; return false;
} }
handler.deserializer(q_ptr, it, newPropertyValue); handler.deserializer(q_ptr, newPropertyValue);
} }
return message->setProperty(fieldInfo, std::move(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; int mapIndex = 0;
QtProtobuf::WireTypes type = QtProtobuf::WireTypes::Unknown; QtProtobuf::WireTypes type = QtProtobuf::WireTypes::Unknown;
@ -797,7 +722,7 @@ bool QProtobufSerializerPrivate::deserializeMapPair(QVariant &key, QVariant &val
.arg(QLatin1String(value.typeName()))); .arg(QLatin1String(value.typeName())));
return false; return false;
} }
handler.deserializer(q_ptr, it, value); handler.deserializer(q_ptr, value);
} }
} }
} }

View File

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

View File

@ -23,19 +23,17 @@
#include <QtCore/qendian.h> #include <QtCore/qendian.h>
#include <QtCore/qvariant.h> #include <QtCore/qvariant.h>
#include <QtProtobuf/qprotobufselfcheckiterator.h> #include <QtProtobuf/private/qprotobufselfcheckiterator_p.h>
#include <QtProtobuf/qprotobufserializer.h>
#include <QtProtobuf/qtprotobuftypes.h>
#include <QtProtobuf/private/qtprotobuflogging_p.h> #include <QtProtobuf/private/qtprotobuflogging_p.h>
#include <QtProtobuf/qabstractprotobufserializer.h> #include <QtProtobuf/qabstractprotobufserializer.h>
#include <QtProtobuf/qprotobufserializer.h>
#include <QtProtobuf/qtprotobuftypes.h>
#include <optional> #include <optional>
#include <type_traits> #include <type_traits>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using QtProtobufPrivate::QProtobufSelfcheckIterator;
class QProtobufSerializerPrivate class QProtobufSerializerPrivate
{ {
// The below type trait structures help to determine the required encoding method for protobuf // 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 skipVarint(QProtobufSelfcheckIterator &it);
static void skipLengthDelimited(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); const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo);
Q_REQUIRED_RESULT Q_REQUIRED_RESULT
bool deserializeProperty(QProtobufMessage *message, bool deserializeProperty(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering, const QtProtobufPrivate::QProtobufPropertyOrdering &ordering);
QProtobufSelfcheckIterator &it);
void setDeserializationError(QAbstractProtobufSerializer::DeserializationError error, void setDeserializationError(QAbstractProtobufSerializer::DeserializationError error,
const QString &errorString); const QString &errorString);
@ -513,12 +513,15 @@ public:
void setUnexpectedEndOfStreamError(); void setUnexpectedEndOfStreamError();
Q_REQUIRED_RESULT Q_REQUIRED_RESULT
bool deserializeMapPair(QVariant &key, QVariant &value, QProtobufSelfcheckIterator &it); bool deserializeMapPair(QVariant &key, QVariant &value);
QAbstractProtobufSerializer::DeserializationError deserializationError = QAbstractProtobufSerializer::DeserializationError deserializationError =
QAbstractProtobufSerializer::NoDeserializerError; QAbstractProtobufSerializer::NoDeserializerError;
QString deserializationErrorString; QString deserializationErrorString;
QProtobufSelfcheckIterator it;
QByteArray result;
bool preserveUnknownFields = true; bool preserveUnknownFields = true;
private: private:
Q_DISABLE_COPY_MOVE(QProtobufSerializerPrivate) 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> template<typename QType, typename PType>
void registerQtTypeHandler() void registerQtTypeHandler()
{ {
registerHandler( registerHandler(QMetaType::fromType<QType>(),
QMetaType::fromType<QType>(),
{ [](const QProtobufBaseSerializer *serializer, const QVariant &value, { [](const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &info, QByteArray &buffer) { const QProtobufPropertyOrderingInfo &info) {
auto do_convert = [](const QType &qtype) { auto do_convert = [](const QType &qtype) {
auto res = convert(qtype); auto res = convert(qtype);
if constexpr (is_optional_v<decltype(res)>) { if constexpr (is_optional_v<decltype(res)>) {
@ -54,16 +53,15 @@ void registerQtTypeHandler()
std::optional<PType> object = do_convert(value.value<QType>()); std::optional<PType> object = do_convert(value.value<QType>());
if (object) { if (object) {
buffer.append(serializer->serializeObject(&(object.value()), serializer->serializeObject(&(object.value()), PType::propertyOrdering,
PType::propertyOrdering, info)); info);
} else { } else {
warnTypeConversionError(); warnTypeConversionError();
} }
}, },
[](const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it, [](const QProtobufBaseSerializer *serializer, QVariant &value) {
QVariant &value) {
PType object; PType object;
serializer->deserializeObject(&object, PType::propertyOrdering, it); serializer->deserializeObject(&object, PType::propertyOrdering);
auto res = convert(object); auto res = convert(object);
if constexpr (is_optional_v<decltype(res)>) { if constexpr (is_optional_v<decltype(res)>) {
if (!res) if (!res)
@ -73,8 +71,7 @@ void registerQtTypeHandler()
} else { } else {
value = QVariant::fromValue<QType>(res); value = QVariant::fromValue<QType>(res);
} }
} } });
});
} }
} // namespace QtProtobufPrivate } // namespace QtProtobufPrivate

View File

@ -3,7 +3,7 @@
#include <QtProtobufWellKnownTypes/qtprotobufwellknowntypesglobal.h> #include <QtProtobufWellKnownTypes/qtprotobufwellknowntypesglobal.h>
#include <QtProtobuf/qprotobufserializer.h> #include <QtProtobuf/qprotobufbaseserializer.h>
#include <QtProtobuf/private/qprotobufserializer_p.h> #include <QtProtobuf/private/qprotobufserializer_p.h>
#include "qprotobufanysupport.h" #include "qprotobufanysupport.h"
@ -25,7 +25,7 @@ public:
}; };
static void serializerProxy(const QProtobufBaseSerializer *serializer, const QVariant &object, static void serializerProxy(const QProtobufBaseSerializer *serializer, const QVariant &object,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &output) const QProtobufPropertyOrderingInfo &fieldInfo)
{ {
if (object.isNull()) if (object.isNull())
return; return;
@ -37,41 +37,28 @@ static void serializerProxy(const QProtobufBaseSerializer *serializer, const QVa
google::protobuf::Any realAny; google::protobuf::Any realAny;
realAny.setValue(any.value()); realAny.setValue(any.value());
realAny.setTypeUrl(any.typeUrl()); realAny.setTypeUrl(any.typeUrl());
output.append(serializer->serializeObject(&realAny, google::protobuf::Any::propertyOrdering, serializer->serializeObject(&realAny, google::protobuf::Any::propertyOrdering, fieldInfo);
fieldInfo));
} }
static void listSerializerProxy(const QProtobufBaseSerializer *serializer, static void listSerializerProxy(const QProtobufBaseSerializer *serializer, const QVariant &object,
const QVariant &object, const QProtobufPropertyOrderingInfo &fieldInfo)
const QProtobufPropertyOrderingInfo &fieldInfo,
QByteArray &output)
{ {
const QList<Any> anyList = object.value<QList<Any>>(); const auto anyList = object.value<QList<Any>>();
QList<const QProtobufMessage*> msgList;
msgList.reserve(anyList.size());
QList<google::protobuf::Any> msgAny;
msgAny.reserve(anyList.size());
for (const Any &any : anyList) { for (const Any &any : anyList) {
google::protobuf::Any realAny; google::protobuf::Any realAny;
realAny.setValue(any.value()); realAny.setValue(any.value());
realAny.setTypeUrl(any.typeUrl()); 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, static void listDeserializerProxy(const QProtobufBaseSerializer *deserializer, QVariant &object)
QProtobufSelfcheckIterator &it, QVariant &object)
{ {
auto anyList = object.value<QList<Any>>(); auto anyList = object.value<QList<Any>>();
const auto &ordering = google::protobuf::Any::propertyOrdering; const auto &ordering = google::protobuf::Any::propertyOrdering;
google::protobuf::Any realAny; google::protobuf::Any realAny;
if (deserializer->deserializeObject(&realAny, ordering, it)) { if (deserializer->deserializeObject(&realAny, ordering)) {
Any any; Any any;
any.setTypeUrl(realAny.typeUrl()); any.setTypeUrl(realAny.typeUrl());
any.setValue(realAny.value()); any.setValue(realAny.value());
@ -82,11 +69,10 @@ static void listDeserializerProxy(const QProtobufBaseSerializer *deserializer,
object.setValue(std::move(anyList)); object.setValue(std::move(anyList));
} }
static void deserializerProxy(const QProtobufBaseSerializer *deserializer, static void deserializerProxy(const QProtobufBaseSerializer *deserializer, QVariant &object)
QProtobufSelfcheckIterator &it, QVariant &object)
{ {
google::protobuf::Any realAny; google::protobuf::Any realAny;
if (deserializer->deserializeObject(&realAny, google::protobuf::Any::propertyOrdering, it)) { if (deserializer->deserializeObject(&realAny, google::protobuf::Any::propertyOrdering)) {
Any any; Any any;
any.setTypeUrl(realAny.typeUrl()); any.setTypeUrl(realAny.typeUrl());
any.setValue(realAny.value()); 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() 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 If the verification or deserialization fails it will return
\c{std::nullopt}. \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. \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 QtProtobufPrivate::QProtobufPropertyOrdering ordering) const
{ {
QProtobufSerializer serializer; Q_ASSERT_X(serializer != nullptr, "Any::asImpl", "serializer is null");
QString tUrl = typeUrl(); QString tUrl = typeUrl();
qsizetype lastSegmentIndex = tUrl.lastIndexOf(u'/') + 1; qsizetype lastSegmentIndex = tUrl.lastIndexOf(u'/') + 1;
if (QStringView(tUrl).mid(lastSegmentIndex).compare(ordering.getMessageFullName()) != 0) if (QStringView(tUrl).mid(lastSegmentIndex).compare(ordering.getMessageFullName()) != 0)
return false; 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; google::protobuf::Any realAny;
if (!asImpl(&realAny, google::protobuf::Any::propertyOrdering)) if (!asImpl(serializer, &realAny, google::protobuf::Any::propertyOrdering))
return std::nullopt; return std::nullopt;
Any any; Any any;
any.setTypeUrl(realAny.typeUrl()); 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 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 Any instance. This instance's typeUrl() is constructed from a prefix, a
forward slash and the message name obtained from forward slash and the message name obtained from
\c{T::propertyOrdering.getMessageFullName()}. If \a typeUrlPrefix is \c{T::propertyOrdering.getMessageFullName()} using \a serializer. If \a
supplied, it is used as prefix, otherwise \c{"type.googleapis.com"} is used. 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 \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. \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, QtProtobufPrivate::QProtobufPropertyOrdering ordering,
QAnyStringView typeUrlPrefix) QAnyStringView typeUrlPrefix)
{ {
QProtobufSerializer serializer;
Any any; Any any;
any.setValue(serializer.serializeMessage(message, ordering)); any.setValue(serializer->serializeMessage(message, ordering));
any.setTypeUrl(typeUrlPrefix.toString() + u'/' + ordering.getMessageFullName().toString()); any.setTypeUrl(typeUrlPrefix.toString() + u'/' + ordering.getMessageFullName().toString());
return { any }; return { any };
} }
// Used to handle nested Any messages. // 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; using RealAny = google::protobuf::Any;
RealAny realAny; RealAny realAny;
realAny.setTypeUrl(message->typeUrl()); realAny.setTypeUrl(message->typeUrl());
realAny.setValue(message->value()); realAny.setValue(message->value());
return fromMessageImpl(&realAny, RealAny::propertyOrdering, typeUrlPrefix); return fromMessageImpl(serializer, &realAny, RealAny::propertyOrdering, typeUrlPrefix);
} }
QAnyStringView Any::defaultUrlPrefix() QAnyStringView Any::defaultUrlPrefix()

View File

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

View File

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

View File

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

View File

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

View File

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