Browse Source

Implement Fixed32/64 serialization

- Implement serialization for Fixed32/64 types
- Add tests
TODO: Refactor fixed type detection
Alexey Edelev 6 years ago
parent
commit
9128c261ea
4 changed files with 139 additions and 20 deletions
  1. 23 3
      src/lib/protobufobject.h
  2. 5 0
      src/lib/qtprotobuf.h
  3. 2 1
      src/lib/qtprotobuftypes.h
  4. 109 16
      tests/serializationtest.cpp

+ 23 - 3
src/lib/protobufobject.h

@@ -64,7 +64,7 @@ protected:
         return *(char *)&header;
     }
 
-    inline QByteArray serializeValue(const QVariant& propertyValue, int fieldIndex) {
+    inline QByteArray serializeValue(const QVariant& propertyValue, int fieldIndex, bool isFixed = false) {
         QByteArray result;
         WireTypes type = UnknownWireType;
         switch (propertyValue.type()) {
@@ -97,6 +97,22 @@ protected:
             type = LengthDelimited;
             result.append(serializeUserType(propertyValue));
             break;
+        case QMetaType::UInt:
+            type = Fixed32;
+            if (isFixed) {
+                result.append(serializeFixed(propertyValue.toUInt()));
+            } else {
+                result.append(serializeVarint(propertyValue.toUInt()));
+            }
+            break;
+        case QMetaType::ULongLong:
+            type = Fixed64;
+            if (isFixed) {
+                result.append(serializeFixed(propertyValue.toULongLong()));
+            } else {
+                result.append(serializeVarint(propertyValue.toULongLong()));
+            }
+            break;
         default:
             Q_ASSERT_X(false, staticMetaObject.className(), "Serialization of unknown type is impossible");
         }
@@ -158,7 +174,9 @@ protected:
     }
 
     template <typename V,
-              typename std::enable_if_t<std::is_floating_point<V>::value, int> = 0>
+              typename std::enable_if_t<std::is_floating_point<V>::value
+                                        || std::is_same<V, unsigned int>::value
+                                        || std::is_same<V, qulonglong>::value, int> = 0>
     QByteArray serializeFixed(V value) {
         //Reserve required amount of bytes
         QByteArray result(sizeof(V), '\0');
@@ -223,7 +241,9 @@ public:
             QMetaProperty metaProperty = T::staticMetaObject.property(propertyIndex);
             const char* propertyName = metaProperty.name();
             const QVariant& propertyValue = instance->property(propertyName);
-            result.append(serializeValue(propertyValue, fieldIndex));
+            //TODO: flag isFixed looks ugly. Need to define more effective strategy
+            //for type detection.
+            result.append(serializeValue(propertyValue, fieldIndex, QString(metaProperty.typeName()).contains("Fixed")));
         }
 
         return result;

+ 5 - 0
src/lib/qtprotobuf.h

@@ -38,10 +38,15 @@ public:
         Q_ASSERT_X(!registationDone, "QtProtobuf", "Protobuf registation is already done");
         if (!registationDone) {
             qRegisterMetaType<IntList>("IntList");
+            qRegisterMetaType<IntList>("qtprotobuf::IntList");
             qRegisterMetaType<FloatList>("FloatList");
+            qRegisterMetaType<FloatList>("qtprotobuf::FloatList");
             qRegisterMetaType<DoubleList>("DoubleList");
+            qRegisterMetaType<DoubleList>("qtprotobuf::DoubleList");
             qRegisterMetaType<FixedInt32>("FixedInt32");
+            qRegisterMetaType<FixedInt32>("qtprotobuf::FixedInt32");
             qRegisterMetaType<FixedInt64>("FixedInt64");
+            qRegisterMetaType<FixedInt64>("qtprotobuf::FixedInt64");
             registationDone = true;
         }
     }

+ 2 - 1
src/lib/qtprotobuftypes.h

@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include <qglobal.h>
 #include <QList>
 #include <QMetaType>
 
@@ -35,7 +36,7 @@ using FloatList = QList<float>;
 using DoubleList = QList<double>;
 
 using FixedInt32 = unsigned int;
-using FixedInt64 = uint64_t;
+using FixedInt64 = qulonglong;
 }
 
 Q_DECLARE_METATYPE(qtprotobuf::IntList)

+ 109 - 16
tests/serializationtest.cpp

@@ -182,22 +182,115 @@ TEST_F(SerializationTest, IntMessageSerializeTest)
     ASSERT_EQ(result.at(3), '\x04');
 }
 
-// Need help with result size
-//TEST_F(SerializationTest, FixedInt32MessageSerializeTest)
-//{
-//    return;
-//    SimpleFixedInt32Message test;
-//    test.setTestFieldFixedInt32(15);
-//    QByteArray result = test.serialize();
-//    ASSERT_EQ(result.size(), 2);
-//    ASSERT_EQ(result.at(0), 0x08);
-//    ASSERT_EQ(result.at(1), '\x1e');
-//}
-
-//TEST_F(SerializationTest, FixedInt64MessageSerializeTest)
-//{
-//    return;
-//}
+TEST_F(SerializationTest, FixedInt32MessageSerializeTest)
+{
+    constexpr int Fixed32MessageSize = 5;
+    SimpleFixedInt32Message test;
+    test.setTestFieldFixedInt32(15);
+    QByteArray result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed32MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("0d0f000000"));
+
+    test.setTestFieldFixedInt32(300);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed32MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("0d2c010000"));
+
+    test.setTestFieldFixedInt32(65545);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed32MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("0d09000100"));
+
+    test.setTestFieldFixedInt32(0);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed32MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("0d00000000"));
+
+    test.setTestFieldFixedInt32(UINT8_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed32MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("0d00010000"));
+
+    test.setTestFieldFixedInt32(UINT16_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed32MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("0d00000100"));
+
+    test.setTestFieldFixedInt32(UINT8_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed32MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("0dff000000"));
+
+    test.setTestFieldFixedInt32(UINT16_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed32MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("0dffff0000"));
+
+    test.setTestFieldFixedInt32(UINT32_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed32MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("0dffffffff"));
+}
+
+TEST_F(SerializationTest, FixedInt64MessageSerializeTest)
+{
+    constexpr int Fixed64MessageSize = 9;
+    SimpleFixedInt64Message test;
+    test.setTestFieldFixedInt64(15);
+    QByteArray result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("090f00000000000000"));
+
+    test.setTestFieldFixedInt64(300);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("092c01000000000000"));
+
+    test.setTestFieldFixedInt64(65545);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("090900010000000000"));
+
+    test.setTestFieldFixedInt64(0);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("090000000000000000"));
+
+    test.setTestFieldFixedInt64(UINT8_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("090001000000000000"));
+
+    test.setTestFieldFixedInt64(UINT16_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("090000010000000000"));
+
+    test.setTestFieldFixedInt64((unsigned long long)(UINT32_MAX) + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("090000000001000000"));
+
+    test.setTestFieldFixedInt64(UINT8_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("09ff00000000000000"));
+
+    test.setTestFieldFixedInt64(UINT16_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("09ffff000000000000"));
+
+    test.setTestFieldFixedInt64(UINT32_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("09ffffffff00000000"));
+
+    test.setTestFieldFixedInt64(UINT64_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), Fixed64MessageSize);
+    ASSERT_TRUE(result == QByteArray::fromHex("09ffffffffffffffff"));
+}
 
 TEST_F(SerializationTest, FloatMessageSerializeTest)
 {