/* * MIT License * * Copyright (c) 2019 Alexey Edelev * * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and * to permit persons to whom the Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "qprotobufobject_p.h" using namespace qtprotobuf; ProtobufObjectPrivate::SerializerRegistry ProtobufObjectPrivate::serializers = {}; void ProtobufObjectPrivate::registerSerializers() { wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Fixed32); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Fixed64); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Varint); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Varint); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Varint); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Varint); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Varint); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Varint); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Fixed32); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Fixed64); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Fixed32); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Fixed64); wrapSerializer(ProtobufObjectPrivate::serializeBasic, ProtobufObjectPrivate::deserializeBasic, Varint); wrapSerializer([](const QString &data, int &/*fieldIndex*/) { return serializeLengthDelimited(data); }, [](QByteArray::const_iterator &it){ return QVariant::fromValue(QString::fromUtf8(deserializeLengthDelimited(it))); }, LengthDelimited); wrapSerializer([](const QByteArray &data, int &/*fieldIndex*/) { return serializeLengthDelimited(data); }, ProtobufObjectPrivate::deserializeLengthDelimited, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); wrapSerializer(ProtobufObjectPrivate::serializeListType, ProtobufObjectPrivate::deserializeList, LengthDelimited); } QByteArray ProtobufObjectPrivate::serializeValue(const QVariant &propertyValue, int fieldIndex, const QMetaProperty &metaProperty) { qProtoDebug() << __func__ << "propertyValue" << propertyValue << "fieldIndex" << fieldIndex << "typeName" << metaProperty.typeName() << static_cast(propertyValue.type()); QByteArray result; WireTypes type = UnknownWireType; if (metaProperty.isEnumType()) { type = Varint; result.append(serializeBasic(propertyValue.toLongLong(), fieldIndex)); } else { result.append(serializeUserType(propertyValue, fieldIndex, type)); } if (fieldIndex != NotUsedFieldIndex && type != UnknownWireType) { result.prepend(encodeHeaderByte(fieldIndex, type)); } return result; } QByteArray ProtobufObjectPrivate::serializeUserType(const QVariant &propertyValue, int &fieldIndex, WireTypes &type) { qProtoDebug() << __func__ << "propertyValue" << propertyValue << "fieldIndex" << fieldIndex; int userType = propertyValue.userType(); auto serializer = serializers[userType].serializer; Q_ASSERT_X(serializer, "ProtobufObjectPrivate", "Serialization of unknown type is impossible. QtProtobuf::init() missed?"); type = serializers[userType].type; return serializer(propertyValue, fieldIndex); } void ProtobufObjectPrivate::deserializeProperty(QObject *object, WireTypes wireType, const QMetaProperty &metaProperty, QByteArray::const_iterator &it) { qProtoDebug() << __func__ << " wireType: " << wireType << " metaProperty: " << metaProperty.typeName() << "currentByte:" << QString::number((*it), 16); QVariant newPropertyValue; //TODO: this switch should be removed in future and replaced by wrapped serializer switch (metaProperty.userType()) { case QMetaType::QByteArrayList: { QByteArrayList currentValue = metaProperty.read(object).value(); currentValue.append(deserializeLengthDelimited(it)); metaProperty.write(object, QVariant::fromValue(currentValue)); } return; case QMetaType::QStringList: { QStringList currentValue = metaProperty.read(object).value(); currentValue.append(QString::fromUtf8(deserializeLengthDelimited(it))); metaProperty.write(object, currentValue); } return; default: if (metaProperty.isEnumType()) { newPropertyValue = deserializeBasic(it); } else { newPropertyValue = metaProperty.read(object); deserializeUserType(metaProperty, it, newPropertyValue); } break; } metaProperty.write(object, newPropertyValue); } void ProtobufObjectPrivate::deserializeUserType(const QMetaProperty &metaType, QByteArray::const_iterator& it, QVariant &newValue) { qProtoDebug() << __func__ << "userType" << metaType.userType() << "typeName" << metaType.typeName() << "currentByte:" << QString::number((*it), 16); auto deserializer = serializers[metaType.userType()].deserializer; Q_ASSERT_X(deserializer, "ProtobufObjectPrivate", "Deserialization of unknown type is impossible. QtProtobuf::init() missed?"); deserializer(it, newValue); }