• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Contains methods defined in extension_set.h which cannot be part of the
36 // lite library because they use descriptors or reflection.
37 
38 #include <google/protobuf/extension_set.h>
39 
40 #include <google/protobuf/stubs/casts.h>
41 #include <google/protobuf/descriptor.pb.h>
42 #include <google/protobuf/extension_set_inl.h>
43 #include <google/protobuf/parse_context.h>
44 #include <google/protobuf/io/coded_stream.h>
45 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
46 #include <google/protobuf/descriptor.h>
47 #include <google/protobuf/message.h>
48 #include <google/protobuf/repeated_field.h>
49 #include <google/protobuf/unknown_field_set.h>
50 #include <google/protobuf/wire_format.h>
51 #include <google/protobuf/wire_format_lite.h>
52 
53 
54 #include <google/protobuf/port_def.inc>
55 
56 namespace google {
57 namespace protobuf {
58 namespace internal {
59 
60 // A FieldSkipper used to store unknown MessageSet fields into UnknownFieldSet.
61 class MessageSetFieldSkipper : public UnknownFieldSetFieldSkipper {
62  public:
MessageSetFieldSkipper(UnknownFieldSet * unknown_fields)63   explicit MessageSetFieldSkipper(UnknownFieldSet* unknown_fields)
64       : UnknownFieldSetFieldSkipper(unknown_fields) {}
~MessageSetFieldSkipper()65   virtual ~MessageSetFieldSkipper() {}
66 
67   virtual bool SkipMessageSetField(io::CodedInputStream* input,
68                                    int field_number);
69 };
SkipMessageSetField(io::CodedInputStream * input,int field_number)70 bool MessageSetFieldSkipper::SkipMessageSetField(io::CodedInputStream* input,
71                                                  int field_number) {
72   uint32 length;
73   if (!input->ReadVarint32(&length)) return false;
74   if (unknown_fields_ == NULL) {
75     return input->Skip(length);
76   } else {
77     return input->ReadString(unknown_fields_->AddLengthDelimited(field_number),
78                              length);
79   }
80 }
81 
82 
83 // Implementation of ExtensionFinder which finds extensions in a given
84 // DescriptorPool, using the given MessageFactory to construct sub-objects.
85 // This class is implemented in extension_set_heavy.cc.
86 class DescriptorPoolExtensionFinder : public ExtensionFinder {
87  public:
DescriptorPoolExtensionFinder(const DescriptorPool * pool,MessageFactory * factory,const Descriptor * containing_type)88   DescriptorPoolExtensionFinder(const DescriptorPool* pool,
89                                 MessageFactory* factory,
90                                 const Descriptor* containing_type)
91       : pool_(pool), factory_(factory), containing_type_(containing_type) {}
~DescriptorPoolExtensionFinder()92   ~DescriptorPoolExtensionFinder() override {}
93 
94   bool Find(int number, ExtensionInfo* output) override;
95 
96  private:
97   const DescriptorPool* pool_;
98   MessageFactory* factory_;
99   const Descriptor* containing_type_;
100 };
101 
AppendToList(const Descriptor * containing_type,const DescriptorPool * pool,std::vector<const FieldDescriptor * > * output) const102 void ExtensionSet::AppendToList(
103     const Descriptor* containing_type, const DescriptorPool* pool,
104     std::vector<const FieldDescriptor*>* output) const {
105   ForEach([containing_type, pool, &output](int number, const Extension& ext) {
106     bool has = false;
107     if (ext.is_repeated) {
108       has = ext.GetSize() > 0;
109     } else {
110       has = !ext.is_cleared;
111     }
112 
113     if (has) {
114       // TODO(kenton): Looking up each field by number is somewhat unfortunate.
115       //   Is there a better way?  The problem is that descriptors are lazily-
116       //   initialized, so they might not even be constructed until
117       //   AppendToList() is called.
118 
119       if (ext.descriptor == NULL) {
120         output->push_back(pool->FindExtensionByNumber(containing_type, number));
121       } else {
122         output->push_back(ext.descriptor);
123       }
124     }
125   });
126 }
127 
real_type(FieldType type)128 inline FieldDescriptor::Type real_type(FieldType type) {
129   GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
130   return static_cast<FieldDescriptor::Type>(type);
131 }
132 
cpp_type(FieldType type)133 inline FieldDescriptor::CppType cpp_type(FieldType type) {
134   return FieldDescriptor::TypeToCppType(
135       static_cast<FieldDescriptor::Type>(type));
136 }
137 
field_type(FieldType type)138 inline WireFormatLite::FieldType field_type(FieldType type) {
139   GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
140   return static_cast<WireFormatLite::FieldType>(type);
141 }
142 
143 #define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE)                         \
144   GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED  \
145                                     : FieldDescriptor::LABEL_OPTIONAL, \
146             FieldDescriptor::LABEL_##LABEL);                           \
147   GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
148 
GetMessage(int number,const Descriptor * message_type,MessageFactory * factory) const149 const MessageLite& ExtensionSet::GetMessage(int number,
150                                             const Descriptor* message_type,
151                                             MessageFactory* factory) const {
152   const Extension* extension = FindOrNull(number);
153   if (extension == NULL || extension->is_cleared) {
154     // Not present.  Return the default value.
155     return *factory->GetPrototype(message_type);
156   } else {
157     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
158     if (extension->is_lazy) {
159       return extension->lazymessage_value->GetMessage(
160           *factory->GetPrototype(message_type));
161     } else {
162       return *extension->message_value;
163     }
164   }
165 }
166 
MutableMessage(const FieldDescriptor * descriptor,MessageFactory * factory)167 MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
168                                           MessageFactory* factory) {
169   Extension* extension;
170   if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
171     extension->type = descriptor->type();
172     GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
173     extension->is_repeated = false;
174     extension->is_packed = false;
175     const MessageLite* prototype =
176         factory->GetPrototype(descriptor->message_type());
177     extension->is_lazy = false;
178     extension->message_value = prototype->New(arena_);
179     extension->is_cleared = false;
180     return extension->message_value;
181   } else {
182     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
183     extension->is_cleared = false;
184     if (extension->is_lazy) {
185       return extension->lazymessage_value->MutableMessage(
186           *factory->GetPrototype(descriptor->message_type()));
187     } else {
188       return extension->message_value;
189     }
190   }
191 }
192 
ReleaseMessage(const FieldDescriptor * descriptor,MessageFactory * factory)193 MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
194                                           MessageFactory* factory) {
195   Extension* extension = FindOrNull(descriptor->number());
196   if (extension == NULL) {
197     // Not present.  Return NULL.
198     return NULL;
199   } else {
200     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
201     MessageLite* ret = NULL;
202     if (extension->is_lazy) {
203       ret = extension->lazymessage_value->ReleaseMessage(
204           *factory->GetPrototype(descriptor->message_type()));
205       if (arena_ == NULL) {
206         delete extension->lazymessage_value;
207       }
208     } else {
209       if (arena_ != NULL) {
210         ret = extension->message_value->New();
211         ret->CheckTypeAndMergeFrom(*extension->message_value);
212       } else {
213         ret = extension->message_value;
214       }
215     }
216     Erase(descriptor->number());
217     return ret;
218   }
219 }
220 
UnsafeArenaReleaseMessage(const FieldDescriptor * descriptor,MessageFactory * factory)221 MessageLite* ExtensionSet::UnsafeArenaReleaseMessage(
222     const FieldDescriptor* descriptor, MessageFactory* factory) {
223   Extension* extension = FindOrNull(descriptor->number());
224   if (extension == NULL) {
225     // Not present.  Return NULL.
226     return NULL;
227   } else {
228     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
229     MessageLite* ret = NULL;
230     if (extension->is_lazy) {
231       ret = extension->lazymessage_value->UnsafeArenaReleaseMessage(
232           *factory->GetPrototype(descriptor->message_type()));
233       if (arena_ == NULL) {
234         delete extension->lazymessage_value;
235       }
236     } else {
237       ret = extension->message_value;
238     }
239     Erase(descriptor->number());
240     return ret;
241   }
242 }
243 
MaybeNewRepeatedExtension(const FieldDescriptor * descriptor)244 ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(
245     const FieldDescriptor* descriptor) {
246   Extension* extension;
247   if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
248     extension->type = descriptor->type();
249     GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
250     extension->is_repeated = true;
251     extension->repeated_message_value =
252         Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
253   } else {
254     GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
255   }
256   return extension;
257 }
258 
AddMessage(const FieldDescriptor * descriptor,MessageFactory * factory)259 MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
260                                       MessageFactory* factory) {
261   Extension* extension = MaybeNewRepeatedExtension(descriptor);
262 
263   // RepeatedPtrField<Message> does not know how to Add() since it cannot
264   // allocate an abstract object, so we have to be tricky.
265   MessageLite* result =
266       reinterpret_cast<internal::RepeatedPtrFieldBase*>(
267           extension->repeated_message_value)
268           ->AddFromCleared<GenericTypeHandler<MessageLite> >();
269   if (result == NULL) {
270     const MessageLite* prototype;
271     if (extension->repeated_message_value->size() == 0) {
272       prototype = factory->GetPrototype(descriptor->message_type());
273       GOOGLE_CHECK(prototype != NULL);
274     } else {
275       prototype = &extension->repeated_message_value->Get(0);
276     }
277     result = prototype->New(arena_);
278     extension->repeated_message_value->AddAllocated(result);
279   }
280   return result;
281 }
282 
AddAllocatedMessage(const FieldDescriptor * descriptor,MessageLite * new_entry)283 void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor,
284                                        MessageLite* new_entry) {
285   Extension* extension = MaybeNewRepeatedExtension(descriptor);
286 
287   extension->repeated_message_value->AddAllocated(new_entry);
288 }
289 
ValidateEnumUsingDescriptor(const void * arg,int number)290 static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
291   return reinterpret_cast<const EnumDescriptor*>(arg)->FindValueByNumber(
292              number) != NULL;
293 }
294 
Find(int number,ExtensionInfo * output)295 bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
296   const FieldDescriptor* extension =
297       pool_->FindExtensionByNumber(containing_type_, number);
298   if (extension == NULL) {
299     return false;
300   } else {
301     output->type = extension->type();
302     output->is_repeated = extension->is_repeated();
303     output->is_packed = extension->options().packed();
304     output->descriptor = extension;
305     if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
306       output->message_info.prototype =
307           factory_->GetPrototype(extension->message_type());
308       GOOGLE_CHECK(output->message_info.prototype != nullptr)
309           << "Extension factory's GetPrototype() returned NULL for extension: "
310           << extension->full_name();
311     } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
312       output->enum_validity_check.func = ValidateEnumUsingDescriptor;
313       output->enum_validity_check.arg = extension->enum_type();
314     }
315 
316     return true;
317   }
318 }
319 
320 
321 #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
FindExtension(int wire_type,uint32 field,const Message * containing_type,const internal::ParseContext * ctx,ExtensionInfo * extension,bool * was_packed_on_wire)322 bool ExtensionSet::FindExtension(int wire_type, uint32 field,
323                                  const Message* containing_type,
324                                  const internal::ParseContext* ctx,
325                                  ExtensionInfo* extension,
326                                  bool* was_packed_on_wire) {
327   if (ctx->data().pool == nullptr) {
328     GeneratedExtensionFinder finder(containing_type);
329     if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension,
330                                           was_packed_on_wire)) {
331       return false;
332     }
333   } else {
334     DescriptorPoolExtensionFinder finder(ctx->data().pool, ctx->data().factory,
335                                          containing_type->GetDescriptor());
336     if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension,
337                                           was_packed_on_wire)) {
338       return false;
339     }
340   }
341   return true;
342 }
343 
ParseField(uint64 tag,const char * ptr,const Message * containing_type,internal::InternalMetadataWithArena * metadata,internal::ParseContext * ctx)344 const char* ExtensionSet::ParseField(
345     uint64 tag, const char* ptr, const Message* containing_type,
346     internal::InternalMetadataWithArena* metadata,
347     internal::ParseContext* ctx) {
348   int number = tag >> 3;
349   bool was_packed_on_wire;
350   ExtensionInfo extension;
351   if (!FindExtension(tag & 7, number, containing_type, ctx, &extension,
352                      &was_packed_on_wire)) {
353     return UnknownFieldParse(tag, metadata->mutable_unknown_fields(), ptr, ctx);
354   }
355   return ParseFieldWithExtensionInfo(number, was_packed_on_wire, extension,
356                                      metadata, ptr, ctx);
357 }
358 
ParseFieldMaybeLazily(uint64 tag,const char * ptr,const Message * containing_type,internal::InternalMetadataWithArena * metadata,internal::ParseContext * ctx)359 const char* ExtensionSet::ParseFieldMaybeLazily(
360     uint64 tag, const char* ptr, const Message* containing_type,
361     internal::InternalMetadataWithArena* metadata,
362     internal::ParseContext* ctx) {
363   return ParseField(tag, ptr, containing_type, metadata, ctx);
364 }
365 
ParseMessageSetItem(const char * ptr,const Message * containing_type,internal::InternalMetadataWithArena * metadata,internal::ParseContext * ctx)366 const char* ExtensionSet::ParseMessageSetItem(
367     const char* ptr, const Message* containing_type,
368     internal::InternalMetadataWithArena* metadata,
369     internal::ParseContext* ctx) {
370   return ParseMessageSetItemTmpl(ptr, containing_type, metadata, ctx);
371 }
372 
373 #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
374 
ParseField(uint32 tag,io::CodedInputStream * input,const Message * containing_type,UnknownFieldSet * unknown_fields)375 bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
376                               const Message* containing_type,
377                               UnknownFieldSet* unknown_fields) {
378   UnknownFieldSetFieldSkipper skipper(unknown_fields);
379   if (input->GetExtensionPool() == NULL) {
380     GeneratedExtensionFinder finder(containing_type);
381     return ParseField(tag, input, &finder, &skipper);
382   } else {
383     DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
384                                          input->GetExtensionFactory(),
385                                          containing_type->GetDescriptor());
386     return ParseField(tag, input, &finder, &skipper);
387   }
388 }
389 
ParseMessageSet(io::CodedInputStream * input,const Message * containing_type,UnknownFieldSet * unknown_fields)390 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
391                                    const Message* containing_type,
392                                    UnknownFieldSet* unknown_fields) {
393   MessageSetFieldSkipper skipper(unknown_fields);
394   if (input->GetExtensionPool() == NULL) {
395     GeneratedExtensionFinder finder(containing_type);
396     return ParseMessageSet(input, &finder, &skipper);
397   } else {
398     DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
399                                          input->GetExtensionFactory(),
400                                          containing_type->GetDescriptor());
401     return ParseMessageSet(input, &finder, &skipper);
402   }
403 }
404 
SpaceUsedExcludingSelf() const405 int ExtensionSet::SpaceUsedExcludingSelf() const {
406   return internal::FromIntSize(SpaceUsedExcludingSelfLong());
407 }
408 
SpaceUsedExcludingSelfLong() const409 size_t ExtensionSet::SpaceUsedExcludingSelfLong() const {
410   size_t total_size = Size() * sizeof(KeyValue);
411   ForEach([&total_size](int /* number */, const Extension& ext) {
412     total_size += ext.SpaceUsedExcludingSelfLong();
413   });
414   return total_size;
415 }
416 
RepeatedMessage_SpaceUsedExcludingSelfLong(RepeatedPtrFieldBase * field)417 inline size_t ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelfLong(
418     RepeatedPtrFieldBase* field) {
419   return field->SpaceUsedExcludingSelfLong<GenericTypeHandler<Message> >();
420 }
421 
SpaceUsedExcludingSelfLong() const422 size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const {
423   size_t total_size = 0;
424   if (is_repeated) {
425     switch (cpp_type(type)) {
426 #define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
427   case FieldDescriptor::CPPTYPE_##UPPERCASE:                                  \
428     total_size += sizeof(*repeated_##LOWERCASE##_value) +                     \
429                   repeated_##LOWERCASE##_value->SpaceUsedExcludingSelfLong(); \
430     break
431 
432       HANDLE_TYPE(INT32, int32);
433       HANDLE_TYPE(INT64, int64);
434       HANDLE_TYPE(UINT32, uint32);
435       HANDLE_TYPE(UINT64, uint64);
436       HANDLE_TYPE(FLOAT, float);
437       HANDLE_TYPE(DOUBLE, double);
438       HANDLE_TYPE(BOOL, bool);
439       HANDLE_TYPE(ENUM, enum);
440       HANDLE_TYPE(STRING, string);
441 #undef HANDLE_TYPE
442 
443       case FieldDescriptor::CPPTYPE_MESSAGE:
444         // repeated_message_value is actually a RepeatedPtrField<MessageLite>,
445         // but MessageLite has no SpaceUsedLong(), so we must directly call
446         // RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() with a different
447         // type handler.
448         total_size += sizeof(*repeated_message_value) +
449                       RepeatedMessage_SpaceUsedExcludingSelfLong(
450                           reinterpret_cast<internal::RepeatedPtrFieldBase*>(
451                               repeated_message_value));
452         break;
453     }
454   } else {
455     switch (cpp_type(type)) {
456       case FieldDescriptor::CPPTYPE_STRING:
457         total_size += sizeof(*string_value) +
458                       StringSpaceUsedExcludingSelfLong(*string_value);
459         break;
460       case FieldDescriptor::CPPTYPE_MESSAGE:
461         if (is_lazy) {
462           total_size += lazymessage_value->SpaceUsedLong();
463         } else {
464           total_size += down_cast<Message*>(message_value)->SpaceUsedLong();
465         }
466         break;
467       default:
468         // No extra storage costs for primitive types.
469         break;
470     }
471   }
472   return total_size;
473 }
474 
475 // The Serialize*ToArray methods are only needed in the heavy library, as
476 // the lite library only generates SerializeWithCachedSizes.
SerializeWithCachedSizesToArray(int start_field_number,int end_field_number,uint8 * target) const477 uint8* ExtensionSet::SerializeWithCachedSizesToArray(int start_field_number,
478                                                      int end_field_number,
479                                                      uint8* target) const {
480   return InternalSerializeWithCachedSizesToArray(start_field_number,
481                                                  end_field_number, target);
482 }
483 
SerializeMessageSetWithCachedSizesToArray(uint8 * target) const484 uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
485     uint8* target) const {
486   return InternalSerializeMessageSetWithCachedSizesToArray(target);
487 }
488 
InternalSerializeWithCachedSizesToArray(int start_field_number,int end_field_number,uint8 * target) const489 uint8* ExtensionSet::InternalSerializeWithCachedSizesToArray(
490     int start_field_number, int end_field_number, uint8* target) const {
491   if (PROTOBUF_PREDICT_FALSE(is_large())) {
492     const auto& end = map_.large->end();
493     for (auto it = map_.large->lower_bound(start_field_number);
494          it != end && it->first < end_field_number; ++it) {
495       target = it->second.InternalSerializeFieldWithCachedSizesToArray(
496           it->first, target);
497     }
498     return target;
499   }
500   const KeyValue* end = flat_end();
501   for (const KeyValue* it = std::lower_bound(
502            flat_begin(), end, start_field_number, KeyValue::FirstComparator());
503        it != end && it->first < end_field_number; ++it) {
504     target = it->second.InternalSerializeFieldWithCachedSizesToArray(it->first,
505                                                                      target);
506   }
507   return target;
508 }
509 
InternalSerializeMessageSetWithCachedSizesToArray(uint8 * target) const510 uint8* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray(
511     uint8* target) const {
512   ForEach([&target](int number, const Extension& ext) {
513     target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray(number,
514                                                                        target);
515   });
516   return target;
517 }
518 
InternalSerializeFieldWithCachedSizesToArray(int number,uint8 * target) const519 uint8* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray(
520     int number, uint8* target) const {
521   if (is_repeated) {
522     if (is_packed) {
523       if (cached_size == 0) return target;
524 
525       target = WireFormatLite::WriteTagToArray(
526           number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
527       target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
528 
529       switch (real_type(type)) {
530 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                 \
531   case FieldDescriptor::TYPE_##UPPERCASE:                            \
532     for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
533       target = WireFormatLite::Write##CAMELCASE##NoTagToArray(       \
534           repeated_##LOWERCASE##_value->Get(i), target);             \
535     }                                                                \
536     break
537 
538         HANDLE_TYPE(INT32, Int32, int32);
539         HANDLE_TYPE(INT64, Int64, int64);
540         HANDLE_TYPE(UINT32, UInt32, uint32);
541         HANDLE_TYPE(UINT64, UInt64, uint64);
542         HANDLE_TYPE(SINT32, SInt32, int32);
543         HANDLE_TYPE(SINT64, SInt64, int64);
544         HANDLE_TYPE(FIXED32, Fixed32, uint32);
545         HANDLE_TYPE(FIXED64, Fixed64, uint64);
546         HANDLE_TYPE(SFIXED32, SFixed32, int32);
547         HANDLE_TYPE(SFIXED64, SFixed64, int64);
548         HANDLE_TYPE(FLOAT, Float, float);
549         HANDLE_TYPE(DOUBLE, Double, double);
550         HANDLE_TYPE(BOOL, Bool, bool);
551         HANDLE_TYPE(ENUM, Enum, enum);
552 #undef HANDLE_TYPE
553 
554         case FieldDescriptor::TYPE_STRING:
555         case FieldDescriptor::TYPE_BYTES:
556         case FieldDescriptor::TYPE_GROUP:
557         case FieldDescriptor::TYPE_MESSAGE:
558           GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
559           break;
560       }
561     } else {
562       switch (real_type(type)) {
563 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                 \
564   case FieldDescriptor::TYPE_##UPPERCASE:                            \
565     for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
566       target = WireFormatLite::Write##CAMELCASE##ToArray(            \
567           number, repeated_##LOWERCASE##_value->Get(i), target);     \
568     }                                                                \
569     break
570 
571         HANDLE_TYPE(INT32, Int32, int32);
572         HANDLE_TYPE(INT64, Int64, int64);
573         HANDLE_TYPE(UINT32, UInt32, uint32);
574         HANDLE_TYPE(UINT64, UInt64, uint64);
575         HANDLE_TYPE(SINT32, SInt32, int32);
576         HANDLE_TYPE(SINT64, SInt64, int64);
577         HANDLE_TYPE(FIXED32, Fixed32, uint32);
578         HANDLE_TYPE(FIXED64, Fixed64, uint64);
579         HANDLE_TYPE(SFIXED32, SFixed32, int32);
580         HANDLE_TYPE(SFIXED64, SFixed64, int64);
581         HANDLE_TYPE(FLOAT, Float, float);
582         HANDLE_TYPE(DOUBLE, Double, double);
583         HANDLE_TYPE(BOOL, Bool, bool);
584         HANDLE_TYPE(STRING, String, string);
585         HANDLE_TYPE(BYTES, Bytes, string);
586         HANDLE_TYPE(ENUM, Enum, enum);
587 #undef HANDLE_TYPE
588 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                 \
589   case FieldDescriptor::TYPE_##UPPERCASE:                            \
590     for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
591       target = WireFormatLite::InternalWrite##CAMELCASE##ToArray(    \
592           number, repeated_##LOWERCASE##_value->Get(i), target);     \
593     }                                                                \
594     break
595 
596         HANDLE_TYPE(GROUP, Group, message);
597         HANDLE_TYPE(MESSAGE, Message, message);
598 #undef HANDLE_TYPE
599       }
600     }
601   } else if (!is_cleared) {
602     switch (real_type(type)) {
603 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE)                               \
604   case FieldDescriptor::TYPE_##UPPERCASE:                                      \
605     target = WireFormatLite::Write##CAMELCASE##ToArray(number, VALUE, target); \
606     break
607 
608       HANDLE_TYPE(INT32, Int32, int32_value);
609       HANDLE_TYPE(INT64, Int64, int64_value);
610       HANDLE_TYPE(UINT32, UInt32, uint32_value);
611       HANDLE_TYPE(UINT64, UInt64, uint64_value);
612       HANDLE_TYPE(SINT32, SInt32, int32_value);
613       HANDLE_TYPE(SINT64, SInt64, int64_value);
614       HANDLE_TYPE(FIXED32, Fixed32, uint32_value);
615       HANDLE_TYPE(FIXED64, Fixed64, uint64_value);
616       HANDLE_TYPE(SFIXED32, SFixed32, int32_value);
617       HANDLE_TYPE(SFIXED64, SFixed64, int64_value);
618       HANDLE_TYPE(FLOAT, Float, float_value);
619       HANDLE_TYPE(DOUBLE, Double, double_value);
620       HANDLE_TYPE(BOOL, Bool, bool_value);
621       HANDLE_TYPE(STRING, String, *string_value);
622       HANDLE_TYPE(BYTES, Bytes, *string_value);
623       HANDLE_TYPE(ENUM, Enum, enum_value);
624       HANDLE_TYPE(GROUP, Group, *message_value);
625 #undef HANDLE_TYPE
626       case FieldDescriptor::TYPE_MESSAGE:
627         if (is_lazy) {
628           target = lazymessage_value->WriteMessageToArray(number, target);
629         } else {
630           target = WireFormatLite::InternalWriteMessageToArray(
631               number, *message_value, target);
632         }
633         break;
634     }
635   }
636   return target;
637 }
638 
639 uint8*
InternalSerializeMessageSetItemWithCachedSizesToArray(int number,uint8 * target) const640 ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray(
641     int number, uint8* target) const {
642   if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
643     // Not a valid MessageSet extension, but serialize it the normal way.
644     GOOGLE_LOG(WARNING) << "Invalid message set extension.";
645     return InternalSerializeFieldWithCachedSizesToArray(number, target);
646   }
647 
648   if (is_cleared) return target;
649 
650   // Start group.
651   target = io::CodedOutputStream::WriteTagToArray(
652       WireFormatLite::kMessageSetItemStartTag, target);
653   // Write type ID.
654   target = WireFormatLite::WriteUInt32ToArray(
655       WireFormatLite::kMessageSetTypeIdNumber, number, target);
656   // Write message.
657   if (is_lazy) {
658     target = lazymessage_value->WriteMessageToArray(
659         WireFormatLite::kMessageSetMessageNumber, target);
660   } else {
661     target = WireFormatLite::InternalWriteMessageToArray(
662         WireFormatLite::kMessageSetMessageNumber, *message_value, target);
663   }
664   // End group.
665   target = io::CodedOutputStream::WriteTagToArray(
666       WireFormatLite::kMessageSetItemEndTag, target);
667   return target;
668 }
669 
ParseFieldMaybeLazily(int wire_type,int field_number,io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)670 bool ExtensionSet::ParseFieldMaybeLazily(
671     int wire_type, int field_number, io::CodedInputStream* input,
672     ExtensionFinder* extension_finder, MessageSetFieldSkipper* field_skipper) {
673   return ParseField(
674       WireFormatLite::MakeTag(field_number,
675                               static_cast<WireFormatLite::WireType>(wire_type)),
676       input, extension_finder, field_skipper);
677 }
678 
ParseMessageSet(io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)679 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
680                                    ExtensionFinder* extension_finder,
681                                    MessageSetFieldSkipper* field_skipper) {
682   while (true) {
683     const uint32 tag = input->ReadTag();
684     switch (tag) {
685       case 0:
686         return true;
687       case WireFormatLite::kMessageSetItemStartTag:
688         if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
689           return false;
690         }
691         break;
692       default:
693         if (!ParseField(tag, input, extension_finder, field_skipper)) {
694           return false;
695         }
696         break;
697     }
698   }
699 }
700 
ParseMessageSetItem(io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)701 bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
702                                        ExtensionFinder* extension_finder,
703                                        MessageSetFieldSkipper* field_skipper) {
704   struct MSFull {
705     bool ParseField(int type_id, io::CodedInputStream* input) {
706       return me->ParseFieldMaybeLazily(
707           WireFormatLite::WIRETYPE_LENGTH_DELIMITED, type_id, input,
708           extension_finder, field_skipper);
709     }
710 
711     bool SkipField(uint32 tag, io::CodedInputStream* input) {
712       return field_skipper->SkipField(input, tag);
713     }
714 
715     ExtensionSet* me;
716     ExtensionFinder* extension_finder;
717     MessageSetFieldSkipper* field_skipper;
718   };
719 
720   return ParseMessageSetItemImpl(input,
721                                  MSFull{this, extension_finder, field_skipper});
722 }
723 
724 }  // namespace internal
725 }  // namespace protobuf
726 }  // namespace google
727