diff --git a/src/protobuf/qabstractprotobufserializer.h b/src/protobuf/qabstractprotobufserializer.h index b517cb7a..cf4e3055 100644 --- a/src/protobuf/qabstractprotobufserializer.h +++ b/src/protobuf/qabstractprotobufserializer.h @@ -37,11 +37,6 @@ public: virtual DeserializationError deserializationError() const = 0; virtual QString deserializationErrorString() const = 0; - virtual void - serializeObject(const QProtobufMessage *message, - const QtProtobufPrivate::QProtobufFieldInfo &fieldInfo) const = 0; - virtual bool deserializeObject(QProtobufMessage *message) const = 0; - protected: virtual QByteArray serializeMessage(const QProtobufMessage *message) const = 0; virtual bool deserializeMessage(QProtobufMessage *message, QByteArrayView data) const = 0; diff --git a/src/protobuf/qprotobufjsonserializer.cpp b/src/protobuf/qprotobufjsonserializer.cpp index 365753d0..862c8fce 100644 --- a/src/protobuf/qprotobufjsonserializer.cpp +++ b/src/protobuf/qprotobufjsonserializer.cpp @@ -187,8 +187,7 @@ public: return QJsonValue(arr); } - QProtobufJsonSerializerPrivate(QProtobufJsonSerializer *q) - : qPtr(q) + QProtobufJsonSerializerPrivate() { [[maybe_unused]] static bool initialized = []() -> bool { handlers[qMetaTypeId()] = createCommonHandler(); @@ -275,7 +274,7 @@ public: auto store = activeValue.toObject(); activeValue = QJsonObject(); auto *messageProperty = propertyValue.value(); - serializeObject(messageProperty); + serializeObjectImpl(messageProperty); store.insert(fieldInfo.jsonName().toString(), activeValue); activeValue = store; return; @@ -302,6 +301,11 @@ public: return; } + auto serializerFunction = [this](const QProtobufMessage *message, + const QProtobufFieldInfo &fieldInfo) { + this->serializeObject(message, fieldInfo); + }; + auto handler = QtProtobufPrivate::findHandler(metaType); if (handler.serializer) { if (fieldFlags & QtProtobufPrivate::FieldFlag::Repeated @@ -309,12 +313,12 @@ public: const auto fieldName = fieldInfo.jsonName().toString(); QJsonObject activeObject = activeValue.toObject(); activeValue = activeObject.value(fieldName).toArray(); - handler.serializer(qPtr, propertyValue.constData(), fieldInfo); + handler.serializer(serializerFunction, propertyValue.constData(), fieldInfo); if (!activeValue.toArray().empty()) activeObject.insert(fieldName, activeValue); activeValue = activeObject; } else { - handler.serializer(qPtr, propertyValue.constData(), fieldInfo); + handler.serializer(serializerFunction, propertyValue.constData(), fieldInfo); } } else { QJsonObject activeObject = activeValue.toObject(); @@ -333,24 +337,8 @@ public: } } - void serializeObject(const QProtobufMessage *message) - { - // if a message is not initialized, just return empty { } - if (message) { - auto ordering = message->propertyOrdering(); - Q_ASSERT(ordering != nullptr); - for (int index = 0; index < ordering->fieldCount(); ++index) { - int fieldIndex = ordering->fieldNumber(index); - Q_ASSERT_X(fieldIndex <= ProtobufFieldNumMax && fieldIndex >= ProtobufFieldNumMin, - "", - "fieldIndex is out of range"); - QProtobufFieldInfo fieldInfo(*ordering, index); - QVariant propertyValue = QtProtobufSerializerHelpers::messageProperty(message, - fieldInfo); - serializeProperty(propertyValue, fieldInfo); - } - } - } + void serializeObject(const QProtobufMessage *message, const QProtobufFieldInfo &fieldInfo); + void serializeObjectImpl(const QProtobufMessage *message); template static QVariant deserializeCommon(const QJsonValue &value, bool &ok) @@ -533,6 +521,9 @@ public: auto handler = QtProtobufPrivate::findHandler(metaType); if (handler.deserializer) { + auto deserializerFunction = [this](QProtobufMessage *message) { + return this->deserializeObject(message); + }; if (activeValue.isArray()) { QJsonArray array = activeValue.toArray(); if (array.isEmpty()) { @@ -540,15 +531,14 @@ public: activeValue = {}; return propertyData; } - if (!array.at(0).isObject()) { // Enum array - handler.deserializer(qPtr, propertyData.data()); + handler.deserializer(deserializerFunction, propertyData.data()); ok = propertyData.isValid(); } else { while (!array.isEmpty() && deserializationError == QAbstractProtobufSerializer::NoError) { activeValue = array.takeAt(0); - handler.deserializer(qPtr, propertyData.data()); + handler.deserializer(deserializerFunction, propertyData.data()); } ok = propertyData.isValid(); } @@ -557,7 +547,7 @@ public: // This is required to deserialize the map fields. while (!activeValue.isNull() && deserializationError == QAbstractProtobufSerializer::NoError) { - handler.deserializer(qPtr, propertyData.data()); + handler.deserializer(deserializerFunction, propertyData.data()); } ok = propertyData.isValid(); } @@ -715,9 +705,6 @@ public: QVariant cachedPropertyValue; int cachedIndex = -1; - -private: - QProtobufJsonSerializer *qPtr; }; bool QProtobufJsonSerializerPrivate::storeCachedValue(QProtobufMessage *message) @@ -736,14 +723,31 @@ bool QProtobufJsonSerializerPrivate::storeCachedValue(QProtobufMessage *message) QProtobufJsonSerializerPrivate::SerializerRegistry QProtobufJsonSerializerPrivate::handlers = {}; +void QProtobufJsonSerializerPrivate::serializeObjectImpl(const QProtobufMessage *message) +{ + // if a message is not initialized, just return empty { } + if (message) { + auto ordering = message->propertyOrdering(); + Q_ASSERT(ordering != nullptr); + for (int index = 0; index < ordering->fieldCount(); ++index) { + int fieldIndex = ordering->fieldNumber(index); + Q_ASSERT_X(fieldIndex <= ProtobufFieldNumMax && fieldIndex >= ProtobufFieldNumMin, "", + "fieldIndex is out of range"); + QProtobufFieldInfo fieldInfo(*ordering, index); + QVariant propertyValue = QtProtobufSerializerHelpers::messageProperty(message, + fieldInfo); + serializeProperty(propertyValue, fieldInfo); + } + } +} + void QProtobufJsonSerializerPrivate::clearError() { deserializationError = QAbstractProtobufSerializer::NoError; deserializationErrorString.clear(); } -QProtobufJsonSerializer::QProtobufJsonSerializer() : - d_ptr(new QProtobufJsonSerializerPrivate(this)) +QProtobufJsonSerializer::QProtobufJsonSerializer() : d_ptr(new QProtobufJsonSerializerPrivate) { } @@ -772,7 +776,7 @@ QByteArray QProtobufJsonSerializer::serializeMessage(const QProtobufMessage *mes { d_ptr->clearError(); d_ptr->activeValue = QJsonObject(); - d_ptr->serializeObject(message); + d_ptr->serializeObjectImpl(message); QJsonDocument doc; doc.setObject(d_ptr->activeValue.toObject()); d_ptr->activeValue = QJsonObject(); @@ -801,36 +805,31 @@ bool QProtobufJsonSerializer::deserializeMessage(QProtobufMessage *message, return d_ptr->deserializeObject(message); } -void QProtobufJsonSerializer::serializeObject(const QProtobufMessage *message, - const QProtobufFieldInfo &fieldInfo) const +void QProtobufJsonSerializerPrivate::serializeObject(const QProtobufMessage *message, + const QProtobufFieldInfo &fieldInfo) { - if (d_ptr->activeValue.isArray()) { - auto store = d_ptr->activeValue.toArray(); - d_ptr->activeValue = QJsonObject(); - d_ptr->serializeObject(message); - store.append(d_ptr->activeValue); - d_ptr->activeValue = store; + if (activeValue.isArray()) { + auto store = activeValue.toArray(); + activeValue = QJsonObject(); + serializeObjectImpl(message); + store.append(activeValue); + activeValue = store; } else { - auto store = d_ptr->activeValue.toObject(); + auto store = activeValue.toObject(); const QString fieldName = fieldInfo.jsonName().toString(); - d_ptr->activeValue = QJsonObject(); + activeValue = QJsonObject(); if (fieldInfo.fieldFlags() & QtProtobufPrivate::FieldFlag::Map) { QJsonObject mapObject = store.value(fieldName).toObject(); - d_ptr->serializeObject(message); + serializeObjectImpl(message); mapObject.insert(message->property("key").toString(), - d_ptr->activeValue.toObject().value("value"_L1)); + activeValue.toObject().value("value"_L1)); store.insert(fieldName, mapObject); } else { - d_ptr->serializeObject(message); - store.insert(fieldName, d_ptr->activeValue); + serializeObjectImpl(message); + store.insert(fieldName, activeValue); } - d_ptr->activeValue = store; + activeValue = store; } } -bool QProtobufJsonSerializer::deserializeObject(QProtobufMessage *message) const -{ - return d_ptr->deserializeObject(message); -} - QT_END_NAMESPACE diff --git a/src/protobuf/qprotobufjsonserializer.h b/src/protobuf/qprotobufjsonserializer.h index 3a2c236d..05dc66a1 100644 --- a/src/protobuf/qprotobufjsonserializer.h +++ b/src/protobuf/qprotobufjsonserializer.h @@ -25,15 +25,10 @@ public: DeserializationError deserializationError() const override; QString deserializationErrorString() const override; -private: +protected: QByteArray serializeMessage(const QProtobufMessage *message) const override; bool deserializeMessage(QProtobufMessage *message, QByteArrayView data) const override; - void serializeObject(const QProtobufMessage *message, - const QtProtobufPrivate::QProtobufFieldInfo &fieldInfo) - const override; - bool deserializeObject(QProtobufMessage *message) const override; - private: std::unique_ptr d_ptr; }; diff --git a/src/protobuf/qprotobufregistration.h b/src/protobuf/qprotobufregistration.h index bcd55db3..ee27604a 100644 --- a/src/protobuf/qprotobufregistration.h +++ b/src/protobuf/qprotobufregistration.h @@ -11,14 +11,14 @@ #include -#include #include #include #include -#include -#include #include +#include +#include +#include QT_BEGIN_NAMESPACE @@ -35,9 +35,12 @@ struct ProtoTypeRegistrar namespace QtProtobufPrivate { extern Q_PROTOBUF_EXPORT void registerOrdering(QMetaType type, QProtobufPropertyOrdering ordering); -using Serializer = void (*)(const QAbstractProtobufSerializer *, const void *, - const QProtobufFieldInfo &); -using Deserializer = void (*)(const QAbstractProtobufSerializer *, void *); +using MessageFieldSerializer = qxp::function_ref; +using MessageFieldDeserializer = qxp::function_ref; + +using Serializer = void (*)(MessageFieldSerializer, const void *, const QProtobufFieldInfo &); +using Deserializer = void (*)(MessageFieldDeserializer, void *); struct SerializationHandler { @@ -48,11 +51,6 @@ struct SerializationHandler extern Q_PROTOBUF_EXPORT void registerHandler(QMetaType type, Serializer serializer, Deserializer deserializer); -inline void ensureSerializer(const QAbstractProtobufSerializer *serializer) -{ - Q_ASSERT_X(serializer != nullptr, "QAbstractProtobufSerializer", "Serializer is null"); -} - inline void ensureValue(const void *valuePtr) { Q_ASSERT_X(valuePtr != nullptr, "QAbstractProtobufSerializer", "Value is nullptr"); @@ -60,21 +58,19 @@ inline void ensureValue(const void *valuePtr) template ::value, int> = 0> -void serializeList(const QAbstractProtobufSerializer *serializer, const void *valuePtr, +void serializeList(MessageFieldSerializer serializer, const void *valuePtr, const QProtobufFieldInfo &fieldInfo) { - ensureSerializer(serializer); ensureValue(valuePtr); for (const auto &value : *static_cast *>(valuePtr)) - serializer->serializeObject(&value, fieldInfo); + serializer(&value, fieldInfo); } template -void serializeMap(const QAbstractProtobufSerializer *serializer, const void *valuePtr, +void serializeMap(MessageFieldSerializer serializer, const void *valuePtr, const QProtobufFieldInfo &fieldInfo) { - ensureSerializer(serializer); ensureValue(valuePtr); using QProtobufMapEntry = QProtobufMapEntry; @@ -90,32 +86,29 @@ void serializeMap(const QAbstractProtobufSerializer *serializer, const void *val else el.setValue(v); - serializer->serializeObject(&el, fieldInfo); + serializer(&el, fieldInfo); } } template ::value, int> = 0> -void deserializeList(const QAbstractProtobufSerializer *serializer, void *valuePtr) +void deserializeList(MessageFieldDeserializer deserializer, void *valuePtr) { - ensureSerializer(serializer); ensureValue(valuePtr); auto *listPtr = static_cast *>(valuePtr); - if (V item; serializer->deserializeObject(&item)) + if (V item; deserializer(&item)) listPtr->append(std::move(item)); } template -void deserializeMap(const QAbstractProtobufSerializer *serializer, void *valuePtr) +void deserializeMap(MessageFieldDeserializer deserializer, void *valuePtr) { - ensureSerializer(serializer); - using QProtobufMapEntry = QProtobufMapEntry; static_assert(!std::is_pointer_v, "Map key must not be message"); auto *mapPtr = static_cast *>(valuePtr); - if (QProtobufMapEntry el; serializer->deserializeObject(&el)) { + if (QProtobufMapEntry el; deserializer(&el)) { auto it = mapPtr->emplace(std::move(el).key()); if constexpr (std::is_pointer_v) diff --git a/src/protobuf/qprotobufserializer.cpp b/src/protobuf/qprotobufserializer.cpp index 35031d3e..429e233c 100644 --- a/src/protobuf/qprotobufserializer.cpp +++ b/src/protobuf/qprotobufserializer.cpp @@ -185,7 +185,7 @@ findIntegratedTypeHandler(QMetaType metaType, bool nonPacked) /*! Constructs a new serializer instance. */ -QProtobufSerializer::QProtobufSerializer() : d_ptr(new QProtobufSerializerPrivate(this)) +QProtobufSerializer::QProtobufSerializer() : d_ptr(new QProtobufSerializerPrivate) { } @@ -316,17 +316,6 @@ bool QProtobufSerializerPrivate::deserializeObject(QProtobufMessage *message) return it.isValid(); } -void QProtobufSerializer::serializeObject(const QProtobufMessage *message, - const QProtobufFieldInfo &fieldInfo) const -{ - d_ptr->serializeObject(message, fieldInfo); -} - -bool QProtobufSerializer::deserializeObject(QProtobufMessage *message) const -{ - return d_ptr->deserializeObject(message); -} - void QProtobufSerializerPrivate::serializeEnumList(const QList &value, const QProtobufFieldInfo &fieldInfo) { @@ -356,10 +345,6 @@ bool QProtobufSerializerPrivate::deserializeEnumList(QList &v return true; } -QProtobufSerializerPrivate::QProtobufSerializerPrivate(QProtobufSerializer *q) : q_ptr(q) -{ -} - /*! \internal Encode a property field index and its type into output bytes. @@ -519,7 +504,11 @@ void QProtobufSerializerPrivate::serializeProperty(const QVariant &propertyValue qProtoWarning() << "No serializer for type" << propertyValue.typeName(); return; } - handler.serializer(q_ptr, propertyValue.constData(), fieldInfo); + + handler.serializer([this](const QProtobufMessage *message, + const QProtobufFieldInfo + &fieldInfo) { this->serializeObject(message, fieldInfo); }, + propertyValue.constData(), fieldInfo); } bool QProtobufSerializerPrivate::deserializeProperty(QProtobufMessage *message) @@ -644,7 +633,9 @@ bool QProtobufSerializerPrivate::deserializeProperty(QProtobufMessage *message) QCoreApplication::translate("QtProtobuf", error.toUtf8().data())); return false; } - handler.deserializer(q_ptr, cachedPropertyValue.data()); + handler.deserializer([this](QProtobufMessage + *message) { return this->deserializeObject(message); }, + cachedPropertyValue.data()); } return true; diff --git a/src/protobuf/qprotobufserializer.h b/src/protobuf/qprotobufserializer.h index 9ff99190..060b3abf 100644 --- a/src/protobuf/qprotobufserializer.h +++ b/src/protobuf/qprotobufserializer.h @@ -27,15 +27,11 @@ public: QString deserializationErrorString() const override; void shouldPreserveUnknownFields(bool preserveUnknownFields); -private: + +protected: QByteArray serializeMessage(const QProtobufMessage *message) const override; bool deserializeMessage(QProtobufMessage *message, QByteArrayView data) const override; - void serializeObject(const QProtobufMessage *message, - const QtProtobufPrivate::QProtobufFieldInfo &fieldInfo) - const override; - bool deserializeObject(QProtobufMessage *message) const override; - private: std::unique_ptr d_ptr; }; diff --git a/src/protobuf/qprotobufserializer_p.h b/src/protobuf/qprotobufserializer_p.h index 70abcb00..e133be98 100644 --- a/src/protobuf/qprotobufserializer_p.h +++ b/src/protobuf/qprotobufserializer_p.h @@ -154,7 +154,7 @@ public: return !value.value().isEmpty(); } - explicit QProtobufSerializerPrivate(QProtobufSerializer *q); + QProtobufSerializerPrivate() = default; ~QProtobufSerializerPrivate() = default; // ########################################################################### // Serializers @@ -538,7 +538,6 @@ public: private: Q_DISABLE_COPY_MOVE(QProtobufSerializerPrivate) - QProtobufSerializer *q_ptr; }; inline bool diff --git a/src/protobufqttypes/protobufqtcoretypes/qtprotobufqttypescommon_p.h b/src/protobufqttypes/protobufqtcoretypes/qtprotobufqttypescommon_p.h index e37b4ed4..6943ad2d 100644 --- a/src/protobufqttypes/protobufqtcoretypes/qtprotobufqttypescommon_p.h +++ b/src/protobufqttypes/protobufqtcoretypes/qtprotobufqttypescommon_p.h @@ -40,46 +40,44 @@ constexpr inline bool is_optional_v> = true; template void registerQtTypeHandler() { - registerHandler(QMetaType::fromType(), - [](const QAbstractProtobufSerializer *serializer, const void *valuePtr, - const QProtobufFieldInfo &info) { - QtProtobufPrivate::ensureSerializer(serializer); - QtProtobufPrivate::ensureValue(valuePtr); + registerHandler( + QMetaType::fromType(), + [](QtProtobufPrivate::MessageFieldSerializer serializer, const void *valuePtr, + const QProtobufFieldInfo &info) { + QtProtobufPrivate::ensureValue(valuePtr); - auto do_convert = [](const QType *qtype) { - auto res = convert(*qtype); - if constexpr (is_optional_v) { - return res; - } else { - return std::optional(std::move(res)); - } - }; + auto do_convert = [](const QType *qtype) { + auto res = convert(*qtype); + if constexpr (is_optional_v) { + return res; + } else { + return std::optional(std::move(res)); + } + }; - std::optional object = - do_convert(static_cast(valuePtr)); - if (object) { - serializer->serializeObject(&(object.value()), info); - } else { - warnTypeConversionError(); - } - }, - [](const QAbstractProtobufSerializer *serializer, void *valuePtr) { - QtProtobufPrivate::ensureSerializer(serializer); - QtProtobufPrivate::ensureValue(valuePtr); + std::optional object = do_convert(static_cast(valuePtr)); + if (object) { + serializer(&(object.value()), info); + } else { + warnTypeConversionError(); + } + }, + [](QtProtobufPrivate::MessageFieldDeserializer deserializer, void *valuePtr) { + QtProtobufPrivate::ensureValue(valuePtr); - PType object; - serializer->deserializeObject(&object); - auto res = convert(object); - auto *qtypePtr = static_cast(valuePtr); - if constexpr (is_optional_v) { - if (!res) - warnTypeConversionError(); - else - *qtypePtr = std::move(*res); - } else { - *qtypePtr = std::move(res); - } - }); + PType object; + deserializer(&object); + auto res = convert(object); + auto *qtypePtr = static_cast(valuePtr); + if constexpr (is_optional_v) { + if (!res) + warnTypeConversionError(); + else + *qtypePtr = std::move(*res); + } else { + *qtypePtr = std::move(res); + } + }); } } // namespace QtProtobufPrivate diff --git a/src/wellknown/qprotobufanysupport.cpp b/src/wellknown/qprotobufanysupport.cpp index c6129d07..96936987 100644 --- a/src/wellknown/qprotobufanysupport.cpp +++ b/src/wellknown/qprotobufanysupport.cpp @@ -35,11 +35,9 @@ AnyPrivate::AnyPrivate(const QMetaObject *metaObject, { } -static void serializerProxy(const QAbstractProtobufSerializer *serializer, const void *object, - const QProtobufFieldInfo &fieldInfo) +static void serializerProxy(QtProtobufPrivate::MessageFieldSerializer serializer, + const void *object, const QProtobufFieldInfo &fieldInfo) { - QtProtobufPrivate::ensureSerializer(serializer); - if (object == nullptr) return; @@ -50,14 +48,12 @@ static void serializerProxy(const QAbstractProtobufSerializer *serializer, const google::protobuf::Any realAny; realAny.setValue(any.value()); realAny.setTypeUrl(any.typeUrl()); - serializer->serializeObject(&realAny, fieldInfo); + serializer(&realAny, fieldInfo); } -static void listSerializerProxy(const QAbstractProtobufSerializer *serializer, const void *object, - const QProtobufFieldInfo &fieldInfo) +static void listSerializerProxy(QtProtobufPrivate::MessageFieldSerializer serializer, + const void *object, const QProtobufFieldInfo &fieldInfo) { - QtProtobufPrivate::ensureSerializer(serializer); - if (object == nullptr) return; @@ -66,20 +62,19 @@ static void listSerializerProxy(const QAbstractProtobufSerializer *serializer, c google::protobuf::Any realAny; realAny.setValue(any.value()); realAny.setTypeUrl(any.typeUrl()); - serializer->serializeObject(&realAny, fieldInfo); + serializer(&realAny, fieldInfo); } } -static void listDeserializerProxy(const QAbstractProtobufSerializer *deserializer, void *object) +static void listDeserializerProxy(QtProtobufPrivate::MessageFieldDeserializer deserializer, + void *object) { - QtProtobufPrivate::ensureSerializer(deserializer); - if (object == nullptr) return; auto &anyList = *static_cast *>(object); google::protobuf::Any realAny; - if (deserializer->deserializeObject(&realAny)) { + if (deserializer(&realAny)) { Any any; any.setTypeUrl(realAny.typeUrl()); any.setValue(realAny.value()); @@ -89,15 +84,14 @@ static void listDeserializerProxy(const QAbstractProtobufSerializer *deserialize } } -static void deserializerProxy(const QAbstractProtobufSerializer *deserializer, void *object) +static void deserializerProxy(QtProtobufPrivate::MessageFieldDeserializer deserializer, + void *object) { - QtProtobufPrivate::ensureSerializer(deserializer); - if (object == nullptr) return; google::protobuf::Any realAny; - if (deserializer->deserializeObject(&realAny)) { + if (deserializer(&realAny)) { auto &any = *static_cast(object); any.setTypeUrl(realAny.typeUrl()); any.setValue(realAny.value()); diff --git a/tests/auto/grpc/qgrpchttp2channel/tst_qgrpchttp2channel.cpp b/tests/auto/grpc/qgrpchttp2channel/tst_qgrpchttp2channel.cpp index 310e93db..0e47ba59 100644 --- a/tests/auto/grpc/qgrpchttp2channel/tst_qgrpchttp2channel.cpp +++ b/tests/auto/grpc/qgrpchttp2channel/tst_qgrpchttp2channel.cpp @@ -39,12 +39,6 @@ protected: { return true; } - - void serializeObject(const QProtobufMessage *, - const QtProtobufPrivate::QProtobufFieldInfo &) const override - { - } - bool deserializeObject(QProtobufMessage *) const override { return true; } }; } // namespace