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/repeated_field.h>
47 #include <google/protobuf/wire_format_lite.h>
48 #include <google/protobuf/wire_format_lite_inl.h>
49 
50 namespace google {
51 namespace protobuf {
52 namespace internal {
53 
Infinity()54 double Infinity() {
55   return std::numeric_limits<double>::infinity();
56 }
NaN()57 double NaN() {
58   return std::numeric_limits<double>::quiet_NaN();
59 }
60 
61 ExplicitlyConstructed< ::std::string> fixed_address_empty_string;
62 GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_);
63 
DeleteEmptyString()64 void DeleteEmptyString() { fixed_address_empty_string.Destruct(); }
65 
InitEmptyString()66 void InitEmptyString() {
67   fixed_address_empty_string.DefaultConstruct();
68   OnShutdown(&DeleteEmptyString);
69 }
70 
StringSpaceUsedExcludingSelfLong(const string & str)71 size_t StringSpaceUsedExcludingSelfLong(const string& str) {
72   const void* start = &str;
73   const void* end = &str + 1;
74   if (start <= str.data() && str.data() < end) {
75     // The string's data is stored inside the string object itself.
76     return 0;
77   } else {
78     return str.capacity();
79   }
80 }
81 
82 
83 
InitProtobufDefaults()84 void InitProtobufDefaults() {
85   GetEmptyString();
86 }
87 
88 template <typename T>
Get(const void * ptr)89 const T& Get(const void* ptr) {
90   return *static_cast<const T*>(ptr);
91 }
92 
93 // PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite.
94 // WireFormatLite has a very inconvenient interface with respect to template
95 // meta-programming. This class wraps the different named functions into
96 // a single Serialize / SerializeToArray interface.
97 template <int type>
98 struct PrimitiveTypeHelper;
99 
100 template <>
101 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> {
102   typedef bool Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper103   static void Serialize(const void* ptr,
104                         ::google::protobuf::io::CodedOutputStream* output) {
105     WireFormatLite::WriteBoolNoTag(Get<bool>(ptr), output);
106   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper107   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
108     return WireFormatLite::WriteBoolNoTagToArray(Get<Type>(ptr), buffer);
109   }
110 };
111 
112 template <>
113 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {
114   typedef int32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper115   static void Serialize(const void* ptr,
116                         ::google::protobuf::io::CodedOutputStream* output) {
117     WireFormatLite::WriteInt32NoTag(Get<int32>(ptr), output);
118   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper119   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
120     return WireFormatLite::WriteInt32NoTagToArray(Get<Type>(ptr), buffer);
121   }
122 };
123 
124 template <>
125 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> {
126   typedef int32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper127   static void Serialize(const void* ptr,
128                         ::google::protobuf::io::CodedOutputStream* output) {
129     WireFormatLite::WriteSInt32NoTag(Get<int32>(ptr), output);
130   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper131   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
132     return WireFormatLite::WriteSInt32NoTagToArray(Get<Type>(ptr), buffer);
133   }
134 };
135 
136 template <>
137 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> {
138   typedef uint32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper139   static void Serialize(const void* ptr,
140                         ::google::protobuf::io::CodedOutputStream* output) {
141     WireFormatLite::WriteUInt32NoTag(Get<uint32>(ptr), output);
142   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper143   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
144     return WireFormatLite::WriteUInt32NoTagToArray(Get<Type>(ptr), buffer);
145   }
146 };
147 template <>
148 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> {
149   typedef int64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper150   static void Serialize(const void* ptr,
151                         ::google::protobuf::io::CodedOutputStream* output) {
152     WireFormatLite::WriteInt64NoTag(Get<int64>(ptr), output);
153   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper154   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
155     return WireFormatLite::WriteInt64NoTagToArray(Get<Type>(ptr), buffer);
156   }
157 };
158 
159 template <>
160 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT64> {
161   typedef int64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper162   static void Serialize(const void* ptr,
163                         ::google::protobuf::io::CodedOutputStream* output) {
164     WireFormatLite::WriteSInt64NoTag(Get<int64>(ptr), output);
165   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper166   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
167     return WireFormatLite::WriteSInt64NoTagToArray(Get<Type>(ptr), buffer);
168   }
169 };
170 template <>
171 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> {
172   typedef uint64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper173   static void Serialize(const void* ptr,
174                         ::google::protobuf::io::CodedOutputStream* output) {
175     WireFormatLite::WriteUInt64NoTag(Get<uint64>(ptr), output);
176   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper177   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
178     return WireFormatLite::WriteUInt64NoTagToArray(Get<Type>(ptr), buffer);
179   }
180 };
181 
182 template <>
183 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
184   typedef uint32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper185   static void Serialize(const void* ptr,
186                         ::google::protobuf::io::CodedOutputStream* output) {
187     WireFormatLite::WriteFixed32NoTag(Get<uint32>(ptr), output);
188   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper189   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
190     return WireFormatLite::WriteFixed32NoTagToArray(Get<Type>(ptr), buffer);
191   }
192 };
193 
194 template <>
195 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
196   typedef uint64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper197   static void Serialize(const void* ptr,
198                         ::google::protobuf::io::CodedOutputStream* output) {
199     WireFormatLite::WriteFixed64NoTag(Get<uint64>(ptr), output);
200   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper201   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
202     return WireFormatLite::WriteFixed64NoTagToArray(Get<Type>(ptr), buffer);
203   }
204 };
205 
206 template <>
207 struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM>
208     : PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {};
209 
210 template <>
211 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32>
212     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
213   typedef int32 Type;
214 };
215 template <>
216 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64>
217     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
218   typedef int64 Type;
219 };
220 template <>
221 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT>
222     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
223   typedef float Type;
224 };
225 template <>
226 struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE>
227     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
228   typedef double Type;
229 };
230 
231 template <>
232 struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {
233   typedef string Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper234   static void Serialize(const void* ptr,
235                         ::google::protobuf::io::CodedOutputStream* output) {
236     const Type& value = *static_cast<const Type*>(ptr);
237     output->WriteVarint32(value.size());
238     output->WriteRawMaybeAliased(value.data(), value.size());
239   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper240   static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
241     const Type& value = *static_cast<const Type*>(ptr);
242     return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer);
243   }
244 };
245 
246 template <>
247 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES>
248     : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
249 
250 
251 // We want to serialize to both CodedOutputStream and directly into byte arrays
252 // without duplicating the code. In fact we might want extra output channels in
253 // the future.
254 template <typename O, int type>
255 struct OutputHelper;
256 
257 template <int type, typename O>
SerializeTo(const void * ptr,O * output)258 void SerializeTo(const void* ptr, O* output) {
259   OutputHelper<O, type>::Serialize(ptr, output);
260 }
261 
262 template <typename O>
WriteTagTo(uint32 tag,O * output)263 void WriteTagTo(uint32 tag, O* output) {
264   SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output);
265 }
266 
267 template <typename O>
WriteLengthTo(uint32 length,O * output)268 void WriteLengthTo(uint32 length, O* output) {
269   SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output);
270 }
271 
272 // Specialization for coded output stream
273 template <int type>
274 struct OutputHelper< ::google::protobuf::io::CodedOutputStream, type> {
Serializegoogle::protobuf::internal::OutputHelper275   static void Serialize(const void* ptr,
276                         ::google::protobuf::io::CodedOutputStream* output) {
277     PrimitiveTypeHelper<type>::Serialize(ptr, output);
278   }
279 };
280 
281 // Specialization for writing into a plain array
282 struct ArrayOutput {
283   uint8* ptr;
284   bool is_deterministic;
285 };
286 
287 template <int type>
288 struct OutputHelper<ArrayOutput, type> {
Serializegoogle::protobuf::internal::OutputHelper289   static void Serialize(const void* ptr, ArrayOutput* output) {
290     output->ptr = PrimitiveTypeHelper<type>::SerializeToArray(ptr, output->ptr);
291   }
292 };
293 
SerializeMessageNoTable(const MessageLite * msg,::google::protobuf::io::CodedOutputStream * output)294 void SerializeMessageNoTable(const MessageLite* msg,
295                              ::google::protobuf::io::CodedOutputStream* output) {
296   msg->SerializeWithCachedSizes(output);
297 }
298 
SerializeMessageNoTable(const MessageLite * msg,ArrayOutput * output)299 void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) {
300   output->ptr = msg->InternalSerializeWithCachedSizesToArray(
301       output->is_deterministic, output->ptr);
302 }
303 
304 // 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)305 void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
306                               const FieldMetadata* field_table, int num_fields,
307                               int32 cached_size,
308                               ::google::protobuf::io::CodedOutputStream* output) {
309   const uint8* base = reinterpret_cast<const uint8*>(&msg);
310   // Try the fast path
311   uint8* ptr = output->GetDirectBufferForNBytesAndAdvance(cached_size);
312   if (ptr) {
313     // We use virtual dispatch to enable dedicated generated code for the
314     // fast path.
315     msg.InternalSerializeWithCachedSizesToArray(
316         output->IsSerializationDeterministic(), ptr);
317     return;
318   }
319   SerializeInternal(base, field_table, num_fields, output);
320 }
321 
322 // 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)323 void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
324                               const FieldMetadata* field_table, int num_fields,
325                               int32 cached_size, ArrayOutput* output) {
326   const uint8* base = reinterpret_cast<const uint8*>(&msg);
327   output->ptr = SerializeInternalToArray(base, field_table, num_fields,
328                                          output->is_deterministic, output->ptr);
329 }
330 
331 // Serializing messages is special as it's not a primitive type and needs an
332 // explicit overload for each output type.
333 template <typename O>
SerializeMessageTo(const MessageLite * msg,const void * table_ptr,O * output)334 void SerializeMessageTo(const MessageLite* msg, const void* table_ptr,
335                         O* output) {
336   const SerializationTable* table =
337       static_cast<const SerializationTable*>(table_ptr);
338   if (!table) {
339     // Proto1
340     WriteLengthTo(msg->GetCachedSize(), output);
341     SerializeMessageNoTable(msg, output);
342     return;
343   }
344   const FieldMetadata* field_table = table->field_table;
345   const uint8* base = reinterpret_cast<const uint8*>(msg);
346   int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
347   WriteLengthTo(cached_size, output);
348   int num_fields = table->num_fields - 1;
349   SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
350                            output);
351 }
352 
353 // Almost the same as above only it doesn't output the length field.
354 template <typename O>
SerializeGroupTo(const MessageLite * msg,const void * table_ptr,O * output)355 void SerializeGroupTo(const MessageLite* msg, const void* table_ptr,
356                       O* output) {
357   const SerializationTable* table =
358       static_cast<const SerializationTable*>(table_ptr);
359   if (!table) {
360     // Proto1
361     SerializeMessageNoTable(msg, output);
362     return;
363   }
364   const FieldMetadata* field_table = table->field_table;
365   const uint8* base = reinterpret_cast<const uint8*>(msg);
366   int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
367   int num_fields = table->num_fields - 1;
368   SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
369                            output);
370 }
371 
372 template <int type>
373 struct SingularFieldHelper {
374   template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper375   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
376     WriteTagTo(md.tag, output);
377     SerializeTo<type>(field, output);
378   }
379 };
380 
381 template <>
382 struct SingularFieldHelper<WireFormatLite::TYPE_STRING> {
383   template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper384   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
385     WriteTagTo(md.tag, output);
386     SerializeTo<WireFormatLite::TYPE_STRING>(&Get<ArenaStringPtr>(field).Get(),
387                                              output);
388   }
389 };
390 
391 template <>
392 struct SingularFieldHelper<WireFormatLite::TYPE_BYTES>
393     : SingularFieldHelper<WireFormatLite::TYPE_STRING> {};
394 
395 template <>
396 struct SingularFieldHelper<WireFormatLite::TYPE_GROUP> {
397   template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper398   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
399     WriteTagTo(md.tag, output);
400     SerializeGroupTo(Get<const MessageLite*>(field),
401                      static_cast<const SerializationTable*>(md.ptr), output);
402     WriteTagTo(md.tag + 1, output);
403   }
404 };
405 
406 template <>
407 struct SingularFieldHelper<WireFormatLite::TYPE_MESSAGE> {
408   template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper409   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
410     WriteTagTo(md.tag, output);
411     SerializeMessageTo(Get<const MessageLite*>(field),
412                        static_cast<const SerializationTable*>(md.ptr), output);
413   }
414 };
415 
416 template <int type>
417 struct RepeatedFieldHelper {
418   template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper419   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
420     typedef typename PrimitiveTypeHelper<type>::Type T;
421     const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
422     for (int i = 0; i < array.size(); i++) {
423       WriteTagTo(md.tag, output);
424       SerializeTo<type>(&array[i], output);
425     }
426   }
427 };
428 
429 // We need to use a helper class to get access to the private members
430 class AccessorHelper {
431  public:
Size(const RepeatedPtrFieldBase & x)432   static int Size(const RepeatedPtrFieldBase& x) { return x.size(); }
Get(const RepeatedPtrFieldBase & x,int idx)433   static void const* Get(const RepeatedPtrFieldBase& x, int idx) {
434     return x.raw_data()[idx];
435   }
436 };
437 
438 template <>
439 struct RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {
440   template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper441   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
442     const internal::RepeatedPtrFieldBase& array =
443         Get<internal::RepeatedPtrFieldBase>(field);
444     for (int i = 0; i < AccessorHelper::Size(array); i++) {
445       WriteTagTo(md.tag, output);
446       SerializeTo<WireFormatLite::TYPE_STRING>(AccessorHelper::Get(array, i),
447                                                output);
448     }
449   }
450 };
451 
452 template <>
453 struct RepeatedFieldHelper<WireFormatLite::TYPE_BYTES>
454     : RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {};
455 
456 template <>
457 struct RepeatedFieldHelper<WireFormatLite::TYPE_GROUP> {
458   template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper459   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
460     const internal::RepeatedPtrFieldBase& array =
461         Get<internal::RepeatedPtrFieldBase>(field);
462     for (int i = 0; i < AccessorHelper::Size(array); i++) {
463       WriteTagTo(md.tag, output);
464       SerializeGroupTo(
465           static_cast<const MessageLite*>(AccessorHelper::Get(array, i)),
466           static_cast<const SerializationTable*>(md.ptr), output);
467       WriteTagTo(md.tag + 1, output);
468     }
469   }
470 };
471 
472 template <>
473 struct RepeatedFieldHelper<WireFormatLite::TYPE_MESSAGE> {
474   template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper475   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
476     const internal::RepeatedPtrFieldBase& array =
477         Get<internal::RepeatedPtrFieldBase>(field);
478     for (int i = 0; i < AccessorHelper::Size(array); i++) {
479       WriteTagTo(md.tag, output);
480       SerializeMessageTo(
481           static_cast<const MessageLite*>(AccessorHelper::Get(array, i)), md.ptr,
482           output);
483     }
484   }
485 };
486 
487 
488 template <int type>
489 struct PackedFieldHelper {
490   template <typename O>
Serializegoogle::protobuf::internal::PackedFieldHelper491   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
492     typedef typename PrimitiveTypeHelper<type>::Type T;
493     const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
494     if (array.empty()) return;
495     WriteTagTo(md.tag, output);
496     int cached_size =
497         Get<int>(static_cast<const uint8*>(field) + sizeof(RepeatedField<T>));
498     WriteLengthTo(cached_size, output);
499     for (int i = 0; i < array.size(); i++) {
500       SerializeTo<type>(&array[i], output);
501     }
502   }
503 };
504 
505 template <>
506 struct PackedFieldHelper<WireFormatLite::TYPE_STRING> {
507   template <typename O>
Serializegoogle::protobuf::internal::PackedFieldHelper508   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
509     GOOGLE_LOG(FATAL) << "Not implemented field number " << md.tag << " with type "
510                << md.type;
511   }
512 };
513 
514 template <>
515 struct PackedFieldHelper<WireFormatLite::TYPE_BYTES>
516     : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
517 template <>
518 struct PackedFieldHelper<WireFormatLite::TYPE_GROUP>
519     : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
520 template <>
521 struct PackedFieldHelper<WireFormatLite::TYPE_MESSAGE>
522     : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
523 
524 template <int type>
525 struct OneOfFieldHelper {
526   template <typename O>
Serializegoogle::protobuf::internal::OneOfFieldHelper527   static void Serialize(const void* field, const FieldMetadata& md, O* output) {
528     SingularFieldHelper<type>::Serialize(field, md, output);
529   }
530 };
531 
532 
SerializeNotImplemented(int field)533 void SerializeNotImplemented(int field) {
534   GOOGLE_LOG(FATAL) << "Not implemented field number " << field;
535 }
536 
537 // When switching to c++11 we should make these constexpr functions
538 #define SERIALIZE_TABLE_OP(type, type_class) \
539   ((type - 1) + static_cast<int>(type_class) * FieldMetadata::kNumTypes)
540 
CalculateType(int type,FieldMetadata::FieldTypeClass type_class)541 int FieldMetadata::CalculateType(int type,
542                                  FieldMetadata::FieldTypeClass type_class) {
543   return SERIALIZE_TABLE_OP(type, type_class);
544 }
545 
546 template <int type>
IsNull(const void * ptr)547 bool IsNull(const void* ptr) {
548   return *static_cast<const typename PrimitiveTypeHelper<type>::Type*>(ptr) ==
549          0;
550 }
551 
552 template <>
IsNull(const void * ptr)553 bool IsNull<WireFormatLite::TYPE_STRING>(const void* ptr) {
554   return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
555 }
556 
557 template <>
IsNull(const void * ptr)558 bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) {
559   return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
560 }
561 
562 template <>
IsNull(const void * ptr)563 bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) {
564   return Get<const MessageLite*>(ptr) == NULL;
565 }
566 
567 template <>
IsNull(const void * ptr)568 bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) {
569   return Get<const MessageLite*>(ptr) == NULL;
570 }
571 
572 
573 #define SERIALIZERS_FOR_TYPE(type)                                            \
574   case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence):                    \
575     if (!IsPresent(base, field_metadata.has_offset)) continue;                \
576     SingularFieldHelper<type>::Serialize(ptr, field_metadata, output);        \
577     break;                                                                    \
578   case SERIALIZE_TABLE_OP(type, FieldMetadata::kNoPresence):                  \
579     if (IsNull<type>(ptr)) continue;                                          \
580     SingularFieldHelper<type>::Serialize(ptr, field_metadata, output);        \
581     break;                                                                    \
582   case SERIALIZE_TABLE_OP(type, FieldMetadata::kRepeated):                    \
583     RepeatedFieldHelper<type>::Serialize(ptr, field_metadata, output);        \
584     break;                                                                    \
585   case SERIALIZE_TABLE_OP(type, FieldMetadata::kPacked):                      \
586     PackedFieldHelper<type>::Serialize(ptr, field_metadata, output);          \
587     break;                                                                    \
588   case SERIALIZE_TABLE_OP(type, FieldMetadata::kOneOf):                       \
589     if (!IsOneofPresent(base, field_metadata.has_offset, field_metadata.tag)) \
590       continue;                                                               \
591     OneOfFieldHelper<type>::Serialize(ptr, field_metadata, output);           \
592     break
593 
SerializeInternal(const uint8 * base,const FieldMetadata * field_metadata_table,int32 num_fields,::google::protobuf::io::CodedOutputStream * output)594 void SerializeInternal(const uint8* base,
595                        const FieldMetadata* field_metadata_table,
596                        int32 num_fields,
597                        ::google::protobuf::io::CodedOutputStream* output) {
598   for (int i = 0; i < num_fields; i++) {
599     const FieldMetadata& field_metadata = field_metadata_table[i];
600     const uint8* ptr = base + field_metadata.offset;
601     switch (field_metadata.type) {
602       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
603       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
604       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
605       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
606       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
607       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
608       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
609       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
610       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
611       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
612       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
613       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
614       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
615       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
616       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
617       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
618       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
619       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
620 
621       // Special cases
622       case FieldMetadata::kSpecial:
623         reinterpret_cast<SpecialSerializer>(
624             const_cast<void*>(field_metadata.ptr))(
625             base, field_metadata.offset, field_metadata.tag,
626             field_metadata.has_offset, output);
627         break;
628       default:
629         // __builtin_unreachable()
630         SerializeNotImplemented(field_metadata.type);
631     }
632   }
633 }
634 
SerializeInternalToArray(const uint8 * base,const FieldMetadata * field_metadata_table,int32 num_fields,bool is_deterministic,uint8 * buffer)635 uint8* SerializeInternalToArray(const uint8* base,
636                                 const FieldMetadata* field_metadata_table,
637                                 int32 num_fields, bool is_deterministic,
638                                 uint8* buffer) {
639   ArrayOutput array_output = {buffer, is_deterministic};
640   ArrayOutput* output = &array_output;
641   for (int i = 0; i < num_fields; i++) {
642     const FieldMetadata& field_metadata = field_metadata_table[i];
643     const uint8* ptr = base + field_metadata.offset;
644     switch (field_metadata.type) {
645       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
646       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
647       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
648       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
649       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
650       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
651       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
652       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
653       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
654       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
655       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
656       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
657       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
658       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
659       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
660       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
661       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
662       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
663       // Special cases
664       case FieldMetadata::kSpecial: {
665         io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX);
666         io::CodedOutputStream output(&array_stream);
667         output.SetSerializationDeterministic(is_deterministic);
668         reinterpret_cast<SpecialSerializer>(
669             const_cast<void*>(field_metadata.ptr))(
670             base, field_metadata.offset, field_metadata.tag,
671             field_metadata.has_offset, &output);
672         array_output.ptr += output.ByteCount();
673       } break;
674       default:
675         // __builtin_unreachable()
676         SerializeNotImplemented(field_metadata.type);
677     }
678   }
679   return array_output.ptr;
680 }
681 #undef SERIALIZERS_FOR_TYPE
682 
ExtensionSerializer(const uint8 * ptr,uint32 offset,uint32 tag,uint32 has_offset,::google::protobuf::io::CodedOutputStream * output)683 void ExtensionSerializer(const uint8* ptr, uint32 offset, uint32 tag,
684                          uint32 has_offset,
685                          ::google::protobuf::io::CodedOutputStream* output) {
686   reinterpret_cast<const ExtensionSet*>(ptr + offset)
687       ->SerializeWithCachedSizes(tag, has_offset, output);
688 }
689 
UnknownFieldSerializerLite(const uint8 * ptr,uint32 offset,uint32 tag,uint32 has_offset,::google::protobuf::io::CodedOutputStream * output)690 void UnknownFieldSerializerLite(const uint8* ptr, uint32 offset, uint32 tag,
691                                 uint32 has_offset,
692                                 ::google::protobuf::io::CodedOutputStream* output) {
693   output->WriteString(
694       reinterpret_cast<const InternalMetadataWithArenaLite*>(ptr + offset)
695           ->unknown_fields());
696 }
697 
698 }  // namespace internal
699 }  // namespace protobuf
700 }  // namespace google
701