1 | // Copyright (C) 2022 The Qt Company Ltd. |
2 | // Copyright (C) 2019 Alexey Edelev <semlanik@gmail.com>, Viktor Kopp <vifactor@gmail.com> |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #include <QtProtobuf/qprotobufserializer.h> |
6 | |
7 | #include <QtProtobuf/private/protobufscalarserializers_p.h> |
8 | #include <QtProtobuf/private/qprotobufmessage_p.h> |
9 | #include <QtProtobuf/private/qprotobufregistration_p.h> |
10 | #include <QtProtobuf/private/qprotobufserializer_p.h> |
11 | #include <QtProtobuf/private/qprotobufserializerbase_p.h> |
12 | #include <QtProtobuf/private/qtprotobufdefs_p.h> |
13 | #include <QtProtobuf/private/qtprotobufserializerhelpers_p.h> |
14 | #include <QtProtobuf/qprotobufmessage.h> |
15 | #include <QtProtobuf/qtprotobuftypes.h> |
16 | |
17 | #include <QtCore/qcoreapplication.h> |
18 | #include <QtCore/qlist.h> |
19 | #include <QtCore/qmetaobject.h> |
20 | #include <QtCore/qmetatype.h> |
21 | #include <QtCore/qreadwritelock.h> |
22 | |
23 | QT_BEGIN_NAMESPACE |
24 | |
25 | /*! |
26 | \class QProtobufSerializer |
27 | \inmodule QtProtobuf |
28 | \since 6.5 |
29 | \brief The QProtobufSerializer class is interface that represents |
30 | basic functions for serialization/deserialization. |
31 | |
32 | The QProtobufSerializer class registers serializers/deserializers for |
33 | classes implementing a protobuf message, inheriting \l QProtobufMessage. These |
34 | classes are generated automatically, based on a \c{.proto} file, using the CMake |
35 | function \l qt_add_protobuf or by running |
36 | \l {The qtprotobufgen Tool} {qtprotobufgen} directly. |
37 | */ |
38 | |
39 | using namespace Qt::StringLiterals; |
40 | using namespace QtProtobufPrivate; |
41 | using namespace ProtobufScalarSerializers; |
42 | |
43 | template<std::size_t N> |
44 | using SerializerRegistryType = |
45 | std::array<QProtobufSerializerPrivate::ProtobufSerializationHandler, N>; |
46 | |
47 | namespace { |
48 | |
49 | #define QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(Type, WireType) \ |
50 | { QMetaType::fromType<Type>(), \ |
51 | QProtobufSerializerPrivate::serializeWrapper<Type, serializeBasic<Type>>, \ |
52 | deserializeBasic<Type>, ProtobufFieldPresenceChecker::isPresent<Type>, WireType } |
53 | #define QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(ListType, Type) \ |
54 | { QMetaType::fromType<ListType>(), \ |
55 | QProtobufSerializerPrivate::serializeWrapper<ListType, serializeListType<Type>>, \ |
56 | deserializeList<Type>, ProtobufFieldPresenceChecker::isPresent<ListType>, \ |
57 | QtProtobuf::WireTypes::LengthDelimited } |
58 | |
59 | #define QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER(ListType, Type, WireType) \ |
60 | { QMetaType::fromType<ListType>(), \ |
61 | QProtobufSerializerPrivate::serializeNonPackedWrapper<ListType, \ |
62 | serializeNonPackedList<Type>>, \ |
63 | deserializeNonPackedList<Type>, ProtobufFieldPresenceChecker::isPresent<ListType>, \ |
64 | WireType } |
65 | |
66 | constexpr SerializerRegistryType<30> IntegratedTypesSerializers = { ._M_elems: { |
67 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(float, QtProtobuf::WireTypes::Fixed32), |
68 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(double, QtProtobuf::WireTypes::Fixed64), |
69 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::int32, |
70 | QtProtobuf::WireTypes::Varint), |
71 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::int64, |
72 | QtProtobuf::WireTypes::Varint), |
73 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::uint32, |
74 | QtProtobuf::WireTypes::Varint), |
75 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::uint64, |
76 | QtProtobuf::WireTypes::Varint), |
77 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::sint32, |
78 | QtProtobuf::WireTypes::Varint), |
79 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::sint64, |
80 | QtProtobuf::WireTypes::Varint), |
81 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::fixed32, |
82 | QtProtobuf::WireTypes::Fixed32), |
83 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::fixed64, |
84 | QtProtobuf::WireTypes::Fixed64), |
85 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::sfixed32, |
86 | QtProtobuf::WireTypes::Fixed32), |
87 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::sfixed64, |
88 | QtProtobuf::WireTypes::Fixed64), |
89 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QtProtobuf::boolean, |
90 | QtProtobuf::WireTypes::Varint), |
91 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QString, |
92 | QtProtobuf::WireTypes::LengthDelimited), |
93 | QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(QByteArray, |
94 | QtProtobuf::WireTypes::LengthDelimited), |
95 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::floatList, float), |
96 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::doubleList, double), |
97 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::int32List, QtProtobuf::int32), |
98 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::int64List, QtProtobuf::int64), |
99 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::uint32List, |
100 | QtProtobuf::uint32), |
101 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::uint64List, |
102 | QtProtobuf::uint64), |
103 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::sint32List, |
104 | QtProtobuf::sint32), |
105 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::sint64List, |
106 | QtProtobuf::sint64), |
107 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::fixed32List, |
108 | QtProtobuf::fixed32), |
109 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::fixed64List, |
110 | QtProtobuf::fixed64), |
111 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::sfixed32List, |
112 | QtProtobuf::sfixed32), |
113 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::sfixed64List, |
114 | QtProtobuf::sfixed64), |
115 | QT_CONSTRUCT_PROTOBUF_LIST_SERIALIZATION_HANDLER(QtProtobuf::boolList, QtProtobuf::boolean), |
116 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
117 | QStringList, QString, QtProtobuf::WireTypes::LengthDelimited), |
118 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
119 | QByteArrayList, QByteArray, QtProtobuf::WireTypes::LengthDelimited), |
120 | } }; |
121 | |
122 | constexpr SerializerRegistryType<13> IntegratedNonPackedSerializers = { ._M_elems: { |
123 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER(QtProtobuf::floatList, float, |
124 | QtProtobuf::WireTypes::Fixed32), |
125 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER(QtProtobuf::doubleList, double, |
126 | QtProtobuf::WireTypes::Fixed64), |
127 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
128 | QtProtobuf::int32List, QtProtobuf::int32, QtProtobuf::WireTypes::Varint), |
129 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
130 | QtProtobuf::int64List, QtProtobuf::int64, QtProtobuf::WireTypes::Varint), |
131 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
132 | QtProtobuf::uint32List, QtProtobuf::uint32, QtProtobuf::WireTypes::Varint), |
133 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
134 | QtProtobuf::uint64List, QtProtobuf::uint64, QtProtobuf::WireTypes::Varint), |
135 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
136 | QtProtobuf::sint32List, QtProtobuf::sint32, QtProtobuf::WireTypes::Varint), |
137 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
138 | QtProtobuf::sint64List, QtProtobuf::sint64, QtProtobuf::WireTypes::Varint), |
139 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
140 | QtProtobuf::fixed32List, QtProtobuf::fixed32, QtProtobuf::WireTypes::Fixed32), |
141 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
142 | QtProtobuf::fixed64List, QtProtobuf::fixed64, QtProtobuf::WireTypes::Fixed64), |
143 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
144 | QtProtobuf::sfixed32List, QtProtobuf::sfixed32, QtProtobuf::WireTypes::Fixed32), |
145 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
146 | QtProtobuf::sfixed64List, QtProtobuf::sfixed64, QtProtobuf::WireTypes::Fixed64), |
147 | QT_CONSTRUCT_PROTOBUF_NON_PACKED_LIST_SERIALIZATION_HANDLER( |
148 | QtProtobuf::boolList, QtProtobuf::boolean, QtProtobuf::WireTypes::Varint), |
149 | } }; |
150 | |
151 | template<std::size_t N> |
152 | std::optional<QProtobufSerializerPrivate::ProtobufSerializationHandler> |
153 | findIntegratedTypeHandlerImpl(QMetaType metaType, const SerializerRegistryType<N> ®istry) |
154 | { |
155 | typename SerializerRegistryType<N>::const_iterator it = std::find_if( |
156 | registry.begin(), registry.end(), |
157 | [&metaType](const QProtobufSerializerPrivate::ProtobufSerializationHandler &handler) { |
158 | return handler.metaType == metaType; |
159 | }); |
160 | if (it == registry.end()) |
161 | return std::nullopt; |
162 | return { *it }; |
163 | } |
164 | |
165 | std::optional<QProtobufSerializerPrivate::ProtobufSerializationHandler> |
166 | findIntegratedTypeHandler(QMetaType metaType, bool nonPacked) |
167 | { |
168 | if (nonPacked) |
169 | return findIntegratedTypeHandlerImpl(metaType, registry: IntegratedNonPackedSerializers); |
170 | |
171 | return findIntegratedTypeHandlerImpl(metaType, registry: IntegratedTypesSerializers); |
172 | } |
173 | } // namespace |
174 | |
175 | QProtobufSerializerImpl::QProtobufSerializerImpl(QProtobufSerializerPrivate *parent) : m_parent(parent) |
176 | { |
177 | |
178 | } |
179 | |
180 | QProtobufSerializerImpl::~QProtobufSerializerImpl() = default; |
181 | |
182 | void QProtobufSerializerImpl::reset() |
183 | { |
184 | m_state.clear(); |
185 | m_result = {}; |
186 | } |
187 | |
188 | void QProtobufSerializerImpl::serializeUnknownFields(const QProtobufMessage *message) |
189 | { |
190 | if (m_parent->preserveUnknownFields) { |
191 | // Restore any unknown fields we have stored away: |
192 | for (const auto &fields : |
193 | std::as_const(t: QProtobufMessagePrivate::get(message)->unknownEntries)) { |
194 | m_result += fields.join(); |
195 | } |
196 | } |
197 | } |
198 | |
199 | bool QProtobufSerializerImpl::serializeEnum(QVariant &value, |
200 | const QtProtobufPrivate::QProtobufFieldInfo &fieldInfo) |
201 | { |
202 | const auto fieldFlags = fieldInfo.fieldFlags(); |
203 | if (fieldFlags.testFlag(flag: QtProtobufPrivate::FieldFlag::Repeated)) { |
204 | if (!value.canConvert<QList<QtProtobuf::int64>>()) |
205 | return false; |
206 | QList<QtProtobuf::int64> listValue = value.value<QList<QtProtobuf::int64>>(); |
207 | if (listValue.isEmpty()) |
208 | return true; |
209 | |
210 | if (fieldFlags.testFlag(flag: QtProtobufPrivate::FieldFlag::NonPacked)) { |
211 | const auto = encodeHeader(fieldIndex: fieldInfo.fieldNumber(), |
212 | wireType: QtProtobuf::WireTypes::Varint); |
213 | m_result.append(a: serializeNonPackedList<QtProtobuf::int64>(listValue, header)); |
214 | } else { |
215 | m_result.append(a: encodeHeader(fieldIndex: fieldInfo.fieldNumber(), |
216 | wireType: QtProtobuf::WireTypes::LengthDelimited)); |
217 | m_result.append(a: serializeListType<QtProtobuf::int64>(listValue)); |
218 | } |
219 | } else { |
220 | if (!value.canConvert<QtProtobuf::int64>()) |
221 | return false; |
222 | |
223 | if (!ProtobufFieldPresenceChecker::isPresent<QtProtobuf::int64>(value) |
224 | && !isOneofOrOptionalField(flags: fieldInfo.fieldFlags())) { |
225 | return true; |
226 | } |
227 | |
228 | m_result.append(a: encodeHeader(fieldIndex: fieldInfo.fieldNumber(), wireType: QtProtobuf::WireTypes::Varint)); |
229 | m_result.append(a: serializeBasic<QtProtobuf::int64>(value: value.value<QtProtobuf::int64>())); |
230 | } |
231 | return true; |
232 | } |
233 | |
234 | bool QProtobufSerializerImpl::serializeScalarField(const QVariant &value, |
235 | const QProtobufFieldInfo &fieldInfo) |
236 | { |
237 | const QtProtobufPrivate::FieldFlags flags = fieldInfo.fieldFlags(); |
238 | const bool isPacked = flags.testFlag(flag: QtProtobufPrivate::FieldFlag::NonPacked); |
239 | auto basicHandler = findIntegratedTypeHandler(metaType: value.metaType(), nonPacked: isPacked); |
240 | // Is not a protobuf scalar value type |
241 | if (!basicHandler) |
242 | return false; |
243 | |
244 | // Field is empty |
245 | if (!basicHandler->isPresent(value) && !isOneofOrOptionalField(flags)) |
246 | return true; |
247 | |
248 | const QByteArray = encodeHeader(fieldIndex: fieldInfo.fieldNumber(), wireType: basicHandler->wireType); |
249 | m_result.append(a: basicHandler->serializer(value, header)); |
250 | return true; |
251 | } |
252 | |
253 | void QProtobufSerializerImpl::serializeMessageFieldBegin() |
254 | { |
255 | m_state.emplaceBack(args: std::move(m_result)); |
256 | m_result = {}; |
257 | } |
258 | |
259 | void QProtobufSerializerImpl::serializeMessageFieldEnd(const QProtobufMessage *message, |
260 | const QProtobufFieldInfo &fieldInfo) |
261 | { |
262 | Q_ASSERT(!m_state.isEmpty()); |
263 | |
264 | serializeUnknownFields(message); |
265 | |
266 | QByteArray last = m_state.takeLast(); |
267 | last.append(a: encodeHeader(fieldIndex: fieldInfo.fieldNumber(), wireType: QtProtobuf::WireTypes::LengthDelimited)); |
268 | last.append(a: serializeVarintCommon<uint32_t>(value: m_result.size())); |
269 | last.append(a: m_result); |
270 | m_result = last; |
271 | } |
272 | |
273 | QByteArray QProtobufSerializerImpl::(int fieldIndex, QtProtobuf::WireTypes wireType) |
274 | { |
275 | // Encodes a property field index and its type into output bytes. |
276 | |
277 | // Header byte |
278 | // Meaning | Field index | Type |
279 | // ---------- | ------------- | -------- |
280 | // bit number | 7 6 5 4 3 | 2 1 0 |
281 | |
282 | // fieldIndex: The index of a property in parent object |
283 | // wireType: Serialization type used for the property with fieldIndex |
284 | |
285 | // Returns a varint-encoded fieldIndex and wireType |
286 | |
287 | uint32_t = (fieldIndex << 3) | int(wireType); |
288 | return serializeVarintCommon<uint32_t>(value: header); |
289 | } |
290 | |
291 | QProtobufDeserializerImpl::QProtobufDeserializerImpl(QProtobufSerializerPrivate *parent) |
292 | : m_parent(parent) |
293 | { |
294 | } |
295 | |
296 | QProtobufDeserializerImpl::~QProtobufDeserializerImpl() |
297 | = default; |
298 | |
299 | void QProtobufDeserializerImpl::reset(QByteArrayView data) |
300 | { |
301 | m_it = QProtobufSelfcheckIterator::fromView(container: data); |
302 | m_state.push_back(t: data.end()); |
303 | clearCachedValue(); |
304 | } |
305 | |
306 | void QProtobufDeserializerImpl::setError(QAbstractProtobufSerializer::Error error, |
307 | QAnyStringView errorString) |
308 | { |
309 | m_parent->lastError = error; |
310 | m_parent->lastErrorString = errorString.toString(); |
311 | } |
312 | |
313 | bool QProtobufDeserializerImpl::deserializeEnum(QVariant &value, |
314 | const QProtobufFieldInfo &fieldInfo) |
315 | { |
316 | const auto fieldFlags = fieldInfo.fieldFlags(); |
317 | if (fieldFlags.testFlag(flag: QtProtobufPrivate::FieldFlag::Repeated)) { |
318 | QMetaType metaType = value.metaType(); |
319 | value.convert(type: QMetaType::fromType<QList<QtProtobuf::int64>>()); |
320 | bool result = false; |
321 | if (m_wireType == QtProtobuf::WireTypes::Varint) { |
322 | result = deserializeNonPackedList<QtProtobuf::int64>(it&: m_it, previousValue&: value); |
323 | } else if (m_wireType == QtProtobuf::WireTypes::LengthDelimited) { |
324 | result = deserializeList<QtProtobuf::int64>(it&: m_it, previousValue&: value); |
325 | } |
326 | value.convert(type: metaType); |
327 | return result; |
328 | } |
329 | |
330 | return deserializeBasic<QtProtobuf::int64>(it&: m_it, variantValue&: value); |
331 | } |
332 | |
333 | int QProtobufDeserializerImpl::nextFieldIndex(QProtobufMessage *message) |
334 | { |
335 | Q_ASSERT(message); |
336 | |
337 | const auto *ordering = message->propertyOrdering(); |
338 | Q_ASSERT(ordering != nullptr); |
339 | |
340 | while (m_it.isValid() && m_it != m_state.last()) { |
341 | // Each iteration we expect iterator is setup to beginning of next chunk |
342 | int fieldNumber = QtProtobuf::InvalidFieldNumber; |
343 | const QProtobufSelfcheckIterator fieldBegin = m_it; // copy this, we may need it later |
344 | if (!decodeHeader(it&: m_it, fieldIndex&: fieldNumber, wireType&: m_wireType)) { |
345 | setError(error: QAbstractProtobufSerializer::Error::InvalidHeader, |
346 | errorString: "Message received doesn't contain valid header byte." ); |
347 | return -1; |
348 | } |
349 | |
350 | int index = ordering->indexOfFieldNumber(fieldNumber); |
351 | if (index == -1) { |
352 | // This is an unknown field, it may have been added in a later revision |
353 | // of the Message we are currently deserializing. We must store the |
354 | // bytes for this field and re-emit them later if this message is |
355 | // serialized again. |
356 | if (auto length = skipField(fieldBegin); length < 0) { |
357 | return -1; |
358 | } else if (length > 0 && m_parent->preserveUnknownFields) { |
359 | QByteArrayView fieldData(fieldBegin.data(), length); |
360 | QProtobufMessagePrivate::storeUnknownEntry(message, entry: fieldData, fieldNumber); |
361 | } |
362 | continue; |
363 | } |
364 | |
365 | if (ordering->fieldFlags(index).testAnyFlags(flags: { QtProtobufPrivate::FieldFlag::Message, |
366 | QtProtobufPrivate::FieldFlag::Map })) { |
367 | auto opt = deserializeVarintCommon<QtProtobuf::uint64>(it&: m_it); |
368 | if (!opt) { |
369 | setUnexpectedEndOfStreamError(); |
370 | return -1; |
371 | } |
372 | |
373 | quint64 length = *opt; |
374 | if (!m_it.isValid() || quint64(m_it.bytesLeft()) < length |
375 | || length > quint64(QByteArray::maxSize())) { |
376 | setUnexpectedEndOfStreamError(); |
377 | return -1; |
378 | } |
379 | |
380 | m_state.push_back(t: m_it.data() + length); |
381 | } |
382 | return index; |
383 | } |
384 | |
385 | if (!m_it.isValid()) |
386 | setUnexpectedEndOfStreamError(); |
387 | |
388 | m_state.pop_back(); |
389 | return -1; |
390 | } |
391 | |
392 | bool QProtobufDeserializerImpl::deserializeScalarField(QVariant &value, |
393 | const QtProtobufPrivate::QProtobufFieldInfo |
394 | &fieldInfo) |
395 | { |
396 | QMetaType metaType = value.metaType(); |
397 | |
398 | // All repeated scalar types should have LenghtDelimited wiretype. |
399 | // If the wiretype received from the wire is not LenghtDelimited, |
400 | // that most probably means that we received the list in wrong |
401 | // format. This can happen because of mismatch of the field packed |
402 | // option in the protobuf schema on the wire ends. |
403 | // look for non-packed list in this case. Otherwise it's the regular |
404 | // packed repeated field. |
405 | // See the conformance tests |
406 | // Required.Proto3.ProtobufInput.ValidDataRepeated.*.UnpackedInput |
407 | // for details. |
408 | bool isNonPacked = m_wireType != QtProtobuf::WireTypes::LengthDelimited && |
409 | fieldInfo.fieldFlags().testFlags(flags: FieldFlag::Repeated); |
410 | |
411 | auto basicHandler = findIntegratedTypeHandler(metaType, nonPacked: isNonPacked); |
412 | if (!basicHandler) |
413 | return false; |
414 | |
415 | if (basicHandler->wireType != m_wireType) { |
416 | setError(error: QAbstractProtobufSerializer::Error::InvalidHeader, |
417 | errorString: QCoreApplication::translate(context: "QtProtobuf" , |
418 | key: "Invalid wiretype for the %1 " |
419 | "field number %1. Expected %2, received %3" ) |
420 | .arg(a: QString::fromUtf8(utf8: metaType.name())) |
421 | .arg(a: fieldInfo.fieldNumber()) |
422 | .arg(a: basicHandler ? static_cast<int>(basicHandler->wireType) : -1) |
423 | .arg(a: static_cast<int>(m_wireType))); |
424 | value.clear(); |
425 | } else if (!basicHandler->deserializer(m_it, value)) { |
426 | value.clear(); |
427 | setUnexpectedEndOfStreamError(); |
428 | } |
429 | |
430 | return true; |
431 | } |
432 | |
433 | qsizetype QProtobufDeserializerImpl::skipField(const QProtobufSelfcheckIterator &fieldBegin) |
434 | { |
435 | switch (m_wireType) { |
436 | case QtProtobuf::WireTypes::Varint: |
437 | skipVarint(); |
438 | break; |
439 | case QtProtobuf::WireTypes::Fixed32: |
440 | m_it += sizeof(decltype(QtProtobuf::fixed32::t)); |
441 | break; |
442 | case QtProtobuf::WireTypes::Fixed64: |
443 | m_it += sizeof(decltype(QtProtobuf::fixed64::t)); |
444 | break; |
445 | case QtProtobuf::WireTypes::LengthDelimited: |
446 | skipLengthDelimited(); |
447 | break; |
448 | case QtProtobuf::WireTypes::Unknown: |
449 | default: |
450 | Q_UNREACHABLE(); |
451 | return 0; |
452 | } |
453 | |
454 | if (!m_it.isValid()) { |
455 | setUnexpectedEndOfStreamError(); |
456 | return -1; |
457 | } |
458 | |
459 | return std::distance(first: fieldBegin, last: m_it); |
460 | } |
461 | |
462 | void QProtobufDeserializerImpl::skipVarint() |
463 | { |
464 | while ((*m_it) & 0x80) |
465 | ++m_it; |
466 | ++m_it; |
467 | } |
468 | |
469 | void QProtobufDeserializerImpl::skipLengthDelimited() |
470 | { |
471 | //Get length of length-delimited field |
472 | auto opt = deserializeVarintCommon<QtProtobuf::uint64>(it&: m_it); |
473 | if (!opt) { |
474 | m_it += m_it.bytesLeft() + 1; |
475 | return; |
476 | } |
477 | QtProtobuf::uint64 length = opt.value(); |
478 | m_it += length; |
479 | } |
480 | |
481 | void QProtobufDeserializerImpl::setUnexpectedEndOfStreamError() |
482 | { |
483 | setError(error: QAbstractProtobufSerializer::Error::UnexpectedEndOfStream, |
484 | errorString: QCoreApplication::translate(context: "QtProtobuf" , key: "Unexpected end of stream" )); |
485 | } |
486 | |
487 | bool QProtobufDeserializerImpl::(QProtobufSelfcheckIterator &it, int &fieldIndex, |
488 | QtProtobuf::WireTypes &wireType) |
489 | { |
490 | if (it.bytesLeft() == 0) |
491 | return false; |
492 | auto opt = deserializeVarintCommon<uint32_t>(it); |
493 | if (!opt) |
494 | return false; |
495 | uint32_t = opt.value(); |
496 | wireType = static_cast<QtProtobuf::WireTypes>(header & 0b00000111); |
497 | fieldIndex = header >> 3; |
498 | |
499 | constexpr int maxFieldIndex = (1 << 29) - 1; |
500 | return fieldIndex <= maxFieldIndex && fieldIndex > 0 |
501 | && (wireType == QtProtobuf::WireTypes::Varint || wireType == QtProtobuf::WireTypes::Fixed64 |
502 | || wireType == QtProtobuf::WireTypes::Fixed32 |
503 | || wireType == QtProtobuf::WireTypes::LengthDelimited); |
504 | } |
505 | |
506 | QProtobufSerializerPrivate::QProtobufSerializerPrivate() : serializer(this), deserializer(this) |
507 | { |
508 | } |
509 | |
510 | void QProtobufSerializerPrivate::clearError() |
511 | { |
512 | lastError = QAbstractProtobufSerializer::Error::None; |
513 | lastErrorString.clear(); |
514 | } |
515 | |
516 | /*! |
517 | Constructs a new serializer instance. |
518 | */ |
519 | QProtobufSerializer::QProtobufSerializer() : d_ptr(new QProtobufSerializerPrivate()) |
520 | { |
521 | } |
522 | |
523 | /*! |
524 | Destroys the serializer instance. |
525 | */ |
526 | QProtobufSerializer::~QProtobufSerializer() = default; |
527 | |
528 | QByteArray QProtobufSerializer::serializeMessage(const QProtobufMessage *message) const |
529 | { |
530 | d_ptr->clearError(); |
531 | d_ptr->serializer.reset(); |
532 | d_ptr->serializer.serializeMessage(message); |
533 | d_ptr->serializer.serializeUnknownFields(message); |
534 | auto result = d_ptr->serializer.result(); |
535 | d_ptr->serializer.reset(); |
536 | return result; |
537 | } |
538 | |
539 | bool QProtobufSerializer::deserializeMessage(QProtobufMessage *message, QByteArrayView data) const |
540 | { |
541 | d_ptr->clearError(); |
542 | d_ptr->deserializer.reset(data); |
543 | d_ptr->deserializer.deserializeMessage(message); |
544 | d_ptr->deserializer.reset(data: {}); |
545 | return d_ptr->lastError == QAbstractProtobufSerializer::Error::None; |
546 | } |
547 | |
548 | /*! |
549 | Returns the last deserialization error for the serializer instance. |
550 | \sa lastErrorString() |
551 | */ |
552 | QAbstractProtobufSerializer::Error QProtobufSerializer::lastError() const |
553 | { |
554 | return d_ptr->lastError; |
555 | } |
556 | |
557 | /*! |
558 | Returns the last deserialization error string for the serializer instance. |
559 | \sa lastError() |
560 | */ |
561 | QString QProtobufSerializer::lastErrorString() const |
562 | { |
563 | return d_ptr->lastErrorString; |
564 | } |
565 | |
566 | /*! |
567 | Controls whether the unknown fields received from the wire should be |
568 | stored in the resulting message or if it should be omitted, based |
569 | on \a preserveUnknownFields. |
570 | \since 6.7 |
571 | */ |
572 | void QProtobufSerializer::shouldPreserveUnknownFields(bool preserveUnknownFields) |
573 | { |
574 | d_ptr->preserveUnknownFields = preserveUnknownFields; |
575 | } |
576 | |
577 | QT_END_NAMESPACE |
578 | |