|
@@ -33,6 +33,11 @@
|
|
|
|
|
|
namespace qtprotobuf {
|
|
|
|
|
|
+/**
|
|
|
+ * @private
|
|
|
+ *
|
|
|
+ * @brief The QProtobufSerializerPrivate class
|
|
|
+ */
|
|
|
class QProtobufSerializerPrivate {
|
|
|
QProtobufSerializerPrivate() = delete;
|
|
|
~QProtobufSerializerPrivate() = delete;
|
|
@@ -40,6 +45,10 @@ class QProtobufSerializerPrivate {
|
|
|
QProtobufSerializerPrivate(QProtobufSerializerPrivate &&) = delete;
|
|
|
QProtobufSerializerPrivate &operator =(QProtobufSerializerPrivate &&) = delete;
|
|
|
public:
|
|
|
+ //###########################################################################
|
|
|
+ // Serializers
|
|
|
+ //###########################################################################
|
|
|
+
|
|
|
template <typename V,
|
|
|
typename std::enable_if_t<std::is_integral<V>::value
|
|
|
&& std::is_unsigned<V>::value, int> = 0>
|
|
@@ -63,57 +72,8 @@ public:
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_integral<V>::value
|
|
|
- && std::is_unsigned<V>::value, int> = 0>
|
|
|
- static V deserializeVarintCommon(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
-
|
|
|
- V value = 0;
|
|
|
- int k = 0;
|
|
|
- while (true) {
|
|
|
- uint64_t byte = static_cast<uint64_t>(*it);
|
|
|
- value += (byte & 0b01111111) << k;
|
|
|
- k += 7;
|
|
|
- if (((*it) & 0b10000000) == 0) {
|
|
|
- break;
|
|
|
- }
|
|
|
- ++it;
|
|
|
- }
|
|
|
- ++it;
|
|
|
- return value;
|
|
|
- }
|
|
|
-
|
|
|
- template <typename T,
|
|
|
- typename std::enable_if_t<!std::is_base_of<QObject, T>::value, int> = 0>
|
|
|
- static void wrapSerializer(QProtobufSerializer *owner,const std::function<QByteArray(const T &, int &)> &s, const std::function<QVariant(SelfcheckIterator &)> &d, WireTypes type)
|
|
|
- {
|
|
|
- owner->serializers[qMetaTypeId<T>()] = {
|
|
|
- [s](const QVariant &value, int &fieldIndex) {
|
|
|
- return s(value.value<T>(), fieldIndex);
|
|
|
- },
|
|
|
- [d](SelfcheckIterator &it, QVariant & value){
|
|
|
- value = d(it);
|
|
|
- },
|
|
|
- type
|
|
|
- };
|
|
|
-}
|
|
|
-
|
|
|
-template <typename T,
|
|
|
-typename std::enable_if_t<!std::is_base_of<QObject, T>::value, int> = 0>
|
|
|
-static void wrapSerializer(QProtobufSerializer *owner, const std::function<QByteArray(const T &, int &)> &s, const std::function<void(SelfcheckIterator &it, QVariant & value)> &d, WireTypes type)
|
|
|
-{
|
|
|
- owner->serializers[qMetaTypeId<T>()] = {
|
|
|
- [s](const QVariant &value, int &fieldIndex) {
|
|
|
- return s(value.value<T>(), fieldIndex);
|
|
|
- },
|
|
|
- d,
|
|
|
- type
|
|
|
-};
|
|
|
-}
|
|
|
-
|
|
|
-//----------------Serialize basic integral and floating point----------------
|
|
|
-/**
|
|
|
+ //---------------Integral and floating point types serializers---------------
|
|
|
+ /**
|
|
|
* @brief Serialization of fixed-length primitive types
|
|
|
*
|
|
|
* Natural layout of bits is used: value is encoded in a byte array same way as it is located in memory
|
|
@@ -122,18 +82,18 @@ static void wrapSerializer(QProtobufSerializer *owner, const std::function<QByte
|
|
|
* @param[out] outFieldIndex Index of the value in parent structure (ignored)
|
|
|
* @return Byte array with value encoded
|
|
|
*/
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_floating_point<V>::value, int> = 0>
|
|
|
-static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
- qProtoDebug() << __func__ << "value" << value;
|
|
|
-
|
|
|
- //Reserve required number of bytes
|
|
|
- QByteArray result(sizeof(V), '\0');
|
|
|
- *reinterpret_cast<V *>(result.data()) = value;
|
|
|
- return result;
|
|
|
-}
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_floating_point<V>::value, int> = 0>
|
|
|
+ static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
+ qProtoDebug() << __func__ << "value" << value;
|
|
|
|
|
|
-/**
|
|
|
+ //Reserve required number of bytes
|
|
|
+ QByteArray result(sizeof(V), '\0');
|
|
|
+ *reinterpret_cast<V *>(result.data()) = value;
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* @brief Serialization of fixed length integral types
|
|
|
*
|
|
|
* @details Natural layout of bits is employed
|
|
@@ -142,21 +102,21 @@ static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
* @param[out] outFieldIndex Index of the value in parent structure (ignored)
|
|
|
* @return Byte array with value encoded
|
|
|
*/
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, fixed32>::value
|
|
|
- || std::is_same<V, fixed64>::value
|
|
|
- || std::is_same<V, sfixed32>::value
|
|
|
- || std::is_same<V, sfixed64>::value, int> = 0>
|
|
|
-static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
- qProtoDebug() << __func__ << "value" << value;
|
|
|
-
|
|
|
- //Reserve required number of bytes
|
|
|
- QByteArray result(sizeof(V), '\0');
|
|
|
- *reinterpret_cast<V *>(result.data()) = value;
|
|
|
- return result;
|
|
|
-}
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, fixed32>::value
|
|
|
+ || std::is_same<V, fixed64>::value
|
|
|
+ || std::is_same<V, sfixed32>::value
|
|
|
+ || std::is_same<V, sfixed64>::value, int> = 0>
|
|
|
+ static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
+ qProtoDebug() << __func__ << "value" << value;
|
|
|
|
|
|
-/**
|
|
|
+ //Reserve required number of bytes
|
|
|
+ QByteArray result(sizeof(V), '\0');
|
|
|
+ *reinterpret_cast<V *>(result.data()) = value;
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
*@brief Serialization of signed integral types
|
|
|
*
|
|
|
* Use <a href="https://developers.google.com/protocol-buffers/docs/encoding">ZigZag encoding</a> first,
|
|
@@ -167,30 +127,30 @@ static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
* @param[out] outFieldIndex Index of the value in parent structure
|
|
|
* @return Byte array with value encoded
|
|
|
*/
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_integral<V>::value
|
|
|
- && std::is_signed<V>::value, int> = 0>
|
|
|
-static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "value" << value;
|
|
|
- using UV = typename std::make_unsigned<V>::type;
|
|
|
- UV uValue = 0;
|
|
|
-
|
|
|
- //Use ZigZag convertion first and apply unsigned variant next
|
|
|
- V zigZagValue = (value << 1) ^ (value >> (sizeof(UV) * 8 - 1));
|
|
|
- uValue = static_cast<UV>(zigZagValue);
|
|
|
- return serializeBasic(uValue, outFieldIndex);
|
|
|
-}
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_integral<V>::value
|
|
|
+ && std::is_signed<V>::value, int> = 0>
|
|
|
+ static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "value" << value;
|
|
|
+ using UV = typename std::make_unsigned<V>::type;
|
|
|
+ UV uValue = 0;
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, int32>::value
|
|
|
- || std::is_same<V, int64>::value, int> = 0>
|
|
|
-static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "value" << value;
|
|
|
- using UV = typename std::make_unsigned<V>::type;
|
|
|
- return serializeBasic(static_cast<UV>(value), outFieldIndex);
|
|
|
-}
|
|
|
+ //Use ZigZag convertion first and apply unsigned variant next
|
|
|
+ V zigZagValue = (value << 1) ^ (value >> (sizeof(UV) * 8 - 1));
|
|
|
+ uValue = static_cast<UV>(zigZagValue);
|
|
|
+ return serializeBasic(uValue, outFieldIndex);
|
|
|
+ }
|
|
|
|
|
|
-/**
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, int32>::value
|
|
|
+ || std::is_same<V, int64>::value, int> = 0>
|
|
|
+ static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "value" << value;
|
|
|
+ using UV = typename std::make_unsigned<V>::type;
|
|
|
+ return serializeBasic(static_cast<UV>(value), outFieldIndex);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
*@brief Serialization of unsigned integral types
|
|
|
*
|
|
|
* Use <a href="https://developers.google.com/protocol-buffers/docs/encoding">Varint encoding</a>:
|
|
@@ -201,240 +161,301 @@ static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
* @param[out] outFieldIndex Index of the value in parent structure
|
|
|
* @return Byte array with value encoded
|
|
|
*/
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_integral<V>::value
|
|
|
- && std::is_unsigned<V>::value, int> = 0>
|
|
|
-static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "value" << value;
|
|
|
- V varint = value;
|
|
|
- QByteArray result;
|
|
|
-
|
|
|
- while (varint != 0) {
|
|
|
- //Put 7 bits to result buffer and mark as "not last" (0b10000000)
|
|
|
- result.append((varint & 0b01111111) | 0b10000000);
|
|
|
- //Divide values to chunks of 7 bits and move to next chunk
|
|
|
- varint >>= 7;
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_integral<V>::value
|
|
|
+ && std::is_unsigned<V>::value, int> = 0>
|
|
|
+ static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "value" << value;
|
|
|
+ V varint = value;
|
|
|
+ QByteArray result;
|
|
|
+
|
|
|
+ while (varint != 0) {
|
|
|
+ //Put 7 bits to result buffer and mark as "not last" (0b10000000)
|
|
|
+ result.append((varint & 0b01111111) | 0b10000000);
|
|
|
+ //Divide values to chunks of 7 bits and move to next chunk
|
|
|
+ varint >>= 7;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Invalidate field index in case if serialized result is empty
|
|
|
+ // NOTE: the field will not be sent if its index is equal to NotUsedFieldIndex
|
|
|
+ if (result.size() == 0) {
|
|
|
+ outFieldIndex = NotUsedFieldIndex;
|
|
|
+ } else {
|
|
|
+ //Mark last chunk as last by clearing last bit
|
|
|
+ result.data()[result.size() - 1] &= ~0b10000000;
|
|
|
+ }
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
- // Invalidate field index in case if serialized result is empty
|
|
|
- // NOTE: the field will not be sent if its index is equal to NotUsedFieldIndex
|
|
|
- if (result.size() == 0) {
|
|
|
- outFieldIndex = NotUsedFieldIndex;
|
|
|
- } else {
|
|
|
- //Mark last chunk as last by clearing last bit
|
|
|
- result.data()[result.size() - 1] &= ~0b10000000;
|
|
|
+ //------------------QString and QByteArray types serializers-----------------
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
+ static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
+ return serializeLengthDelimited(value.toUtf8());
|
|
|
}
|
|
|
- return result;
|
|
|
-}
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
-static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
- return serializeLengthDelimited(value.toUtf8());
|
|
|
-}
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
+ static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
+ return serializeLengthDelimited(value);
|
|
|
+ }
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
-static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
- return serializeLengthDelimited(value);
|
|
|
-}
|
|
|
+ //--------------------------List types serializers---------------------------
|
|
|
+ template<typename V,
|
|
|
+ typename std::enable_if_t<!(std::is_same<V, QString>::value
|
|
|
+ || std::is_same<V, QByteArray>::value
|
|
|
+ || std::is_base_of<QObject, V>::value), int> = 0>
|
|
|
+ static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
+
|
|
|
+ if (listValue.count() <= 0) {
|
|
|
+ outFieldIndex = NotUsedFieldIndex;
|
|
|
+ return QByteArray();
|
|
|
+ }
|
|
|
|
|
|
-//---------------Deserialize basic integral and floating point---------------
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_floating_point<V>::value
|
|
|
- || std::is_same<V, fixed32>::value
|
|
|
- || std::is_same<V, fixed64>::value
|
|
|
- || std::is_same<V, sfixed32>::value
|
|
|
- || std::is_same<V, sfixed64>::value, int> = 0>
|
|
|
-static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
-
|
|
|
- QVariant newPropertyValue(QVariant::fromValue(*(V *)((QByteArray::const_iterator&)it)));
|
|
|
- it += sizeof(V);
|
|
|
- return newPropertyValue;
|
|
|
-}
|
|
|
+ int empty = NotUsedFieldIndex;
|
|
|
+ QByteArray serializedList;
|
|
|
+ for (auto &value : listValue) {
|
|
|
+ serializedList.append(serializeBasic<V>(value, empty));
|
|
|
+ }
|
|
|
+ //If internal field type is not LengthDelimited, exact amount of fields to be specified
|
|
|
+ serializedList = prependLengthDelimitedSize(serializedList);
|
|
|
+ return serializedList;
|
|
|
+ }
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_integral<V>::value
|
|
|
- && std::is_unsigned<V>::value, int> = 0>
|
|
|
-static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ template<typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
+ static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
|
|
|
- return QVariant::fromValue(deserializeVarintCommon<V>(it));
|
|
|
-}
|
|
|
+ if (listValue.count() <= 0) {
|
|
|
+ outFieldIndex = NotUsedFieldIndex;
|
|
|
+ return QByteArray();
|
|
|
+ }
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_integral<V>::value
|
|
|
- && std::is_signed<V>::value,int> = 0>
|
|
|
-static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
- using UV = typename std::make_unsigned<V>::type;
|
|
|
- UV unsignedValue = deserializeVarintCommon<UV>(it);
|
|
|
- V value = (unsignedValue >> 1) ^ (-1 * (unsignedValue & 1));
|
|
|
- return QVariant::fromValue<V>(value);
|
|
|
-}
|
|
|
+ QByteArray serializedList;
|
|
|
+ for (auto &value : listValue) {
|
|
|
+ serializedList.append(QProtobufSerializerPrivate::encodeHeader(outFieldIndex, LengthDelimited));
|
|
|
+ serializedList.append(serializeLengthDelimited(value.toUtf8()));
|
|
|
+ }
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<int32, V>::value
|
|
|
- || std::is_same<int64, V>::value, int> = 0>
|
|
|
-static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
- using UV = typename std::make_unsigned<V>::type;
|
|
|
- UV unsignedValue = deserializeVarintCommon<UV>(it);
|
|
|
- V value = static_cast<V>(unsignedValue);
|
|
|
- return QVariant::fromValue(value);
|
|
|
-}
|
|
|
+ outFieldIndex = NotUsedFieldIndex;
|
|
|
+ return serializedList;
|
|
|
+ }
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<QByteArray, V>::value, int> = 0>
|
|
|
-static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- return QVariant::fromValue(deserializeLengthDelimited(it));
|
|
|
-}
|
|
|
+ template<typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
+ static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<QString, V>::value, int> = 0>
|
|
|
-static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- return QVariant::fromValue(QString::fromUtf8(deserializeLengthDelimited(it)));
|
|
|
-}
|
|
|
+ if (listValue.count() <= 0) {
|
|
|
+ outFieldIndex = NotUsedFieldIndex;
|
|
|
+ return QByteArray();
|
|
|
+ }
|
|
|
|
|
|
-template<typename V,
|
|
|
- typename std::enable_if_t<!(std::is_same<V, QString>::value
|
|
|
- || std::is_same<V, QByteArray>::value
|
|
|
- || std::is_base_of<QObject, V>::value), int> = 0>
|
|
|
-static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
+ QByteArray serializedList;
|
|
|
+ for (auto &value : listValue) {
|
|
|
+ serializedList.append(QProtobufSerializerPrivate::encodeHeader(outFieldIndex, LengthDelimited));
|
|
|
+ serializedList.append(serializeLengthDelimited(value));
|
|
|
+ }
|
|
|
|
|
|
- if (listValue.count() <= 0) {
|
|
|
outFieldIndex = NotUsedFieldIndex;
|
|
|
- return QByteArray();
|
|
|
+ return serializedList;
|
|
|
}
|
|
|
|
|
|
- int empty = NotUsedFieldIndex;
|
|
|
- QByteArray serializedList;
|
|
|
- for (auto &value : listValue) {
|
|
|
- serializedList.append(serializeBasic<V>(value, empty));
|
|
|
+ //###########################################################################
|
|
|
+ // Deserializers
|
|
|
+ //###########################################################################
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_integral<V>::value
|
|
|
+ && std::is_unsigned<V>::value, int> = 0>
|
|
|
+ static V deserializeVarintCommon(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+
|
|
|
+ V value = 0;
|
|
|
+ int k = 0;
|
|
|
+ while (true) {
|
|
|
+ uint64_t byte = static_cast<uint64_t>(*it);
|
|
|
+ value += (byte & 0b01111111) << k;
|
|
|
+ k += 7;
|
|
|
+ if (((*it) & 0b10000000) == 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ ++it;
|
|
|
+ }
|
|
|
+ ++it;
|
|
|
+ return value;
|
|
|
}
|
|
|
- //If internal field type is not LengthDelimited, exact amount of fields to be specified
|
|
|
- serializedList = prependLengthDelimitedSize(serializedList);
|
|
|
- return serializedList;
|
|
|
-}
|
|
|
|
|
|
-template<typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
-static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
+ //-------------Integral and floating point types deserializers---------------
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_floating_point<V>::value
|
|
|
+ || std::is_same<V, fixed32>::value
|
|
|
+ || std::is_same<V, fixed64>::value
|
|
|
+ || std::is_same<V, sfixed32>::value
|
|
|
+ || std::is_same<V, sfixed64>::value, int> = 0>
|
|
|
+ static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
|
|
|
- if (listValue.count() <= 0) {
|
|
|
- outFieldIndex = NotUsedFieldIndex;
|
|
|
- return QByteArray();
|
|
|
+ QVariant newPropertyValue(QVariant::fromValue(*(V *)((QByteArray::const_iterator&)it)));
|
|
|
+ it += sizeof(V);
|
|
|
+ return newPropertyValue;
|
|
|
}
|
|
|
|
|
|
- QByteArray serializedList;
|
|
|
- for (auto &value : listValue) {
|
|
|
- serializedList.append(QProtobufSerializerPrivate::encodeHeader(outFieldIndex, LengthDelimited));
|
|
|
- serializedList.append(serializeLengthDelimited(value.toUtf8()));
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_integral<V>::value
|
|
|
+ && std::is_unsigned<V>::value, int> = 0>
|
|
|
+ static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+
|
|
|
+ return QVariant::fromValue(deserializeVarintCommon<V>(it));
|
|
|
}
|
|
|
|
|
|
- outFieldIndex = NotUsedFieldIndex;
|
|
|
- return serializedList;
|
|
|
-}
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_integral<V>::value
|
|
|
+ && std::is_signed<V>::value,int> = 0>
|
|
|
+ static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ using UV = typename std::make_unsigned<V>::type;
|
|
|
+ UV unsignedValue = deserializeVarintCommon<UV>(it);
|
|
|
+ V value = (unsignedValue >> 1) ^ (-1 * (unsignedValue & 1));
|
|
|
+ return QVariant::fromValue<V>(value);
|
|
|
+ }
|
|
|
|
|
|
-template<typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
-static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<int32, V>::value
|
|
|
+ || std::is_same<int64, V>::value, int> = 0>
|
|
|
+ static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ using UV = typename std::make_unsigned<V>::type;
|
|
|
+ UV unsignedValue = deserializeVarintCommon<UV>(it);
|
|
|
+ V value = static_cast<V>(unsignedValue);
|
|
|
+ return QVariant::fromValue(value);
|
|
|
+ }
|
|
|
|
|
|
- if (listValue.count() <= 0) {
|
|
|
- outFieldIndex = NotUsedFieldIndex;
|
|
|
- return QByteArray();
|
|
|
+ //-----------------QString and QByteArray types deserializers----------------
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<QByteArray, V>::value, int> = 0>
|
|
|
+ static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ return QVariant::fromValue(deserializeLengthDelimited(it));
|
|
|
}
|
|
|
|
|
|
- QByteArray serializedList;
|
|
|
- for (auto &value : listValue) {
|
|
|
- serializedList.append(QProtobufSerializerPrivate::encodeHeader(outFieldIndex, LengthDelimited));
|
|
|
- serializedList.append(serializeLengthDelimited(value));
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<QString, V>::value, int> = 0>
|
|
|
+ static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ return QVariant::fromValue(QString::fromUtf8(deserializeLengthDelimited(it)));
|
|
|
}
|
|
|
|
|
|
- outFieldIndex = NotUsedFieldIndex;
|
|
|
- return serializedList;
|
|
|
-}
|
|
|
+ //-------------------------List types deserializers--------------------------
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
+ static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
-static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ QByteArrayList list = previous.value<QByteArrayList>();
|
|
|
+ list.append(deserializeLengthDelimited(it));
|
|
|
+ previous.setValue(list);
|
|
|
+ }
|
|
|
|
|
|
- QByteArrayList list = previous.value<QByteArrayList>();
|
|
|
- list.append(deserializeLengthDelimited(it));
|
|
|
- previous.setValue(list);
|
|
|
-}
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
+ static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
-static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ QStringList list = previous.value<QStringList>();
|
|
|
+ QByteArray value = deserializeLengthDelimited(it);
|
|
|
+ list.append(QString::fromUtf8(value));
|
|
|
+ previous.setValue(list);
|
|
|
+ }
|
|
|
|
|
|
- QStringList list = previous.value<QStringList>();
|
|
|
- QByteArray value = deserializeLengthDelimited(it);
|
|
|
- list.append(QString::fromUtf8(value));
|
|
|
- previous.setValue(list);
|
|
|
-}
|
|
|
+ template <typename V,
|
|
|
+ typename std::enable_if_t<!(std::is_same<V, QString>::value
|
|
|
+ || std::is_same<V, QByteArray>::value
|
|
|
+ || std::is_base_of<QObject, V>::value), int> = 0>
|
|
|
+ static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
|
|
|
-template <typename V,
|
|
|
- typename std::enable_if_t<!(std::is_same<V, QString>::value
|
|
|
- || std::is_same<V, QByteArray>::value
|
|
|
- || std::is_base_of<QObject, V>::value), int> = 0>
|
|
|
-static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
-
|
|
|
- QList<V> out;
|
|
|
- unsigned int count = deserializeVarintCommon<uint32>(it);
|
|
|
- SelfcheckIterator lastVarint = it + count;
|
|
|
- while (it != lastVarint) {
|
|
|
- QVariant variant = deserializeBasic<V>(it);
|
|
|
- out.append(variant.value<V>());
|
|
|
+ QList<V> out;
|
|
|
+ unsigned int count = deserializeVarintCommon<uint32>(it);
|
|
|
+ SelfcheckIterator lastVarint = it + count;
|
|
|
+ while (it != lastVarint) {
|
|
|
+ QVariant variant = deserializeBasic<V>(it);
|
|
|
+ out.append(variant.value<V>());
|
|
|
+ }
|
|
|
+ previous.setValue(out);
|
|
|
}
|
|
|
- previous.setValue(out);
|
|
|
-}
|
|
|
|
|
|
-static QByteArray deserializeLengthDelimited(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ //###########################################################################
|
|
|
+ // Common functions
|
|
|
+ //###########################################################################
|
|
|
+ static QByteArray deserializeLengthDelimited(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
|
|
|
- unsigned int length = deserializeVarintCommon<uint32>(it);
|
|
|
- QByteArray result((QByteArray::const_iterator&)it, length); //TODO it's possible to void buffeer copying by setupimg new "end of QByteArray";
|
|
|
- it += length;
|
|
|
- return result;
|
|
|
-}
|
|
|
+ unsigned int length = deserializeVarintCommon<uint32>(it);
|
|
|
+ QByteArray result((QByteArray::const_iterator&)it, length); //TODO it's possible to void buffeer copying by setupimg new "end of QByteArray";
|
|
|
+ it += length;
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
-static QByteArray serializeLengthDelimited(const QByteArray &data) {
|
|
|
- qProtoDebug() << __func__ << "data.size" << data.size() << "data" << data.toHex();
|
|
|
- QByteArray result(data);
|
|
|
- //Varint serialize field size and apply result as starting point
|
|
|
- result = prependLengthDelimitedSize(result);
|
|
|
- return result;
|
|
|
-}
|
|
|
+ static QByteArray serializeLengthDelimited(const QByteArray &data) {
|
|
|
+ qProtoDebug() << __func__ << "data.size" << data.size() << "data" << data.toHex();
|
|
|
+ QByteArray result(data);
|
|
|
+ //Varint serialize field size and apply result as starting point
|
|
|
+ result = prependLengthDelimitedSize(result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
-static bool decodeHeader(SelfcheckIterator &it, int &fieldIndex, WireTypes &wireType);
|
|
|
-static QByteArray encodeHeader(int fieldIndex, WireTypes wireType);
|
|
|
+ static bool decodeHeader(SelfcheckIterator &it, int &fieldIndex, WireTypes &wireType);
|
|
|
+ static QByteArray encodeHeader(int fieldIndex, WireTypes wireType);
|
|
|
|
|
|
-/**
|
|
|
+ /**
|
|
|
* @brief Gets length of a byte-array and prepends to it its serialized length value
|
|
|
* using the appropriate serialization algorithm
|
|
|
*
|
|
|
*
|
|
|
* @param[in, out] serializedList Byte-array to be prepended
|
|
|
*/
|
|
|
-static QByteArray prependLengthDelimitedSize(const QByteArray &data)
|
|
|
-{
|
|
|
- return serializeVarintCommon<uint32_t>(data.size()) + data;
|
|
|
-}
|
|
|
+ static QByteArray prependLengthDelimitedSize(const QByteArray &data)
|
|
|
+ {
|
|
|
+ return serializeVarintCommon<uint32_t>(data.size()) + data;
|
|
|
+ }
|
|
|
+
|
|
|
+ // this set of 3 methods is used to skip bytes corresponding to an unexpected property
|
|
|
+ // in a serialized message met while the message being deserialized
|
|
|
+ static int skipSerializedFieldBytes(SelfcheckIterator &it, WireTypes type);
|
|
|
+
|
|
|
+ static void deserializeMapField(QVariant &value, SelfcheckIterator &it);
|
|
|
|
|
|
-// this set of 3 methods is used to skip bytes corresponding to an unexpected property
|
|
|
-// in a serialized message met while the message being deserialized
|
|
|
-static void skipVarint(SelfcheckIterator &it);
|
|
|
-static void skipLengthDelimited(SelfcheckIterator &it);
|
|
|
-static int skipSerializedFieldBytes(SelfcheckIterator &it, WireTypes type);
|
|
|
-static void deserializeMapField(QVariant &value, SelfcheckIterator &it);
|
|
|
+ template <typename T,
|
|
|
+ typename std::enable_if_t<!std::is_base_of<QObject, T>::value, int> = 0>
|
|
|
+ static void wrapSerializer(QAbstractProtobufSerializer::SerializerRegistry &handlers, const std::function<QByteArray(const T &, int &)> &s, const std::function<QVariant(SelfcheckIterator &)> &d, WireTypes type)
|
|
|
+ {
|
|
|
+ handlers[qMetaTypeId<T>()] = {
|
|
|
+ [s](const QVariant &value, int &fieldIndex) {
|
|
|
+ return s(value.value<T>(), fieldIndex);
|
|
|
+ },
|
|
|
+ [d](SelfcheckIterator &it, QVariant & value){
|
|
|
+ value = d(it);
|
|
|
+ },
|
|
|
+ type
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T,
|
|
|
+ typename std::enable_if_t<!std::is_base_of<QObject, T>::value, int> = 0>
|
|
|
+ static void wrapSerializer(QAbstractProtobufSerializer::SerializerRegistry &handlers, const std::function<QByteArray(const T &, int &)> &s, const std::function<void(SelfcheckIterator &it, QVariant & value)> &d, WireTypes type)
|
|
|
+ {
|
|
|
+ handlers[qMetaTypeId<T>()] = {
|
|
|
+ [s](const QVariant &value, int &fieldIndex) {
|
|
|
+ return s(value.value<T>(), fieldIndex);
|
|
|
+ },
|
|
|
+ d,
|
|
|
+ type
|
|
|
+ };
|
|
|
+ }
|
|
|
+protected:
|
|
|
+ static void skipVarint(SelfcheckIterator &it);
|
|
|
+ static void skipLengthDelimited(SelfcheckIterator &it);
|
|
|
};
|
|
|
|
|
|
//###########################################################################
|
|
@@ -481,4 +502,3 @@ inline bool QProtobufSerializerPrivate::decodeHeader(SelfcheckIterator &it, int
|
|
|
}
|
|
|
|
|
|
}
|
|
|
-
|