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