1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/generated_message_util.h>
36 
37 #include <limits>
38 #include <vector>
39 
40 #include <google/protobuf/io/coded_stream_inl.h>
41 #include <google/protobuf/io/coded_stream.h>
42 #include <google/protobuf/arenastring.h>
43 #include <google/protobuf/extension_set.h>
44 #include <google/protobuf/message_lite.h>
45 #include <google/protobuf/metadata_lite.h>
46 #include <google/protobuf/stubs/port.h>
47 #include <google/protobuf/repeated_field.h>
48 #include <google/protobuf/wire_format_lite.h>
49 #include <google/protobuf/wire_format_lite_inl.h>
50 
51 namespace google {
52 
53 namespace protobuf {
54 namespace internal {
55 
56 
Infinity()57 double Infinity() {
58   return std::numeric_limits<double>::infinity();
59 }
NaN()60 double NaN() {
61   return std::numeric_limits<double>::quiet_NaN();
62 }
63 
64 ExplicitlyConstructed< ::std::string> fixed_address_empty_string;
65 GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_);
66 
DeleteEmptyString()67 void DeleteEmptyString() { fixed_address_empty_string.Destruct(); }
68 
InitEmptyString()69 void InitEmptyString() {
70   fixed_address_empty_string.DefaultConstruct();
71   OnShutdown(&DeleteEmptyString);
72 }
73 
StringSpaceUsedExcludingSelfLong(const string & str)74 size_t StringSpaceUsedExcludingSelfLong(const string& str) {
75   const void* start = &str;
76   const void* end = &str + 1;
77   if (start <= str.data() && str.data() < end) {
78     // The string's data is stored inside the string object itself.
79     return 0;
80   } else {
81     return str.capacity();
82   }
83 }
84 
85 
86 
InitProtobufDefaults()87 void InitProtobufDefaults() {
88   GetEmptyString();
89 }
90 
91 template <typename T>
Get(const void * ptr)92 const T& Get(const void* ptr) {
93   return *static_cast<const T*>(ptr);
94 }
95 
96 // PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite.
97 // WireFormatLite has a very inconvenient interface with respect to template
98 // meta-programming. This class wraps the different named functions into
99 // a single Serialize / SerializeToArray interface.
100 template <int type>
101 struct PrimitiveTypeHelper;
102 
103 template <>
104 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> {
105   typedef bool Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper106   static void Serialize(const void* ptr,
107                         ::google::protobuf::io::CodedOutputStream* output) {
108     WireFormatLite::WriteBoolNoTag(Get<bool>(ptr), output);
109   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper110   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
111     return WireFormatLite::WriteBoolNoTagToArray(Get<Type>(ptr), buffer);
112   }
113 };
114 
115 template <>
116 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {
117   typedef int32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper118   static void Serialize(const void* ptr,
119                         ::google::protobuf::io::CodedOutputStream* output) {
120     WireFormatLite::WriteInt32NoTag(Get<int32>(ptr), output);
121   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper122   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
123     return WireFormatLite::WriteInt32NoTagToArray(Get<Type>(ptr), buffer);
124   }
125 };
126 
127 template <>
128 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> {
129   typedef int32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper130   static void Serialize(const void* ptr,
131                         ::google::protobuf::io::CodedOutputStream* output) {
132     WireFormatLite::WriteSInt32NoTag(Get<int32>(ptr), output);
133   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper134   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
135     return WireFormatLite::WriteSInt32NoTagToArray(Get<Type>(ptr), buffer);
136   }
137 };
138 
139 template <>
140 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> {
141   typedef uint32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper142   static void Serialize(const void* ptr,
143                         ::google::protobuf::io::CodedOutputStream* output) {
144     WireFormatLite::WriteUInt32NoTag(Get<uint32>(ptr), output);
145   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper146   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
147     return WireFormatLite::WriteUInt32NoTagToArray(Get<Type>(ptr), buffer);
148   }
149 };
150 template <>
151 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> {
152   typedef int64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper153   static void Serialize(const void* ptr,
154                         ::google::protobuf::io::CodedOutputStream* output) {
155     WireFormatLite::WriteInt64NoTag(Get<int64>(ptr), output);
156   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper157   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
158     return WireFormatLite::WriteInt64NoTagToArray(Get<Type>(ptr), buffer);
159   }
160 };
161 
162 template <>
163 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT64> {
164   typedef int64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper165   static void Serialize(const void* ptr,
166                         ::google::protobuf::io::CodedOutputStream* output) {
167     WireFormatLite::WriteSInt64NoTag(Get<int64>(ptr), output);
168   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper169   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
170     return WireFormatLite::WriteSInt64NoTagToArray(Get<Type>(ptr), buffer);
171   }
172 };
173 template <>
174 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> {
175   typedef uint64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper176   static void Serialize(const void* ptr,
177                         ::google::protobuf::io::CodedOutputStream* output) {
178     WireFormatLite::WriteUInt64NoTag(Get<uint64>(ptr), output);
179   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper180   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
181     return WireFormatLite::WriteUInt64NoTagToArray(Get<Type>(ptr), buffer);
182   }
183 };
184 
185 template <>
186 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
187   typedef uint32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper188   static void Serialize(const void* ptr,
189                         ::google::protobuf::io::CodedOutputStream* output) {
190     WireFormatLite::WriteFixed32NoTag(Get<uint32>(ptr), output);
191   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper192   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
193     return WireFormatLite::WriteFixed32NoTagToArray(Get<Type>(ptr), buffer);
194   }
195 };
196 
197 template <>
198 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
199   typedef uint64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper200   static void Serialize(const void* ptr,
201                         ::google::protobuf::io::CodedOutputStream* output) {
202     WireFormatLite::WriteFixed64NoTag(Get<uint64>(ptr), output);
203   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper204   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
205     return WireFormatLite::WriteFixed64NoTagToArray(Get<Type>(ptr), buffer);
206   }
207 };
208 
209 template <>
210 struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM>
211     : PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {};
212 
213 template <>
214 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32>
215     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
216   typedef int32 Type;
217 };
218 template <>
219 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64>
220     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
221   typedef int64 Type;
222 };
223 template <>
224 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT>
225     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
226   typedef float Type;
227 };
228 template <>
229 struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE>
230     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
231   typedef double Type;
232 };
233 
234 template <>
235 struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {
236   typedef string Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper237   static void Serialize(const void* ptr,
238                         ::google::protobuf::io::CodedOutputStream* output) {
239     const Type& value = *static_cast<const Type*>(ptr);
240     output->WriteVarint32(value.size());
241     output->WriteRawMaybeAliased(value.data(), value.size());
242   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper243   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
244     const Type& value = *static_cast<const Type*>(ptr);
245     return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer);
246   }
247 };
248 
249 template <>
250 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES>
251     : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
252 
253 
254 // We want to serialize to both CodedOutputStream and directly into byte arrays
255 // without duplicating the code. In fact we might want extra output channels in
256 // the future.
257 template <typename O, int type>
258 struct OutputHelper;
259 
260 template <int type, typename O>
SerializeTo(const void * ptr,O * output)261 void SerializeTo(const void* ptr, O* output) {
262   OutputHelper<O, type>::Serialize(ptr, output);
263 }
264 
265 template <typename O>
WriteTagTo(uint32 tag,O * output)266 void WriteTagTo(uint32 tag, O* output) {
267   SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output);
268 }
269 
270 template <typename O>
WriteLengthTo(uint32 length,O * output)271 void WriteLengthTo(uint32 length, O* output) {
272   SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output);
273 }
274 
275 // Specialization for coded output stream
276 template <int type>
277 struct OutputHelper< ::google::protobuf::io::CodedOutputStream, type> {
Serializegoogle::protobuf::internal::OutputHelper278   static void Serialize(const void* ptr,
279                         ::google::protobuf::io::CodedOutputStream* output) {
280     PrimitiveTypeHelper<type>::Serialize(ptr, output);
281   }
282 };
283 
284 // Specialization for writing into a plain array
285 struct ArrayOutput {
286   uint8* ptr;
287   bool is_deterministic;
288 };
289 
290 template <int type>
291 struct OutputHelper<ArrayOutput, type> {
Serializegoogle::protobuf::internal::OutputHelper292   static void Serialize(const void* ptr, ArrayOutput* output) {
293     output->ptr = PrimitiveTypeHelper<type>::SerializeToArray(ptr, output->ptr);
294   }
295 };
296 
SerializeMessageNoTable(const MessageLite * msg,::google::protobuf::io::CodedOutputStream * output)297 void SerializeMessageNoTable(const MessageLite* msg,
298                              ::google::protobuf::io::CodedOutputStream* output) {
299   msg->SerializeWithCachedSizes(output);
300 }
301 
SerializeMessageNoTable(const MessageLite * msg,ArrayOutput * output)302 void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) {
303   output->ptr = msg->InternalSerializeWithCachedSizesToArray(
304       output->is_deterministic, output->ptr);
305 }
306 
307 // Helper to branch to fast path if possible
SerializeMessageDispatch(const::google::protobuf::MessageLite & msg,const FieldMetadata * field_table,int num_fields,int32 cached_size,::google::protobuf::io::CodedOutputStream * output)308 void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
309                               const FieldMetadata* field_table, int num_fields,
310                               int32 cached_size,
311                               ::google::protobuf::io::CodedOutputStream* output) {
312   const uint8* base = reinterpret_cast<const uint8*>(&msg);
313   // Try the fast path
314   uint8* ptr = output->GetDirectBufferForNBytesAndAdvance(cached_size);
315   if (ptr) {
316     // We use virtual dispatch to enable dedicated generated code for the
317     // fast path.
318     msg.InternalSerializeWithCachedSizesToArray(
319         output->IsSerializationDeterministic(), ptr);
320     return;
321   }
322   SerializeInternal(base, field_table, num_fields, output);
323 }
324 
325 // Helper to branch to fast path if possible
SerializeMessageDispatch(const::google::protobuf::MessageLite & msg,const FieldMetadata * field_table,int num_fields,int32 cached_size,ArrayOutput * output)326 void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
327                               const FieldMetadata* field_table, int num_fields,
328                               int32 cached_size, ArrayOutput* output) {
329   const uint8* base = reinterpret_cast<const uint8*>(&msg);
330   output->ptr = SerializeInternalToArray(base, field_table, num_fields,
331                                          output->is_deterministic, output->ptr);
332 }
333 
334 // Serializing messages is special as it's not a primitive type and needs an
335 // explicit overload for each output type.
336 template <typename O>
SerializeMessageTo(const MessageLite * msg,const void * table_ptr,O * output)337 void SerializeMessageTo(const MessageLite* msg, const void* table_ptr,
338                         O* output) {
339   const SerializationTable* table =
340       static_cast<const SerializationTable*>(table_ptr);
341   if (!table) {
342     // Proto1
343     WriteLengthTo(msg->GetCachedSize(), output);
344     SerializeMessageNoTable(msg, output);
345     return;
346   }
347   const FieldMetadata* field_table = table->field_table;
348   const uint8* base = reinterpret_cast<const uint8*>(msg);
349   int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
350   WriteLengthTo(cached_size, output);
351   int num_fields = table->num_fields - 1;
352   SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
353                            output);
354 }
355 
356 // Almost the same as above only it doesn't output the length field.
357 template <typename O>
SerializeGroupTo(const MessageLite * msg,const void * table_ptr,O * output)358 void SerializeGroupTo(const MessageLite* msg, const void* table_ptr,
359                       O* output) {
360   const SerializationTable* table =
361       static_cast<const SerializationTable*>(table_ptr);
362   if (!table) {
363     // Proto1
364     SerializeMessageNoTable(msg, output);
365     return;
366   }
367   const FieldMetadata* field_table = table->field_table;
368   const uint8* base = reinterpret_cast<const uint8*>(msg);
369   int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
370   int num_fields = table->num_fields - 1;
371   SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
372                            output);
373 }
374 
375 template <int type>
376 struct SingularFieldHelper {
377   template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper378   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
379     WriteTagTo(md.tag, output);
380     SerializeTo<type>(field, output);
381   }
382 };
383 
384 template <>
385 struct SingularFieldHelper<WireFormatLite::TYPE_STRING> {
386   template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper387   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
388     WriteTagTo(md.tag, output);
389     SerializeTo<WireFormatLite::TYPE_STRING>(&Get<ArenaStringPtr>(field).Get(),
390                                              output);
391   }
392 };
393 
394 template <>
395 struct SingularFieldHelper<WireFormatLite::TYPE_BYTES>
396     : SingularFieldHelper<WireFormatLite::TYPE_STRING> {};
397 
398 template <>
399 struct SingularFieldHelper<WireFormatLite::TYPE_GROUP> {
400   template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper401   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
402     WriteTagTo(md.tag, output);
403     SerializeGroupTo(Get<const MessageLite*>(field),
404                      static_cast<const SerializationTable*>(md.ptr), output);
405     WriteTagTo(md.tag + 1, output);
406   }
407 };
408 
409 template <>
410 struct SingularFieldHelper<WireFormatLite::TYPE_MESSAGE> {
411   template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper412   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
413     WriteTagTo(md.tag, output);
414     SerializeMessageTo(Get<const MessageLite*>(field),
415                        static_cast<const SerializationTable*>(md.ptr), output);
416   }
417 };
418 
419 template <int type>
420 struct RepeatedFieldHelper {
421   template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper422   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
423     typedef typename PrimitiveTypeHelper<type>::Type T;
424     const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
425     for (int i = 0; i < array.size(); i++) {
426       WriteTagTo(md.tag, output);
427       SerializeTo<type>(&array[i], output);
428     }
429   }
430 };
431 
432 // We need to use a helper class to get access to the private members
433 class AccessorHelper {
434  public:
Size(const RepeatedPtrFieldBase & x)435   static int Size(const RepeatedPtrFieldBase& x) { return x.size(); }
Get(const RepeatedPtrFieldBase & x,int idx)436   static void const* Get(const RepeatedPtrFieldBase& x, int idx) {
437     return x.raw_data()[idx];
438   }
439 };
440 
441 template <>
442 struct RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {
443   template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper444   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
445     const internal::RepeatedPtrFieldBase& array =
446         Get<internal::RepeatedPtrFieldBase>(field);
447     for (int i = 0; i < AccessorHelper::Size(array); i++) {
448       WriteTagTo(md.tag, output);
449       SerializeTo<WireFormatLite::TYPE_STRING>(AccessorHelper::Get(array, i),
450                                                output);
451     }
452   }
453 };
454 
455 template <>
456 struct RepeatedFieldHelper<WireFormatLite::TYPE_BYTES>
457     : RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {};
458 
459 template <>
460 struct RepeatedFieldHelper<WireFormatLite::TYPE_GROUP> {
461   template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper462   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
463     const internal::RepeatedPtrFieldBase& array =
464         Get<internal::RepeatedPtrFieldBase>(field);
465     for (int i = 0; i < AccessorHelper::Size(array); i++) {
466       WriteTagTo(md.tag, output);
467       SerializeGroupTo(
468           static_cast<const MessageLite*>(AccessorHelper::Get(array, i)),
469           static_cast<const SerializationTable*>(md.ptr), output);
470       WriteTagTo(md.tag + 1, output);
471     }
472   }
473 };
474 
475 template <>
476 struct RepeatedFieldHelper<WireFormatLite::TYPE_MESSAGE> {
477   template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper478   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
479     const internal::RepeatedPtrFieldBase& array =
480         Get<internal::RepeatedPtrFieldBase>(field);
481     for (int i = 0; i < AccessorHelper::Size(array); i++) {
482       WriteTagTo(md.tag, output);
483       SerializeMessageTo(
484           static_cast<const MessageLite*>(AccessorHelper::Get(array, i)), md.ptr,
485           output);
486     }
487   }
488 };
489 
490 
491 template <int type>
492 struct PackedFieldHelper {
493   template <typename O>
Serializegoogle::protobuf::internal::PackedFieldHelper494   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
495     typedef typename PrimitiveTypeHelper<type>::Type T;
496     const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
497     if (array.empty()) return;
498     WriteTagTo(md.tag, output);
499     int cached_size =
500         Get<int>(static_cast<const uint8*>(field) + sizeof(RepeatedField<T>));
501     WriteLengthTo(cached_size, output);
502     for (int i = 0; i < array.size(); i++) {
503       SerializeTo<type>(&array[i], output);
504     }
505   }
506 };
507 
508 template <>
509 struct PackedFieldHelper<WireFormatLite::TYPE_STRING> {
510   template <typename O>
Serializegoogle::protobuf::internal::PackedFieldHelper511   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
512     GOOGLE_LOG(FATAL) << "Not implemented field number " << md.tag << " with type "
513                << md.type;
514   }
515 };
516 
517 template <>
518 struct PackedFieldHelper<WireFormatLite::TYPE_BYTES>
519     : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
520 template <>
521 struct PackedFieldHelper<WireFormatLite::TYPE_GROUP>
522     : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
523 template <>
524 struct PackedFieldHelper<WireFormatLite::TYPE_MESSAGE>
525     : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
526 
527 template <int type>
528 struct OneOfFieldHelper {
529   template <typename O>
Serializegoogle::protobuf::internal::OneOfFieldHelper530   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
531     SingularFieldHelper<type>::Serialize(field, md, output);
532   }
533 };
534 
535 
SerializeNotImplemented(int field)536 void SerializeNotImplemented(int field) {
537   GOOGLE_LOG(FATAL) << "Not implemented field number " << field;
538 }
539 
540 // When switching to c++11 we should make these constexpr functions
541 #define SERIALIZE_TABLE_OP(type, type_class) \
542   ((type - 1) + static_cast<int>(type_class) * FieldMetadata::kNumTypes)
543 
CalculateType(int type,FieldMetadata::FieldTypeClass type_class)544 int FieldMetadata::CalculateType(int type,
545                                  FieldMetadata::FieldTypeClass type_class) {
546   return SERIALIZE_TABLE_OP(type, type_class);
547 }
548 
549 template <int type>
IsNull(const void * ptr)550 bool IsNull(const void* ptr) {
551   return *static_cast<const typename PrimitiveTypeHelper<type>::Type*>(ptr) ==
552          0;
553 }
554 
555 template <>
IsNull(const void * ptr)556 bool IsNull<WireFormatLite::TYPE_STRING>(const void* ptr) {
557   return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
558 }
559 
560 template <>
IsNull(const void * ptr)561 bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) {
562   return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
563 }
564 
565 template <>
IsNull(const void * ptr)566 bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) {
567   return Get<const MessageLite*>(ptr) == NULL;
568 }
569 
570 template <>
IsNull(const void * ptr)571 bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) {
572   return Get<const MessageLite*>(ptr) == NULL;
573 }
574 
575 
576 #define SERIALIZERS_FOR_TYPE(type)                                            \
577   case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence):                    \
578     if (!IsPresent(base, field_metadata.has_offset)) continue;                \
579     SingularFieldHelper<type>::Serialize(ptr, field_metadata, output);        \
580     break;                                                                    \
581   case SERIALIZE_TABLE_OP(type, FieldMetadata::kNoPresence):                  \
582     if (IsNull<type>(ptr)) continue;                                          \
583     SingularFieldHelper<type>::Serialize(ptr, field_metadata, output);        \
584     break;                                                                    \
585   case SERIALIZE_TABLE_OP(type, FieldMetadata::kRepeated):                    \
586     RepeatedFieldHelper<type>::Serialize(ptr, field_metadata, output);        \
587     break;                                                                    \
588   case SERIALIZE_TABLE_OP(type, FieldMetadata::kPacked):                      \
589     PackedFieldHelper<type>::Serialize(ptr, field_metadata, output);          \
590     break;                                                                    \
591   case SERIALIZE_TABLE_OP(type, FieldMetadata::kOneOf):                       \
592     if (!IsOneofPresent(base, field_metadata.has_offset, field_metadata.tag)) \
593       continue;                                                               \
594     OneOfFieldHelper<type>::Serialize(ptr, field_metadata, output);           \
595     break
596 
SerializeInternal(const uint8 * base,const FieldMetadata * field_metadata_table,int32 num_fields,::google::protobuf::io::CodedOutputStream * output)597 void SerializeInternal(const uint8* base,
598                        const FieldMetadata* field_metadata_table,
599                        int32 num_fields,
600                        ::google::protobuf::io::CodedOutputStream* output) {
601   for (int i = 0; i < num_fields; i++) {
602     const FieldMetadata& field_metadata = field_metadata_table[i];
603     const uint8* ptr = base + field_metadata.offset;
604     switch (field_metadata.type) {
605       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
606       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
607       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
608       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
609       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
610       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
611       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
612       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
613       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
614       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
615       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
616       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
617       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
618       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
619       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
620       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
621       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
622       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
623 
624       // Special cases
625       case FieldMetadata::kSpecial:
626         reinterpret_cast<SpecialSerializer>(
627             const_cast<void*>(field_metadata.ptr))(
628             base, field_metadata.offset, field_metadata.tag,
629             field_metadata.has_offset, output);
630         break;
631       default:
632         // __builtin_unreachable()
633         SerializeNotImplemented(field_metadata.type);
634     }
635   }
636 }
637 
SerializeInternalToArray(const uint8 * base,const FieldMetadata * field_metadata_table,int32 num_fields,bool is_deterministic,uint8 * buffer)638 uint8* SerializeInternalToArray(const uint8* base,
639                                 const FieldMetadata* field_metadata_table,
640                                 int32 num_fields, bool is_deterministic,
641                                 uint8* buffer) {
642   ArrayOutput array_output = {buffer, is_deterministic};
643   ArrayOutput* output = &array_output;
644   for (int i = 0; i < num_fields; i++) {
645     const FieldMetadata& field_metadata = field_metadata_table[i];
646     const uint8* ptr = base + field_metadata.offset;
647     switch (field_metadata.type) {
648       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
649       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
650       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
651       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
652       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
653       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
654       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
655       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
656       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
657       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
658       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
659       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
660       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
661       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
662       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
663       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
664       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
665       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
666       // Special cases
667       case FieldMetadata::kSpecial: {
668         io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX);
669         io::CodedOutputStream output(&array_stream);
670         output.SetSerializationDeterministic(is_deterministic);
671         reinterpret_cast<SpecialSerializer>(
672             const_cast<void*>(field_metadata.ptr))(
673             base, field_metadata.offset, field_metadata.tag,
674             field_metadata.has_offset, &output);
675         array_output.ptr += output.ByteCount();
676       } break;
677       default:
678         // __builtin_unreachable()
679         SerializeNotImplemented(field_metadata.type);
680     }
681   }
682   return array_output.ptr;
683 }
684 #undef SERIALIZERS_FOR_TYPE
685 
ExtensionSerializer(const uint8 * ptr,uint32 offset,uint32 tag,uint32 has_offset,::google::protobuf::io::CodedOutputStream * output)686 void ExtensionSerializer(const uint8* ptr, uint32 offset, uint32 tag,
687                          uint32 has_offset,
688                          ::google::protobuf::io::CodedOutputStream* output) {
689   reinterpret_cast<const ExtensionSet*>(ptr + offset)
690       ->SerializeWithCachedSizes(tag, has_offset, output);
691 }
692 
UnknownFieldSerializerLite(const uint8 * ptr,uint32 offset,uint32 tag,uint32 has_offset,::google::protobuf::io::CodedOutputStream * output)693 void UnknownFieldSerializerLite(const uint8* ptr, uint32 offset, uint32 tag,
694                                 uint32 has_offset,
695                                 ::google::protobuf::io::CodedOutputStream* output) {
696   output->WriteString(
697       reinterpret_cast<const InternalMetadataWithArenaLite*>(ptr + offset)
698           ->unknown_fields());
699 }
700 
DuplicateIfNonNullInternal(MessageLite * message,Arena * arena)701 MessageLite* DuplicateIfNonNullInternal(MessageLite* message, Arena* arena) {
702   if (message) {
703     MessageLite* ret = message->New(arena);
704     ret->CheckTypeAndMergeFrom(*message);
705     return ret;
706   } else {
707     return NULL;
708   }
709 }
710 
711 // Returns a message owned by this Arena.  This may require Own()ing or
712 // duplicating the message.
GetOwnedMessageInternal(Arena * message_arena,MessageLite * submessage,Arena * submessage_arena)713 MessageLite* GetOwnedMessageInternal(Arena* message_arena,
714                                      MessageLite* submessage,
715                                      Arena* submessage_arena) {
716   GOOGLE_DCHECK(submessage->GetArena() == submessage_arena);
717   GOOGLE_DCHECK(message_arena != submessage_arena);
718   if (message_arena != NULL && submessage_arena == NULL) {
719     message_arena->Own(submessage);
720     return submessage;
721   } else {
722     MessageLite* ret = submessage->New(message_arena);
723     ret->CheckTypeAndMergeFrom(*submessage);
724     return ret;
725   }
726 }
727 
728 }  // namespace internal
729 }  // namespace protobuf
730 }  // namespace google
731