1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #ifndef GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
9 #define GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
10
11 #include <cstdint>
12 #include <type_traits>
13
14 #include "google/protobuf/arena.h"
15 #include "google/protobuf/arenastring.h"
16 #include "google/protobuf/io/coded_stream.h"
17 #include "google/protobuf/parse_context.h"
18 #include "google/protobuf/wire_format_lite.h"
19
20 #ifdef SWIG
21 #error "You cannot SWIG proto headers"
22 #endif
23
24 namespace google {
25 namespace protobuf {
26 namespace internal {
27
28 // Define constants for given wire field type
29 template <WireFormatLite::FieldType field_type, typename Type>
30 class MapWireFieldTypeTraits {};
31
32 #define TYPE_TRAITS(FieldType, CType, WireFormatType) \
33 template <typename Type> \
34 class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, Type> { \
35 public: \
36 using TypeOnMemory = \
37 std::conditional_t<WireFormatLite::TYPE_##FieldType == \
38 WireFormatLite::TYPE_MESSAGE, \
39 Type*, CType>; \
40 using MapEntryAccessorType = \
41 std::conditional_t<std::is_enum<Type>::value, int, Type>; \
42 static const WireFormatLite::WireType kWireType = \
43 WireFormatLite::WIRETYPE_##WireFormatType; \
44 };
45
46 TYPE_TRAITS(MESSAGE, Type, LENGTH_DELIMITED)
47 TYPE_TRAITS(STRING, ArenaStringPtr, LENGTH_DELIMITED)
48 TYPE_TRAITS(BYTES, ArenaStringPtr, LENGTH_DELIMITED)
49 TYPE_TRAITS(INT64, int64_t, VARINT)
50 TYPE_TRAITS(UINT64, uint64_t, VARINT)
51 TYPE_TRAITS(INT32, int32_t, VARINT)
52 TYPE_TRAITS(UINT32, uint32_t, VARINT)
53 TYPE_TRAITS(SINT64, int64_t, VARINT)
54 TYPE_TRAITS(SINT32, int32_t, VARINT)
55 TYPE_TRAITS(ENUM, int, VARINT)
56 TYPE_TRAITS(DOUBLE, double, FIXED64)
57 TYPE_TRAITS(FLOAT, float, FIXED32)
58 TYPE_TRAITS(FIXED64, uint64_t, FIXED64)
59 TYPE_TRAITS(FIXED32, uint32_t, FIXED32)
60 TYPE_TRAITS(SFIXED64, int64_t, FIXED64)
61 TYPE_TRAITS(SFIXED32, int32_t, FIXED32)
62 TYPE_TRAITS(BOOL, bool, VARINT)
63
64 #undef TYPE_TRAITS
65
66 template <WireFormatLite::FieldType field_type, typename Type>
67 class MapTypeHandler;
68
69 template <typename Type>
70 class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
71 public:
72 // Enum type cannot be used for MapTypeHandler::Read. Define a type which will
73 // replace Enum with int.
74 typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
75 Type>::MapEntryAccessorType
76 MapEntryAccessorType;
77 // Internal stored type in MapEntryLite for given wire field type.
78 typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
79 Type>::TypeOnMemory TypeOnMemory;
80 // Corresponding wire type for field type.
81 static constexpr WireFormatLite::WireType kWireType =
82 MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kWireType;
83
84 // Functions used in parsing and serialization. ===================
85 static inline size_t ByteSize(const MapEntryAccessorType& value);
86 static inline int GetCachedSize(const MapEntryAccessorType& value);
87
88 static inline uint8_t* Write(int field, const MapEntryAccessorType& value,
89 uint8_t* ptr, io::EpsCopyOutputStream* stream);
90
91 // Functions to manipulate data on memory. ========================
92 static inline void DeleteNoArena(const Type* x);
93 static constexpr TypeOnMemory Constinit();
94 };
95
96 #define MAP_HANDLER(FieldType) \
97 template <typename Type> \
98 class MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type> { \
99 public: \
100 typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
101 Type>::MapEntryAccessorType \
102 MapEntryAccessorType; \
103 typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
104 Type>::TypeOnMemory TypeOnMemory; \
105 static const WireFormatLite::WireType kWireType = \
106 MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
107 Type>::kWireType; \
108 static inline int ByteSize(const MapEntryAccessorType& value); \
109 static inline int GetCachedSize(const MapEntryAccessorType& value); \
110 static inline uint8_t* Write(int field, const MapEntryAccessorType& value, \
111 uint8_t* ptr, \
112 io::EpsCopyOutputStream* stream); \
113 static inline void DeleteNoArena(const TypeOnMemory& x); \
114 static void DeleteNoArena(TypeOnMemory& value); \
115 static constexpr TypeOnMemory Constinit(); \
116 };
117 MAP_HANDLER(STRING)
MAP_HANDLER(BYTES)118 MAP_HANDLER(BYTES)
119 MAP_HANDLER(INT64)
120 MAP_HANDLER(UINT64)
121 MAP_HANDLER(INT32)
122 MAP_HANDLER(UINT32)
123 MAP_HANDLER(SINT64)
124 MAP_HANDLER(SINT32)
125 MAP_HANDLER(ENUM)
126 MAP_HANDLER(DOUBLE)
127 MAP_HANDLER(FLOAT)
128 MAP_HANDLER(FIXED64)
129 MAP_HANDLER(FIXED32)
130 MAP_HANDLER(SFIXED64)
131 MAP_HANDLER(SFIXED32)
132 MAP_HANDLER(BOOL)
133 #undef MAP_HANDLER
134
135 template <typename Type>
136 inline size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::ByteSize(
137 const MapEntryAccessorType& value) {
138 return WireFormatLite::MessageSizeNoVirtual(value);
139 }
140
141 #define GOOGLE_PROTOBUF_BYTE_SIZE(FieldType, DeclaredType) \
142 template <typename Type> \
143 inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
144 const MapEntryAccessorType& value) { \
145 return static_cast<int>(WireFormatLite::DeclaredType##Size(value)); \
146 }
147
GOOGLE_PROTOBUF_BYTE_SIZE(STRING,String)148 GOOGLE_PROTOBUF_BYTE_SIZE(STRING, String)
149 GOOGLE_PROTOBUF_BYTE_SIZE(BYTES, Bytes)
150 GOOGLE_PROTOBUF_BYTE_SIZE(INT64, Int64)
151 GOOGLE_PROTOBUF_BYTE_SIZE(UINT64, UInt64)
152 GOOGLE_PROTOBUF_BYTE_SIZE(INT32, Int32)
153 GOOGLE_PROTOBUF_BYTE_SIZE(UINT32, UInt32)
154 GOOGLE_PROTOBUF_BYTE_SIZE(SINT64, SInt64)
155 GOOGLE_PROTOBUF_BYTE_SIZE(SINT32, SInt32)
156 GOOGLE_PROTOBUF_BYTE_SIZE(ENUM, Enum)
157
158 #undef GOOGLE_PROTOBUF_BYTE_SIZE
159
160 #define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
161 template <typename Type> \
162 inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
163 const MapEntryAccessorType& /* value */) { \
164 return WireFormatLite::k##DeclaredType##Size; \
165 }
166
167 FIXED_BYTE_SIZE(DOUBLE, Double)
168 FIXED_BYTE_SIZE(FLOAT, Float)
169 FIXED_BYTE_SIZE(FIXED64, Fixed64)
170 FIXED_BYTE_SIZE(FIXED32, Fixed32)
171 FIXED_BYTE_SIZE(SFIXED64, SFixed64)
172 FIXED_BYTE_SIZE(SFIXED32, SFixed32)
173 FIXED_BYTE_SIZE(BOOL, Bool)
174
175 #undef FIXED_BYTE_SIZE
176
177 template <typename Type>
178 inline int MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetCachedSize(
179 const MapEntryAccessorType& value) {
180 return static_cast<int>(WireFormatLite::LengthDelimitedSize(
181 static_cast<size_t>(value.GetCachedSize())));
182 }
183
184 #define GET_CACHED_SIZE(FieldType, DeclaredType) \
185 template <typename Type> \
186 inline int \
187 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
188 const MapEntryAccessorType& value) { \
189 return static_cast<int>(WireFormatLite::DeclaredType##Size(value)); \
190 }
191
GET_CACHED_SIZE(STRING,String)192 GET_CACHED_SIZE(STRING, String)
193 GET_CACHED_SIZE(BYTES, Bytes)
194 GET_CACHED_SIZE(INT64, Int64)
195 GET_CACHED_SIZE(UINT64, UInt64)
196 GET_CACHED_SIZE(INT32, Int32)
197 GET_CACHED_SIZE(UINT32, UInt32)
198 GET_CACHED_SIZE(SINT64, SInt64)
199 GET_CACHED_SIZE(SINT32, SInt32)
200 GET_CACHED_SIZE(ENUM, Enum)
201
202 #undef GET_CACHED_SIZE
203
204 #define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
205 template <typename Type> \
206 inline int \
207 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
208 const MapEntryAccessorType& /* value */) { \
209 return WireFormatLite::k##DeclaredType##Size; \
210 }
211
212 GET_FIXED_CACHED_SIZE(DOUBLE, Double)
213 GET_FIXED_CACHED_SIZE(FLOAT, Float)
214 GET_FIXED_CACHED_SIZE(FIXED64, Fixed64)
215 GET_FIXED_CACHED_SIZE(FIXED32, Fixed32)
216 GET_FIXED_CACHED_SIZE(SFIXED64, SFixed64)
217 GET_FIXED_CACHED_SIZE(SFIXED32, SFixed32)
218 GET_FIXED_CACHED_SIZE(BOOL, Bool)
219
220 #undef GET_FIXED_CACHED_SIZE
221
222 template <typename Type>
223 inline uint8_t* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Write(
224 int field, const MapEntryAccessorType& value, uint8_t* ptr,
225 io::EpsCopyOutputStream* stream) {
226 ptr = stream->EnsureSpace(ptr);
227 return WireFormatLite::InternalWriteMessage(
228 field, value, value.GetCachedSize(), ptr, stream);
229 }
230
231 #define WRITE_METHOD(FieldType, DeclaredType) \
232 template <typename Type> \
233 inline uint8_t* \
234 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
235 int field, const MapEntryAccessorType& value, uint8_t* ptr, \
236 io::EpsCopyOutputStream* stream) { \
237 ptr = stream->EnsureSpace(ptr); \
238 return stream->Write##DeclaredType(field, value, ptr); \
239 }
240
WRITE_METHOD(STRING,String)241 WRITE_METHOD(STRING, String)
242 WRITE_METHOD(BYTES, Bytes)
243
244 #undef WRITE_METHOD
245 #define WRITE_METHOD(FieldType, DeclaredType) \
246 template <typename Type> \
247 inline uint8_t* \
248 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
249 int field, const MapEntryAccessorType& value, uint8_t* ptr, \
250 io::EpsCopyOutputStream* stream) { \
251 ptr = stream->EnsureSpace(ptr); \
252 return WireFormatLite::Write##DeclaredType##ToArray(field, value, ptr); \
253 }
254
255 WRITE_METHOD(INT64, Int64)
256 WRITE_METHOD(UINT64, UInt64)
257 WRITE_METHOD(INT32, Int32)
258 WRITE_METHOD(UINT32, UInt32)
259 WRITE_METHOD(SINT64, SInt64)
260 WRITE_METHOD(SINT32, SInt32)
261 WRITE_METHOD(ENUM, Enum)
262 WRITE_METHOD(DOUBLE, Double)
263 WRITE_METHOD(FLOAT, Float)
264 WRITE_METHOD(FIXED64, Fixed64)
265 WRITE_METHOD(FIXED32, Fixed32)
266 WRITE_METHOD(SFIXED64, SFixed64)
267 WRITE_METHOD(SFIXED32, SFixed32)
268 WRITE_METHOD(BOOL, Bool)
269
270 #undef WRITE_METHOD
271
272 // Definition for message handler
273
274 template <typename Type>
275 void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DeleteNoArena(
276 const Type* ptr) {
277 delete ptr;
278 }
279
280 template <typename Type>
281 constexpr auto MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Constinit()
282 -> TypeOnMemory {
283 return nullptr;
284 }
285
286 // Definition for string/bytes handler
287
288 #define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \
289 template <typename Type> \
290 void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::DeleteNoArena( \
291 TypeOnMemory& value) { \
292 value.Destroy(); \
293 } \
294 template <typename Type> \
295 constexpr auto \
296 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \
297 -> TypeOnMemory { \
298 return TypeOnMemory(&internal::fixed_address_empty_string, \
299 ConstantInitialized{}); \
300 }
301 STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING)
302 STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES)
303 #undef STRING_OR_BYTES_HANDLER_FUNCTIONS
304
305 #define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \
306 template <typename Type> \
307 inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
308 Type>::DeleteNoArena(TypeOnMemory& /* x */) {} \
309 template <typename Type> \
310 constexpr auto \
311 MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \
312 ->TypeOnMemory { \
313 return 0; \
314 }
315 PRIMITIVE_HANDLER_FUNCTIONS(INT64)
316 PRIMITIVE_HANDLER_FUNCTIONS(UINT64)
317 PRIMITIVE_HANDLER_FUNCTIONS(INT32)
318 PRIMITIVE_HANDLER_FUNCTIONS(UINT32)
319 PRIMITIVE_HANDLER_FUNCTIONS(SINT64)
320 PRIMITIVE_HANDLER_FUNCTIONS(SINT32)
321 PRIMITIVE_HANDLER_FUNCTIONS(ENUM)
322 PRIMITIVE_HANDLER_FUNCTIONS(DOUBLE)
323 PRIMITIVE_HANDLER_FUNCTIONS(FLOAT)
324 PRIMITIVE_HANDLER_FUNCTIONS(FIXED64)
325 PRIMITIVE_HANDLER_FUNCTIONS(FIXED32)
326 PRIMITIVE_HANDLER_FUNCTIONS(SFIXED64)
327 PRIMITIVE_HANDLER_FUNCTIONS(SFIXED32)
328 PRIMITIVE_HANDLER_FUNCTIONS(BOOL)
329 #undef PRIMITIVE_HANDLER_FUNCTIONS
330
331 // Functions for operating on a map entry using type handlers.
332 //
333 // Does not contain any representation (this class is not intended to be
334 // instantiated).
335 template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
336 WireFormatLite::FieldType kValueFieldType>
337 struct MapEntryFuncs {
338 typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
339 typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
340 enum : int {
341 kKeyFieldNumber = 1,
342 kValueFieldNumber = 2
343 };
344
InternalSerializeMapEntryFuncs345 static uint8_t* InternalSerialize(int field_number, const Key& key,
346 const Value& value, uint8_t* ptr,
347 io::EpsCopyOutputStream* stream) {
348 ptr = stream->EnsureSpace(ptr);
349 ptr = WireFormatLite::WriteTagToArray(
350 field_number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, ptr);
351 ptr = io::CodedOutputStream::WriteVarint32ToArray(GetCachedSize(key, value),
352 ptr);
353
354 ptr = KeyTypeHandler::Write(kKeyFieldNumber, key, ptr, stream);
355 return ValueTypeHandler::Write(kValueFieldNumber, value, ptr, stream);
356 }
357
ByteSizeLongMapEntryFuncs358 static size_t ByteSizeLong(const Key& key, const Value& value) {
359 // Tags for key and value will both be one byte (field numbers 1 and 2).
360 size_t inner_length =
361 2 + KeyTypeHandler::ByteSize(key) + ValueTypeHandler::ByteSize(value);
362 return inner_length + io::CodedOutputStream::VarintSize32(
363 static_cast<uint32_t>(inner_length));
364 }
365
GetCachedSizeMapEntryFuncs366 static int GetCachedSize(const Key& key, const Value& value) {
367 // Tags for key and value will both be one byte (field numbers 1 and 2).
368 return 2 + KeyTypeHandler::GetCachedSize(key) +
369 ValueTypeHandler::GetCachedSize(value);
370 }
371 };
372
373 } // namespace internal
374 } // namespace protobuf
375 } // namespace google
376
377 #endif // GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
378