• 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 
FindExtension(int wire_type,uint32 field,const Message * containing_type,const internal::ParseContext * ctx,ExtensionInfo * extension,bool * was_packed_on_wire)321 bool ExtensionSet::FindExtension(int wire_type, uint32 field,
322                                  const Message* containing_type,
323                                  const internal::ParseContext* ctx,
324                                  ExtensionInfo* extension,
325                                  bool* was_packed_on_wire) {
326   if (ctx->data().pool == nullptr) {
327     GeneratedExtensionFinder finder(containing_type);
328     if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension,
329                                           was_packed_on_wire)) {
330       return false;
331     }
332   } else {
333     DescriptorPoolExtensionFinder finder(ctx->data().pool, ctx->data().factory,
334                                          containing_type->GetDescriptor());
335     if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension,
336                                           was_packed_on_wire)) {
337       return false;
338     }
339   }
340   return true;
341 }
342 
ParseField(uint64 tag,const char * ptr,const Message * containing_type,internal::InternalMetadata * metadata,internal::ParseContext * ctx)343 const char* ExtensionSet::ParseField(uint64 tag, const char* ptr,
344                                      const Message* containing_type,
345                                      internal::InternalMetadata* metadata,
346                                      internal::ParseContext* ctx) {
347   int number = tag >> 3;
348   bool was_packed_on_wire;
349   ExtensionInfo extension;
350   if (!FindExtension(tag & 7, number, containing_type, ctx, &extension,
351                      &was_packed_on_wire)) {
352     return UnknownFieldParse(
353         tag, metadata->mutable_unknown_fields<UnknownFieldSet>(), ptr, ctx);
354   }
355   return ParseFieldWithExtensionInfo<UnknownFieldSet>(
356       number, was_packed_on_wire, extension, metadata, ptr, ctx);
357 }
358 
ParseFieldMaybeLazily(uint64 tag,const char * ptr,const Message * containing_type,internal::InternalMetadata * metadata,internal::ParseContext * ctx)359 const char* ExtensionSet::ParseFieldMaybeLazily(
360     uint64 tag, const char* ptr, const Message* containing_type,
361     internal::InternalMetadata* metadata, internal::ParseContext* ctx) {
362   return ParseField(tag, ptr, containing_type, metadata, ctx);
363 }
364 
ParseMessageSetItem(const char * ptr,const Message * containing_type,internal::InternalMetadata * metadata,internal::ParseContext * ctx)365 const char* ExtensionSet::ParseMessageSetItem(
366     const char* ptr, const Message* containing_type,
367     internal::InternalMetadata* metadata, internal::ParseContext* ctx) {
368   return ParseMessageSetItemTmpl<Message, UnknownFieldSet>(ptr, containing_type,
369                                                            metadata, ctx);
370 }
371 
ParseField(uint32 tag,io::CodedInputStream * input,const Message * containing_type,UnknownFieldSet * unknown_fields)372 bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
373                               const Message* containing_type,
374                               UnknownFieldSet* unknown_fields) {
375   UnknownFieldSetFieldSkipper skipper(unknown_fields);
376   if (input->GetExtensionPool() == NULL) {
377     GeneratedExtensionFinder finder(containing_type);
378     return ParseField(tag, input, &finder, &skipper);
379   } else {
380     DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
381                                          input->GetExtensionFactory(),
382                                          containing_type->GetDescriptor());
383     return ParseField(tag, input, &finder, &skipper);
384   }
385 }
386 
ParseMessageSet(io::CodedInputStream * input,const Message * containing_type,UnknownFieldSet * unknown_fields)387 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
388                                    const Message* containing_type,
389                                    UnknownFieldSet* unknown_fields) {
390   MessageSetFieldSkipper skipper(unknown_fields);
391   if (input->GetExtensionPool() == NULL) {
392     GeneratedExtensionFinder finder(containing_type);
393     return ParseMessageSet(input, &finder, &skipper);
394   } else {
395     DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
396                                          input->GetExtensionFactory(),
397                                          containing_type->GetDescriptor());
398     return ParseMessageSet(input, &finder, &skipper);
399   }
400 }
401 
SpaceUsedExcludingSelf() const402 int ExtensionSet::SpaceUsedExcludingSelf() const {
403   return internal::FromIntSize(SpaceUsedExcludingSelfLong());
404 }
405 
SpaceUsedExcludingSelfLong() const406 size_t ExtensionSet::SpaceUsedExcludingSelfLong() const {
407   size_t total_size = Size() * sizeof(KeyValue);
408   ForEach([&total_size](int /* number */, const Extension& ext) {
409     total_size += ext.SpaceUsedExcludingSelfLong();
410   });
411   return total_size;
412 }
413 
RepeatedMessage_SpaceUsedExcludingSelfLong(RepeatedPtrFieldBase * field)414 inline size_t ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelfLong(
415     RepeatedPtrFieldBase* field) {
416   return field->SpaceUsedExcludingSelfLong<GenericTypeHandler<Message> >();
417 }
418 
SpaceUsedExcludingSelfLong() const419 size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const {
420   size_t total_size = 0;
421   if (is_repeated) {
422     switch (cpp_type(type)) {
423 #define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
424   case FieldDescriptor::CPPTYPE_##UPPERCASE:                                  \
425     total_size += sizeof(*repeated_##LOWERCASE##_value) +                     \
426                   repeated_##LOWERCASE##_value->SpaceUsedExcludingSelfLong(); \
427     break
428 
429       HANDLE_TYPE(INT32, int32);
430       HANDLE_TYPE(INT64, int64);
431       HANDLE_TYPE(UINT32, uint32);
432       HANDLE_TYPE(UINT64, uint64);
433       HANDLE_TYPE(FLOAT, float);
434       HANDLE_TYPE(DOUBLE, double);
435       HANDLE_TYPE(BOOL, bool);
436       HANDLE_TYPE(ENUM, enum);
437       HANDLE_TYPE(STRING, string);
438 #undef HANDLE_TYPE
439 
440       case FieldDescriptor::CPPTYPE_MESSAGE:
441         // repeated_message_value is actually a RepeatedPtrField<MessageLite>,
442         // but MessageLite has no SpaceUsedLong(), so we must directly call
443         // RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() with a different
444         // type handler.
445         total_size += sizeof(*repeated_message_value) +
446                       RepeatedMessage_SpaceUsedExcludingSelfLong(
447                           reinterpret_cast<internal::RepeatedPtrFieldBase*>(
448                               repeated_message_value));
449         break;
450     }
451   } else {
452     switch (cpp_type(type)) {
453       case FieldDescriptor::CPPTYPE_STRING:
454         total_size += sizeof(*string_value) +
455                       StringSpaceUsedExcludingSelfLong(*string_value);
456         break;
457       case FieldDescriptor::CPPTYPE_MESSAGE:
458         if (is_lazy) {
459           total_size += lazymessage_value->SpaceUsedLong();
460         } else {
461           total_size += down_cast<Message*>(message_value)->SpaceUsedLong();
462         }
463         break;
464       default:
465         // No extra storage costs for primitive types.
466         break;
467     }
468   }
469   return total_size;
470 }
471 
SerializeMessageSetWithCachedSizesToArray(uint8 * target) const472 uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
473     uint8* target) const {
474   io::EpsCopyOutputStream stream(
475       target, MessageSetByteSize(),
476       io::CodedOutputStream::IsDefaultSerializationDeterministic());
477   return InternalSerializeMessageSetWithCachedSizesToArray(target, &stream);
478 }
479 
ParseFieldMaybeLazily(int wire_type,int field_number,io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)480 bool ExtensionSet::ParseFieldMaybeLazily(
481     int wire_type, int field_number, io::CodedInputStream* input,
482     ExtensionFinder* extension_finder, MessageSetFieldSkipper* field_skipper) {
483   return ParseField(
484       WireFormatLite::MakeTag(field_number,
485                               static_cast<WireFormatLite::WireType>(wire_type)),
486       input, extension_finder, field_skipper);
487 }
488 
ParseMessageSet(io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)489 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
490                                    ExtensionFinder* extension_finder,
491                                    MessageSetFieldSkipper* field_skipper) {
492   while (true) {
493     const uint32 tag = input->ReadTag();
494     switch (tag) {
495       case 0:
496         return true;
497       case WireFormatLite::kMessageSetItemStartTag:
498         if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
499           return false;
500         }
501         break;
502       default:
503         if (!ParseField(tag, input, extension_finder, field_skipper)) {
504           return false;
505         }
506         break;
507     }
508   }
509 }
510 
ParseMessageSetItem(io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)511 bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
512                                        ExtensionFinder* extension_finder,
513                                        MessageSetFieldSkipper* field_skipper) {
514   struct MSFull {
515     bool ParseField(int type_id, io::CodedInputStream* input) {
516       return me->ParseFieldMaybeLazily(
517           WireFormatLite::WIRETYPE_LENGTH_DELIMITED, type_id, input,
518           extension_finder, field_skipper);
519     }
520 
521     bool SkipField(uint32 tag, io::CodedInputStream* input) {
522       return field_skipper->SkipField(input, tag);
523     }
524 
525     ExtensionSet* me;
526     ExtensionFinder* extension_finder;
527     MessageSetFieldSkipper* field_skipper;
528   };
529 
530   return ParseMessageSetItemImpl(input,
531                                  MSFull{this, extension_finder, field_skipper});
532 }
533 
534 }  // namespace internal
535 }  // namespace protobuf
536 }  // namespace google
537