1 | // Copyright (C) 2022 The Qt Company Ltd. |
2 | // Copyright (C) 2019 Alexey Edelev <semlanik@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 | #ifndef QTPROTOBUFTYPES_H |
6 | #define QTPROTOBUFTYPES_H |
7 | |
8 | #include <QtProtobuf/qtprotobufglobal.h> |
9 | |
10 | #include <QtCore/QList> |
11 | #include <QtCore/QHash> |
12 | #include <QtCore/QMetaType> |
13 | #include <QtCore/QtEndian> |
14 | #include <QtProtobuf/QProtobufMessage> |
15 | |
16 | #include <memory> |
17 | #include <functional> |
18 | #include <list> |
19 | #include <type_traits> |
20 | #include <utility> |
21 | |
22 | QT_BEGIN_NAMESPACE |
23 | |
24 | namespace QtProtobufPrivate { |
25 | |
26 | enum FieldFlag : uint { NoFlags = 0x0, NonPacked = 0x1, Oneof = 0x02 }; |
27 | |
28 | struct QProtobufPropertyOrdering |
29 | { |
30 | const struct Data |
31 | { |
32 | uint version; |
33 | uint numFields; |
34 | uint fieldNumberOffset; |
35 | uint propertyIndexOffset; |
36 | uint flagsOffset; |
37 | uint fullPackageNameSize; |
38 | } *data; |
39 | |
40 | Q_PROTOBUF_EXPORT QUtf8StringView getMessageFullName() const; |
41 | Q_PROTOBUF_EXPORT QUtf8StringView getJsonName(int index) const; |
42 | Q_PROTOBUF_EXPORT int getFieldNumber(int index) const; |
43 | Q_PROTOBUF_EXPORT int getPropertyIndex(int index) const; |
44 | Q_PROTOBUF_EXPORT uint getFieldFlags(int index) const; |
45 | Q_PROTOBUF_EXPORT int indexOfFieldNumber(int fieldNumber) const; |
46 | int fieldCount() const { return int(data->numFields); } |
47 | |
48 | private: |
49 | const uint *uint_data() const; |
50 | const char *char_data() const; |
51 | const uint &uint_dataForIndex(int index, uint offset) const; |
52 | }; |
53 | static_assert(std::is_trivially_destructible_v<QProtobufPropertyOrdering>); |
54 | |
55 | extern Q_PROTOBUF_EXPORT void registerOrdering(QMetaType type, QProtobufPropertyOrdering ordering); |
56 | |
57 | // Convenience structure to hold a reference to a single entry |
58 | struct QProtobufPropertyOrderingInfo |
59 | { |
60 | QProtobufPropertyOrderingInfo(QProtobufPropertyOrdering ord, int ind) |
61 | : ordering(ord), index(ind) |
62 | { |
63 | Q_ASSERT(index >= 0); |
64 | } |
65 | |
66 | QUtf8StringView getJsonName() const { return ordering.getJsonName(index); } |
67 | int getFieldNumber() const |
68 | { |
69 | return (overrideFieldNumber >= 0) ? overrideFieldNumber : ordering.getFieldNumber(index); |
70 | } |
71 | int getPropertyIndex() const { return ordering.getPropertyIndex(index); } |
72 | uint getFieldFlags() const { return ordering.getFieldFlags(index); } |
73 | |
74 | // Needed for maps, which uses field number 1 and 2 for key and value respectively |
75 | QProtobufPropertyOrderingInfo infoForMapKey() const { return { ordering, index, 1 }; } |
76 | QProtobufPropertyOrderingInfo infoForMapValue() const { return { ordering, index, 2 }; } |
77 | |
78 | private: |
79 | QProtobufPropertyOrderingInfo(QProtobufPropertyOrdering ord, int ind, int fieldNumber) |
80 | : ordering(ord), index(ind), overrideFieldNumber(fieldNumber) |
81 | { |
82 | } |
83 | const QProtobufPropertyOrdering ordering; |
84 | const int index; |
85 | const int overrideFieldNumber = -1; // special case for maps |
86 | }; |
87 | |
88 | template<typename> |
89 | using sfinae = void; |
90 | template<typename T, typename = void> |
91 | [[maybe_unused]] static constexpr bool HasProtobufPropertyOrdering = false; |
92 | template<typename T> |
93 | [[maybe_unused]] static constexpr bool |
94 | HasProtobufPropertyOrdering<T, sfinae<decltype(T::propertyOrdering)>> = true; |
95 | } // namespace QtProtobufPrivate |
96 | |
97 | namespace QtProtobuf { |
98 | Q_NAMESPACE_EXPORT(Q_PROTOBUF_EXPORT) |
99 | |
100 | [[maybe_unused]] constexpr int InvalidFieldNumber = 0; |
101 | |
102 | enum class WireTypes |
103 | { |
104 | Unknown = -1, |
105 | Varint = 0, |
106 | Fixed64 = 1, |
107 | LengthDelimited = 2, |
108 | StartGroup = 3, |
109 | EndGroup = 4, |
110 | Fixed32 = 5 |
111 | }; |
112 | Q_ENUM_NS(WireTypes) |
113 | |
114 | // The 'tag' template param exists only create a unique type |
115 | template<typename T, typename tag> |
116 | struct TransparentWrapper |
117 | { |
118 | TransparentWrapper(T t = T()) : _t(t) { } |
119 | T _t; |
120 | operator T &() { return _t; } |
121 | operator T() const { return _t; } |
122 | TransparentWrapper &operator=(const T &t) |
123 | { |
124 | _t = t; |
125 | return *this; |
126 | } |
127 | |
128 | static T toType(TransparentWrapper t) { return t._t; } |
129 | static TransparentWrapper fromType(T _t) { return TransparentWrapper(_t); } |
130 | |
131 | static QString toString(TransparentWrapper t) { return QString::number(t._t); } |
132 | }; |
133 | |
134 | template<typename T, typename tag> |
135 | constexpr TransparentWrapper<T, tag> qbswap(TransparentWrapper<T, tag> source) |
136 | { |
137 | return { QT_PREPEND_NAMESPACE(qbswap)(source._t) }; |
138 | } |
139 | |
140 | using int32 = TransparentWrapper<int32_t, struct int_tag>; |
141 | using int64 = TransparentWrapper<int64_t, struct int_tag>; |
142 | using uint32 = uint32_t; |
143 | using uint64 = uint64_t; |
144 | using sint32 = int32_t; |
145 | using sint64 = int64_t; |
146 | using fixed32 = TransparentWrapper<uint32_t, struct fixed_tag>; |
147 | using fixed64 = TransparentWrapper<uint64_t, struct fixed_tag>; |
148 | using sfixed32 = TransparentWrapper<int32_t, struct fixed_tag>; |
149 | using sfixed64 = TransparentWrapper<int64_t, struct fixed_tag>; |
150 | using boolean = bool; |
151 | using int32List = QList<int32>; |
152 | using int64List = QList<int64>; |
153 | using uint32List = QList<uint32>; |
154 | using uint64List = QList<uint64>; |
155 | using sint32List = QList<sint32>; |
156 | using sint64List = QList<sint64>; |
157 | using fixed32List = QList<fixed32>; |
158 | using fixed64List = QList<fixed64>; |
159 | using sfixed32List = QList<sfixed32>; |
160 | using sfixed64List = QList<sfixed64>; |
161 | using floatList = QList<float>; |
162 | using doubleList = QList<double>; |
163 | using boolList = QList<bool>; |
164 | |
165 | using RegisterFunction = void (*)(); |
166 | // This struct is used for type registrations in generated code |
167 | struct ProtoTypeRegistrar |
168 | { |
169 | Q_PROTOBUF_EXPORT explicit ProtoTypeRegistrar(QtProtobuf::RegisterFunction initializer); |
170 | }; |
171 | |
172 | template<typename T> |
173 | bool repeatedValueCompare(const QList<T> &a, const QList<T> &b) |
174 | { |
175 | return std::equal(a.begin(), a.end(), b.begin(), b.end()); |
176 | } |
177 | |
178 | template<typename K, typename V> |
179 | bool repeatedValueCompare(const QHash<K, V> &a, const QHash<K, V> &b) |
180 | { |
181 | return a == b; |
182 | } |
183 | |
184 | template<typename T> |
185 | struct qMakeUnsignedImpl |
186 | { |
187 | using type = std::make_unsigned_t<T>; |
188 | }; |
189 | template<typename T> |
190 | struct qMakeUnsignedImpl<TransparentWrapper<T, struct fixed_tag>> |
191 | { |
192 | using type = TransparentWrapper<std::make_unsigned_t<T>, fixed_tag>; |
193 | }; |
194 | template<> |
195 | struct qMakeUnsignedImpl<int32> |
196 | { |
197 | using type = uint32_t; |
198 | }; |
199 | template<> |
200 | struct qMakeUnsignedImpl<int64> |
201 | { |
202 | using type = uint64_t; |
203 | }; |
204 | template<typename T> |
205 | using qMakeUnsigned = typename qMakeUnsignedImpl<T>::type; |
206 | |
207 | } // namespace QtProtobuf |
208 | |
209 | Q_PROTOBUF_EXPORT void qRegisterProtobufTypes(); |
210 | |
211 | QT_END_NAMESPACE |
212 | |
213 | QT_DECL_METATYPE_EXTERN_TAGGED(QtProtobuf::int32, QtProtobuf_int32, Q_PROTOBUF_EXPORT) |
214 | QT_DECL_METATYPE_EXTERN_TAGGED(QtProtobuf::int64, QtProtobuf_int64, Q_PROTOBUF_EXPORT) |
215 | QT_DECL_METATYPE_EXTERN_TAGGED(QtProtobuf::fixed32, QtProtobuf_fixed32, Q_PROTOBUF_EXPORT) |
216 | QT_DECL_METATYPE_EXTERN_TAGGED(QtProtobuf::fixed64, QtProtobuf_fixed64, Q_PROTOBUF_EXPORT) |
217 | QT_DECL_METATYPE_EXTERN_TAGGED(QtProtobuf::sfixed32, QtProtobuf_sfixed32, Q_PROTOBUF_EXPORT) |
218 | QT_DECL_METATYPE_EXTERN_TAGGED(QtProtobuf::sfixed64, QtProtobuf_sfixed64, Q_PROTOBUF_EXPORT) |
219 | |
220 | #endif // QTPROTOBUFTYPES_H |
221 | |