Browse Source

Migrate to registred serializer/deserializer for complex type

Alexey Edelev 6 years ago
parent
commit
bfd94c22cd
3 changed files with 19 additions and 37 deletions
  1. 1 8
      src/protobuf/protobufobject.cpp
  2. 11 14
      src/protobuf/protobufobject.h
  3. 7 15
      src/protobuf/protobufobject_p.h

+ 1 - 8
src/protobuf/protobufobject.cpp

@@ -237,12 +237,7 @@ QByteArray ProtobufObjectPrivate::serializeUserType(const QVariant &propertyValu
         return serializeFixedListType(propertyValue.value<DoubleList>(), fieldIndex);
     }
 
-    //Otherwise it's user type
-    const void *src = propertyValue.constData();
-    //TODO: each time huge objects will make own copies
-    //Probably generate fields reflection is better solution
-    auto value = std::unique_ptr<ProtobufObjectPrivate>(reinterpret_cast<ProtobufObjectPrivate *>(QMetaType::create(userType, src)));
-    return serializeLengthDelimited(value->serializePrivate());
+    return serializers[userType].serializer(this, propertyValue, fieldIndex);
 }
 
 void ProtobufObjectPrivate::deserializeProperty(WireTypes wireType, const QMetaProperty &metaProperty, QByteArray::const_iterator &it)
@@ -373,7 +368,5 @@ void ProtobufObjectPrivate::deserializeUserType(const QMetaProperty &metaType, Q
         newValue = deserializeListType<float>(it);
     } else if (userType == qMetaTypeId<DoubleList>()) {
         newValue = deserializeListType<double>(it);
-    } else {
-        newValue = deserializeProtobufObjectType(userType, it);
     }
 }

+ 11 - 14
src/protobuf/protobufobject.h

@@ -98,26 +98,23 @@ public:
     }
 
 protected:
-    static void registerSerializers(int /*metaTypeId*/, int listMetaTypeId) {
-        serializers[listMetaTypeId] = {ListSerializer(serializeComplexListType), ListDeserializer(deserializeComplexListType)};
+    static void registerSerializers(int metaTypeId, int listMetaTypeId) {
+        serializers[listMetaTypeId] = {Serializer(serializeComplexListType), Deserializer(deserializeComplexListType)};
+        serializers[metaTypeId] = {Serializer(serializeComplexType), Deserializer(deserializeComplexType)};
     }
 
 private:
-    QByteArray serializePrivate() const override {
-        qProtoDebug() << T::staticMetaObject.className() << "serializePrivate";
-        return serialize();
-    }
 
-    void deserializePrivate(const QByteArray &data) override {
-        qProtoDebug() << T::staticMetaObject.className() << "deserializePrivate";
-        deserialize(data);
+    static QByteArray serializeComplexType(const ProtobufObjectPrivate *serializer, const QVariant &variantValue, int &/*outFieldIndex*/) {
+        T value = variantValue.value<T>();
+        return serializer->serializeLengthDelimited(value.serialize());
     }
 
-//TODO: migrate to this function for complex types serialization
-//    static QByteArray serializeSelf(const QVariant &variantValue) {
-//        T value = variantValue.value<T>();
-//        return value->serialize();
-//    }
+    static void deserializeComplexType(ProtobufObjectPrivate *deserializer, QByteArray::const_iterator &it, QVariant &previous) {
+        T value;
+        value.deserialize(deserializer->deserializeLengthDelimited(it));
+        previous = QVariant::fromValue(value);
+    }
 
     static QByteArray serializeComplexListType(const ProtobufObjectPrivate *serializer, const QVariant &listValue, int &outFieldIndex) {
         QList<T> list = listValue.value<QList<T>>();

+ 7 - 15
src/protobuf/protobufobject_p.h

@@ -56,11 +56,11 @@ constexpr int NotUsedFieldIndex = -1;
 class ProtobufObjectPrivate : public QObject
 {
 protected:
-    using ListSerializer = std::function<QByteArray(const ProtobufObjectPrivate *, const QVariant &, int &)>;
-    using ListDeserializer = std::function<void(ProtobufObjectPrivate *, QByteArray::const_iterator &, QVariant &)>;
+    using Serializer = std::function<QByteArray(const ProtobufObjectPrivate *, const QVariant &, int &)>;
+    using Deserializer = std::function<void(ProtobufObjectPrivate *, QByteArray::const_iterator &, QVariant &)>;
     struct SerializationHandlers {
-        ListSerializer serializer;
-        ListDeserializer deserializer;
+        Serializer serializer;
+        Deserializer deserializer;
     };
 
     using SerializerRegistry = std::unordered_map<int/*metatypeid*/, SerializationHandlers>;
@@ -69,9 +69,6 @@ protected:
 public:
     explicit ProtobufObjectPrivate(QObject *parent = nullptr) : QObject(parent) {}
 
-    virtual QByteArray serializePrivate() const = 0;
-    virtual void deserializePrivate(const QByteArray &data) = 0;
-
     inline static unsigned char encodeHeaderByte(int fieldIndex, WireTypes wireType);
     inline static bool decodeHeaderByte(unsigned char typeByte, int &fieldIndex, WireTypes &wireType);
 
@@ -364,12 +361,6 @@ public:
         return result;
     }
 
-    QVariant deserializeProtobufObjectType(int userType, QByteArray::const_iterator &it) {
-        auto value = reinterpret_cast<ProtobufObjectPrivate *>(QMetaType::create(userType));
-        value->deserializePrivate(deserializeLengthDelimited(it));
-        return QVariant(userType, value);
-    }
-
     template <typename V,
               typename std::enable_if_t<std::is_same<V, QString>::value
                                         || std::is_same<V, QByteArray>::value, int> = 0>
@@ -383,8 +374,9 @@ public:
               typename std::enable_if_t<std::is_base_of<ProtobufObjectPrivate, V>::value, int> = 0>
     QVariant deserializeListType(QByteArray::const_iterator &it) {
         qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
-
-        return deserializeProtobufObjectType(qMetaTypeId<V>(), it);
+        QVariant newValue;
+        serializers[qMetaTypeId<V>()].deserializer(this, it, newValue);
+        return newValue;
     }
 
     template <typename V,