summaryrefslogtreecommitdiffstats
path: root/src/protobuf/qprotobufserializer_p.h
blob: f35204a5ea7ee755497d4beb1ec4d961f43162ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright (C) 2022 The Qt Company Ltd.
// Copyright (C) 2019 Alexey Edelev <semlanik@gmail.com>, Viktor Kopp <vifactor@gmail.com>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#ifndef QPROTOBUFSERIALIZER_P_H
#define QPROTOBUFSERIALIZER_P_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include <QtProtobuf/qabstractprotobufserializer.h>
#include <QtProtobuf/qprotobufpropertyordering.h>
#include <QtProtobuf/qprotobufserializer.h>
#include <QtProtobuf/qprotobufrepeatediterator.h>
#include <QtProtobuf/qtprotobuftypes.h>

#include <QtProtobuf/private/protobuffieldpresencechecker_p.h>
#include <QtProtobuf/private/qtprotobuflogging_p.h>
#include <QtProtobuf/private/qprotobufdeserializerbase_p.h>
#include <QtProtobuf/private/qprotobufselfcheckiterator_p.h>
#include <QtProtobuf/private/qprotobufserializerbase_p.h>

#include <QtCore/qendian.h>
#include <QtCore/qstring.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qhash.h>
#include <QtCore/qvariant.h>

QT_BEGIN_NAMESPACE

class QProtobufSerializerImpl final : public QProtobufSerializerBase
{
public:
    explicit QProtobufSerializerImpl(QProtobufSerializerPrivate *parent);
    ~QProtobufSerializerImpl();

    const QByteArray &result() const { return m_result; }

    void reset();
    void serializeUnknownFields(const QProtobufMessage *message);

    QProtobufSerializerPrivate *m_parent = nullptr;

private:
    bool serializeEnum(QVariant &value,
                       const QtProtobufPrivate::QProtobufFieldInfo &fieldInfo) override;
    bool serializeScalarField(const QVariant &value,
                              const QtProtobufPrivate::QProtobufFieldInfo &fieldInfo) override;
    void serializeMessageFieldBegin() override;
    void serializeMessageFieldEnd(const QProtobufMessage *message,
                                  const QtProtobufPrivate::QProtobufFieldInfo &fieldInfo) override;

    static QByteArray encodeHeader(int fieldNumber, QtProtobuf::WireTypes wireType);

    QByteArray m_result;
    QList<QByteArray> m_state;

    Q_DISABLE_COPY_MOVE(QProtobufSerializerImpl)
};

class QProtobufDeserializerImpl final : public QProtobufDeserializerBase
{
public:
    explicit QProtobufDeserializerImpl(QProtobufSerializerPrivate *parent);
    ~QProtobufDeserializerImpl();

    void reset(QByteArrayView data);

    QProtobufSelfcheckIterator m_it = {};

private:
    void setError(QAbstractProtobufSerializer::Error error, QAnyStringView errorString) override;
    bool deserializeEnum(QVariant &value,
                         const QtProtobufPrivate::QProtobufFieldInfo &fieldInfo) override;
    int nextFieldIndex(QProtobufMessage *message) override;
    bool deserializeScalarField(QVariant &value,
                                const QtProtobufPrivate::QProtobufFieldInfo &fieldInfo) override;

    qsizetype skipField(const QProtobufSelfcheckIterator &fieldBegin);
    void skipVarint();
    void skipLengthDelimited();
    void setUnexpectedEndOfStreamError();

    [[nodiscard]]
    static bool decodeHeader(QProtobufSelfcheckIterator &it, int &fieldIndex,
                             QtProtobuf::WireTypes &wireType);

    QtProtobuf::WireTypes m_wireType = QtProtobuf::WireTypes::Unknown;
    QList<QByteArrayView::iterator> m_state;
    QProtobufSerializerPrivate *m_parent = nullptr;

    Q_DISABLE_COPY_MOVE(QProtobufDeserializerImpl)
};

class QProtobufSerializerPrivate
{
public:
    // Serializer is interface function for serialize method
    using Serializer = QByteArray (*)(const QVariant &, const QByteArray &);
    // Deserializer is interface function for deserialize method
    using Deserializer = bool (*)(QProtobufSelfcheckIterator &, QVariant &);
    // Function checks if value in QVariant is considered to be non-ignorable.

    // SerializationHandlers contains set of objects that required for class
    // serializaion/deserialization
    struct ProtobufSerializationHandler
    {
        QMetaType metaType;
        Serializer serializer; // serializer assigned to class
        Deserializer deserializer; // deserializer assigned to class
        ProtobufFieldPresenceChecker::Function isPresent; // checks if contains non-ignorable value
        QtProtobuf::WireTypes wireType; // Serialization WireType
    };

    QProtobufSerializerPrivate();
    ~QProtobufSerializerPrivate() = default;

    template<typename T, QByteArray (*s)(const T &)>
    static QByteArray serializeWrapper(const QVariant &variantValue, const QByteArray &header)
    {
        return header + s(variantValue.value<T>());
    }

    template<typename T, QByteArray (*s)(const T &, const QByteArray &)>
    static QByteArray serializeNonPackedWrapper(const QVariant &variantValue,
                                                const QByteArray &header)
    {
        return s(variantValue.value<T>(), header);
    }

    void clearError();

    QAbstractProtobufSerializer::Error lastError =
            QAbstractProtobufSerializer::Error::UnknownType;
    QString lastErrorString;

    bool preserveUnknownFields = true;

    QProtobufSerializerImpl serializer;
    QProtobufDeserializerImpl deserializer;

private:
    Q_DISABLE_COPY_MOVE(QProtobufSerializerPrivate)
};

QT_END_NAMESPACE

#endif // QPROTOBUFSERIALIZER_P_H