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

source code of qtgrpc/src/protobuf/qprotobufserializer.cpp