1 | // Copyright (C) 2024 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include <QtProtobuf/private/qprotobufdeserializerbase_p.h> |
5 | |
6 | #include <QtProtobuf/private/qprotobufregistration_p.h> |
7 | #include <QtProtobuf/private/qtprotobuflogging_p.h> |
8 | #include <QtProtobuf/private/qtprotobufserializerhelpers_p.h> |
9 | |
10 | QT_BEGIN_NAMESPACE |
11 | |
12 | QProtobufDeserializerBase::QProtobufDeserializerBase() |
13 | = default; |
14 | |
15 | QProtobufDeserializerBase::~QProtobufDeserializerBase() |
16 | = default; |
17 | |
18 | bool QProtobufDeserializerBase::deserializeMessageField(QProtobufMessage *message) |
19 | { |
20 | Q_ASSERT(message != nullptr); |
21 | |
22 | auto prevCachedRepeatedIterator = std::move(m_cachedRepeatedIterator); |
23 | auto prevCachedPropertyValue = m_cachedPropertyValue; |
24 | auto prevCachedIndex = m_cachedIndex; |
25 | clearCachedValue(); |
26 | bool result = deserializeMessage(message); |
27 | m_cachedPropertyValue = prevCachedPropertyValue; |
28 | m_cachedIndex = prevCachedIndex; |
29 | m_cachedRepeatedIterator = std::move(prevCachedRepeatedIterator); |
30 | |
31 | return result; |
32 | } |
33 | |
34 | bool QProtobufDeserializerBase::deserializeMessage(QProtobufMessage *message) |
35 | { |
36 | Q_ASSERT(message != nullptr); |
37 | |
38 | const auto *ordering = message->propertyOrdering(); |
39 | for (int fieldIndex = nextFieldIndex(message); fieldIndex >= 0; |
40 | fieldIndex = nextFieldIndex(message)) { |
41 | QtProtobufPrivate::QProtobufFieldInfo fieldInfo(*ordering, fieldIndex); |
42 | if (m_cachedIndex != fieldIndex) { |
43 | if (!storeCachedValue(message)) { |
44 | setError(error: QAbstractProtobufSerializer::Error::InvalidFormat, |
45 | errorString: "Unable to store the property in message" ); |
46 | return false; |
47 | } |
48 | |
49 | m_cachedPropertyValue = QtProtobufSerializerHelpers::messageProperty(message, fieldInfo, |
50 | allowInitialize: true); |
51 | m_cachedIndex = fieldIndex; |
52 | } |
53 | |
54 | QMetaType metaType = m_cachedPropertyValue.metaType(); |
55 | if (metaType.flags().testFlag(flag: QMetaType::IsPointer)) { |
56 | if (!deserializeMessageField(message: m_cachedPropertyValue.value<QProtobufMessage *>())) |
57 | return false; |
58 | |
59 | continue; |
60 | } |
61 | |
62 | const auto fieldFlags = fieldInfo.fieldFlags(); |
63 | if ((fieldFlags.testFlags(flags: RepeatedMessageFlags) |
64 | || fieldFlags.testFlags(flags: { QtProtobufPrivate::FieldFlag::Map })) |
65 | && m_cachedPropertyValue.canView(targetType: QMetaType::fromType<QProtobufRepeatedIterator>())) { |
66 | if (!m_cachedRepeatedIterator.isValid()) |
67 | m_cachedRepeatedIterator = m_cachedPropertyValue.view<QProtobufRepeatedIterator>(); |
68 | |
69 | if (!deserializeMessageField(message: m_cachedRepeatedIterator.addNext())) |
70 | return false; |
71 | |
72 | m_cachedRepeatedIterator.push(); |
73 | continue; |
74 | } |
75 | |
76 | if (fieldFlags.testFlag(flag: QtProtobufPrivate::FieldFlag::Enum)) { |
77 | if (!deserializeEnum(value&: m_cachedPropertyValue, fieldInfo)) { |
78 | setError(error: QAbstractProtobufSerializer::Error::UnknownType, |
79 | errorString: "Unable to covert enum field to compatible serialization format" ); |
80 | return false; |
81 | } |
82 | continue; |
83 | } |
84 | |
85 | if (deserializeScalarField(value&: m_cachedPropertyValue, fieldInfo)) { |
86 | if (!m_cachedPropertyValue.isValid()) |
87 | return false; |
88 | |
89 | continue; |
90 | } |
91 | |
92 | auto handler = QtProtobufPrivate::findHandler(type: metaType); |
93 | if (!handler.deserializer) { |
94 | qProtoWarning() << "No deserializer for type" << metaType.name(); |
95 | setError(error: QAbstractProtobufSerializer::Error::UnknownType, |
96 | errorString: QString::fromUtf8(utf8: "No deserializer is registered for type %1" ) |
97 | .arg(a: QString::fromUtf8(utf8: metaType.name()))); |
98 | return false; |
99 | } |
100 | |
101 | handler.deserializer([this](QProtobufMessage * |
102 | message) { return this->deserializeMessageField(message); }, |
103 | m_cachedPropertyValue.data()); |
104 | } |
105 | |
106 | if (!storeCachedValue(message)) { |
107 | setError(error: QAbstractProtobufSerializer::Error::InvalidFormat, |
108 | errorString: "Unable to store the property in message" ); |
109 | return false; |
110 | } |
111 | |
112 | return true; |
113 | } |
114 | |
115 | bool QProtobufDeserializerBase::storeCachedValue(QProtobufMessage *message) |
116 | { |
117 | bool ok = true; |
118 | if (m_cachedIndex >= 0 && !m_cachedPropertyValue.isNull()) { |
119 | const auto *ordering = message->propertyOrdering(); |
120 | QtProtobufPrivate::QProtobufFieldInfo fieldInfo(*ordering, m_cachedIndex); |
121 | ok = QtProtobufSerializerHelpers::setMessageProperty(message, fieldInfo, |
122 | value: m_cachedPropertyValue); |
123 | |
124 | clearCachedValue(); |
125 | } |
126 | return ok; |
127 | } |
128 | |
129 | void QProtobufDeserializerBase::clearCachedValue() |
130 | { |
131 | m_cachedPropertyValue.clear(); |
132 | m_cachedIndex = -1; |
133 | m_cachedRepeatedIterator = {}; |
134 | } |
135 | |
136 | QT_END_NAMESPACE |
137 | |