29 #include "qprotobufselfcheckiterator.h"
30 #include "qtprotobuftypes.h"
31 #include "qtprotobuflogging.h"
32 #include "qabstractprotobufserializer.h"
34 namespace QtProtobuf {
41 class QProtobufSerializer;
43 class QProtobufSerializerPrivate final
45 Q_DISABLE_COPY_MOVE(QProtobufSerializerPrivate)
51 using Serializer = QByteArray(*)(
const QVariant &,
int &);
55 using Deserializer = void(*)(QProtobufSelfcheckIterator &, QVariant &);
61 struct SerializationHandlers {
62 Serializer serializer;
63 Deserializer deserializer;
67 using SerializerRegistry = std::unordered_map<
int, SerializationHandlers>;
69 QProtobufSerializerPrivate(QProtobufSerializer *q);
70 ~QProtobufSerializerPrivate() =
default;
76 typename std::enable_if_t<std::is_integral<V>::value
77 && std::is_unsigned<V>::value,
int> = 0>
78 static QByteArray serializeVarintCommon(
const V &value) {
79 qProtoDebug() << __func__ <<
"value" << value;
85 result.append((varint & 0b01111111) | 0b10000000);
90 if (result.isEmpty()) {
94 result.data()[result.size() - 1] &= ~0b10000000;
108 template <
typename V,
109 typename std::enable_if_t<std::is_floating_point<V>::value,
int> = 0>
110 static QByteArray serializeBasic(
const V &value,
int &) {
111 qProtoDebug() << __func__ <<
"value" << value;
114 QByteArray result(
sizeof(V),
'\0');
115 *
reinterpret_cast<V *
>(result.data()) = value;
128 template <
typename V,
129 typename std::enable_if_t<std::is_same<V, fixed32>::value
130 || std::is_same<V, fixed64>::value
131 || std::is_same<V, sfixed32>::value
132 || std::is_same<V, sfixed64>::value,
int> = 0>
133 static QByteArray serializeBasic(
const V &value,
int &) {
134 qProtoDebug() << __func__ <<
"value" << value;
137 QByteArray result(
sizeof(V),
'\0');
138 *
reinterpret_cast<V *
>(result.data()) = value;
153 template <
typename V,
154 typename std::enable_if_t<std::is_integral<V>::value
155 && std::is_signed<V>::value,
int> = 0>
156 static QByteArray serializeBasic(
const V &value,
int &outFieldIndex) {
157 qProtoDebug() << __func__ <<
"value" << value;
158 using UV =
typename std::make_unsigned<V>::type;
162 V zigZagValue = (value << 1) ^ (value >> (
sizeof(UV) * 8 - 1));
163 uValue =
static_cast<UV
>(zigZagValue);
164 return serializeBasic(uValue, outFieldIndex);
167 template <
typename V,
168 typename std::enable_if_t<std::is_same<V, int32>::value
169 || std::is_same<V, int64>::value,
int> = 0>
170 static QByteArray serializeBasic(
const V &value,
int &outFieldIndex) {
171 qProtoDebug() << __func__ <<
"value" << value;
172 using UV =
typename std::make_unsigned<V>::type;
173 return serializeBasic(
static_cast<UV
>(value), outFieldIndex);
187 template <
typename V,
188 typename std::enable_if_t<std::is_integral<V>::value
189 && std::is_unsigned<V>::value,
int> = 0>
190 static QByteArray serializeBasic(
const V &value,
int &outFieldIndex) {
191 qProtoDebug() << __func__ <<
"value" << value;
195 while (varint != 0) {
197 result.append((varint & 0b01111111) | 0b10000000);
204 if (result.size() == 0) {
205 outFieldIndex = QtProtobufPrivate::NotUsedFieldIndex;
208 result.data()[result.size() - 1] &= ~0b10000000;
214 template <
typename V,
215 typename std::enable_if_t<std::is_same<V, QString>::value,
int> = 0>
216 static QByteArray serializeBasic(
const V &value,
int &) {
217 return serializeLengthDelimited(value.toUtf8());
220 template <
typename V,
221 typename std::enable_if_t<std::is_same<V, QByteArray>::value,
int> = 0>
222 static QByteArray serializeBasic(
const V &value,
int &) {
223 return serializeLengthDelimited(value);
228 typename std::enable_if_t<!(std::is_same<V, QString>::value
229 || std::is_base_of<QObject, V>::value),
int> = 0>
230 static QByteArray serializeListType(
const QList<V> &listValue,
int &outFieldIndex) {
231 qProtoDebug() << __func__ <<
"listValue.count" << listValue.count() <<
"outFiledIndex" << outFieldIndex;
233 if (listValue.count() <= 0) {
234 outFieldIndex = QtProtobufPrivate::NotUsedFieldIndex;
238 int empty = QtProtobufPrivate::NotUsedFieldIndex;
239 QByteArray serializedList;
240 for (
auto &value : listValue) {
241 QByteArray element = serializeBasic<V>(value, empty);
242 if (element.isEmpty()) {
243 element.append(
'\0');
245 serializedList.append(element);
248 serializedList = prependLengthDelimitedSize(serializedList);
249 return serializedList;
253 typename std::enable_if_t<std::is_same<V, QString>::value,
int> = 0>
254 static QByteArray serializeListType(
const QStringList &listValue,
int &outFieldIndex) {
255 qProtoDebug() << __func__ <<
"listValue.count" << listValue.count() <<
"outFiledIndex" << outFieldIndex;
257 if (listValue.count() <= 0) {
258 outFieldIndex = QtProtobufPrivate::NotUsedFieldIndex;
262 QByteArray serializedList;
263 for (
auto &value : listValue) {
264 serializedList.append(QProtobufSerializerPrivate::encodeHeader(outFieldIndex,
LengthDelimited));
265 serializedList.append(serializeLengthDelimited(value.toUtf8()));
268 outFieldIndex = QtProtobufPrivate::NotUsedFieldIndex;
269 return serializedList;
275 template <
typename V,
276 typename std::enable_if_t<std::is_integral<V>::value
277 && std::is_unsigned<V>::value,
int> = 0>
278 static V deserializeVarintCommon(QProtobufSelfcheckIterator &it) {
279 qProtoDebug() << __func__ <<
"currentByte:" << QString::number((*it), 16);
284 uint64_t
byte =
static_cast<uint64_t
>(*it);
285 value += (
byte & 0b01111111) << k;
287 if (((*it) & 0b10000000) == 0) {
297 template <
typename V,
298 typename std::enable_if_t<std::is_floating_point<V>::value
299 || std::is_same<V, fixed32>::value
300 || std::is_same<V, fixed64>::value
301 || std::is_same<V, sfixed32>::value
302 || std::is_same<V, sfixed64>::value,
int> = 0>
303 static void deserializeBasic(QProtobufSelfcheckIterator &it, QVariant &variantValue) {
304 qProtoDebug() << __func__ <<
"currentByte:" << QString::number((*it), 16);
306 variantValue = QVariant::fromValue(*(V *)((QByteArray::const_iterator&)it));
310 template <
typename V,
311 typename std::enable_if_t<std::is_integral<V>::value
312 && std::is_unsigned<V>::value,
int> = 0>
313 static void deserializeBasic(QProtobufSelfcheckIterator &it, QVariant &variantValue) {
314 qProtoDebug() << __func__ <<
"currentByte:" << QString::number((*it), 16);
316 variantValue = QVariant::fromValue(deserializeVarintCommon<V>(it));
319 template <
typename V,
320 typename std::enable_if_t<std::is_integral<V>::value
321 && std::is_signed<V>::value,
int> = 0>
322 static void deserializeBasic(QProtobufSelfcheckIterator &it, QVariant &variantValue) {
323 qProtoDebug() << __func__ <<
"currentByte:" << QString::number((*it), 16);
324 using UV =
typename std::make_unsigned<V>::type;
325 UV unsignedValue = deserializeVarintCommon<UV>(it);
326 V value = (unsignedValue >> 1) ^ (-1 * (unsignedValue & 1));
327 variantValue = QVariant::fromValue<V>(value);
330 template <
typename V,
331 typename std::enable_if_t<std::is_same<int32, V>::value
332 || std::is_same<int64, V>::value,
int> = 0>
333 static void deserializeBasic(QProtobufSelfcheckIterator &it, QVariant &variantValue) {
334 qProtoDebug() << __func__ <<
"currentByte:" << QString::number((*it), 16);
335 using UV =
typename std::make_unsigned<V>::type;
336 UV unsignedValue = deserializeVarintCommon<UV>(it);
337 V value =
static_cast<V
>(unsignedValue);
338 variantValue = QVariant::fromValue(value);
342 template <
typename V,
343 typename std::enable_if_t<std::is_same<QByteArray, V>::value,
int> = 0>
344 static void deserializeBasic(QProtobufSelfcheckIterator &it, QVariant &variantValue) {
345 variantValue = QVariant::fromValue(deserializeLengthDelimited(it));
348 template <
typename V,
349 typename std::enable_if_t<std::is_same<QString, V>::value,
int> = 0>
350 static void deserializeBasic(QProtobufSelfcheckIterator &it, QVariant &variantValue) {
351 variantValue = QVariant::fromValue(QString::fromUtf8(deserializeLengthDelimited(it)));
355 template <
typename V,
356 typename std::enable_if_t<!std::is_base_of<QObject, V>::value,
int> = 0>
357 static void deserializeList(QProtobufSelfcheckIterator &it, QVariant &previousValue) {
358 qProtoDebug() << __func__ <<
"currentByte:" << QString::number((*it), 16);
361 unsigned int count = deserializeVarintCommon<uint32>(it);
362 QProtobufSelfcheckIterator lastVarint = it + count;
363 while (it != lastVarint) {
364 QVariant variantValue;
365 deserializeBasic<V>(it, variantValue);
366 out.append(variantValue.value<V>());
368 previousValue.setValue(out);
374 static QByteArray deserializeLengthDelimited(QProtobufSelfcheckIterator &it) {
375 qProtoDebug() << __func__ <<
"currentByte:" << QString::number((*it), 16);
377 unsigned int length = deserializeVarintCommon<uint32>(it);
378 QByteArray result((QByteArray::const_iterator&)it, length);
383 static QByteArray serializeLengthDelimited(
const QByteArray &data) {
384 qProtoDebug() << __func__ <<
"data.size" << data.size() <<
"data" << data.toHex();
385 QByteArray result(data);
387 result = prependLengthDelimitedSize(result);
391 static bool decodeHeader(QProtobufSelfcheckIterator &it,
int &fieldIndex,
WireTypes &wireType);
392 static QByteArray encodeHeader(
int fieldIndex,
WireTypes wireType);
401 static QByteArray prependLengthDelimitedSize(
const QByteArray &data)
403 return serializeVarintCommon<uint32_t>(data.size()) + data;
406 template <
typename T,
407 QByteArray(*s)(
const T &,
int &)>
408 static QByteArray serializeWrapper(
const QVariant &variantValue,
int &fieldIndex) {
409 if (variantValue.isNull()) {
410 fieldIndex = QtProtobufPrivate::NotUsedFieldIndex;
413 const T& value = *(
static_cast<const T *
>(variantValue.data()));
414 return s(value, fieldIndex);
417 template <
typename T, QByteArray(*s)(
const T &,
int &), Deserializer d,
WireTypes type,
418 typename std::enable_if_t<!std::is_base_of<QObject, T>::value,
int> = 0>
419 static void wrapSerializer() {
420 handlers[qMetaTypeId<T>()] = {
421 serializeWrapper<T, s>,
427 template <
typename T,
typename S, QByteArray(*s)(
const S &,
int &), Deserializer d,
WireTypes type,
428 typename std::enable_if_t<!std::is_base_of<QObject, T>::value,
int> = 0>
429 static void wrapSerializer() {
430 handlers[qMetaTypeId<T>()] = {
431 serializeWrapper<S, s>,
439 static int skipSerializedFieldBytes(QProtobufSelfcheckIterator &it,
WireTypes type);
440 static void skipVarint(QProtobufSelfcheckIterator &it);
441 static void skipLengthDelimited(QProtobufSelfcheckIterator &it);
443 QByteArray serializeProperty(
const QVariant &propertyValue,
const QProtobufMetaProperty &metaProperty);
444 void deserializeProperty(QObject *
object,
const QProtobufMetaObject &metaObject, QProtobufSelfcheckIterator &it);
446 void deserializeMapPair(QVariant &key, QVariant &value, QProtobufSelfcheckIterator &it);
448 static SerializerRegistry handlers;
449 QProtobufSerializer *q_ptr;
468 inline QByteArray QProtobufSerializerPrivate::encodeHeader(
int fieldIndex,
WireTypes wireType)
470 uint32_t header = (fieldIndex << 3) | wireType;
471 return serializeVarintCommon<uint32_t>(header);
482 inline bool QProtobufSerializerPrivate::decodeHeader(QProtobufSelfcheckIterator &it,
int &fieldIndex,
WireTypes &wireType)
484 uint32_t header = deserializeVarintCommon<uint32_t>(it);
485 wireType =
static_cast<WireTypes>(header & 0b00000111);
486 fieldIndex = header >> 3;
488 constexpr
int maxFieldIndex = (1 << 29) - 1;
489 return fieldIndex <= maxFieldIndex && fieldIndex > 0 && (wireType ==
Varint
WireTypes
The WireTypes enumeration reflects protobuf default wiretypes.
Definition: qtprotobuftypes.h:47
@ Varint
int32, int64, uint32, uint64, sint32, sint64, bool, enum
Definition: qtprotobuftypes.h:49
@ Fixed32
fixed32, sfixed32, float
Definition: qtprotobuftypes.h:54
@ Fixed64
fixed64, sfixed64, double
Definition: qtprotobuftypes.h:50
@ LengthDelimited
string, bytes, embedded messages, packed repeated fields
Definition: qtprotobuftypes.h:51