• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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