text: // Protocol Buffers - Google's data interchange format
  // Copyright 2008 Google Inc.  All rights reserved.
  // https://developers.google.com/protocol-buffers/
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
  //
  //     * Redistributions of source code must retain the above copyright
  // notice, this list of conditions and the following disclaimer.
  //     * Redistributions in binary form must reproduce the above
  // copyright notice, this list of conditions and the following disclaimer
  // in the documentation and/or other materials provided with the
  // distribution.
  //     * Neither the name of Google Inc. nor the names of its
  // contributors may be used to endorse or promote products derived from
  // this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  // Author: kenton@google.com (Kenton Varda)
  //  Based on original Protocol Buffers design by
  //  Sanjay Ghemawat, Jeff Dean, and others.
  //
  // Contains methods defined in extension_set.h which cannot be part of the
  // lite library because they use descriptors or reflection.
  
  #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
  #include <google/protobuf/descriptor.h>
  #include <google/protobuf/extension_set.h>
  #include <google/protobuf/message.h>
  #include <google/protobuf/repeated_field.h>
  #include <google/protobuf/wire_format.h>
  #include <google/protobuf/wire_format_lite_inl.h>
  
  namespace google {
  
  namespace protobuf {
  namespace internal {
  
  // A FieldSkipper used to store unknown MessageSet fields into UnknownFieldSet.
  class MessageSetFieldSkipper
      : public UnknownFieldSetFieldSkipper {
   public:
    explicit MessageSetFieldSkipper(UnknownFieldSet* unknown_fields)
        : UnknownFieldSetFieldSkipper(unknown_fields) {}
    virtual ~MessageSetFieldSkipper() {}
  
    virtual bool SkipMessageSetField(io::CodedInputStream* input,
                                     int field_number);
  };
  bool MessageSetFieldSkipper::SkipMessageSetField(
      io::CodedInputStream* input, int field_number) {
    uint32 length;
    if (!input->ReadVarint32(&length)) return false;
    if (unknown_fields_ == NULL) {
      return input->Skip(length);
    } else {
      return input->ReadString(
          unknown_fields_->AddLengthDelimited(field_number), length);
    }
  }
  
  
  // Implementation of ExtensionFinder which finds extensions in a given
  // DescriptorPool, using the given MessageFactory to construct sub-objects.
  // This class is implemented in extension_set_heavy.cc.
  class DescriptorPoolExtensionFinder : public ExtensionFinder {
   public:
    DescriptorPoolExtensionFinder(const DescriptorPool* pool,
                                  MessageFactory* factory,
                                  const Descriptor* containing_type)
        : pool_(pool), factory_(factory), containing_type_(containing_type) {}
    virtual ~DescriptorPoolExtensionFinder() {}
  
    virtual bool Find(int number, ExtensionInfo* output);
  
   private:
    const DescriptorPool* pool_;
    MessageFactory* factory_;
    const Descriptor* containing_type_;
  };
  
  void ExtensionSet::AppendToList(
      const Descriptor* containing_type,
      const DescriptorPool* pool,
      std::vector<const FieldDescriptor*>* output) const {
    for (map<int, Extension>::const_iterator iter = extensions_.begin();
         iter != extensions_.end(); ++iter) {
      bool has = false;
      if (iter->second.is_repeated) {
        has = iter->second.GetSize() > 0;
      } else {
        has = !iter->second.is_cleared;
      }
  
      if (has) {
        // TODO(kenton): Looking up each field by number is somewhat unfortunate.
        //   Is there a better way?  The problem is that descriptors are lazily-
        //   initialized, so they might not even be constructed until
        //   AppendToList() is called.
  
        if (iter->second.descriptor == NULL) {
          output->push_back(pool->FindExtensionByNumber(
              containing_type, iter->first));
        } else {
          output->push_back(iter->second.descriptor);
        }
      }
    }
  }
  
  inline FieldDescriptor::Type real_type(FieldType type) {
    GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
    return static_cast<FieldDescriptor::Type>(type);
  }
  
  inline FieldDescriptor::CppType cpp_type(FieldType type) {
    return FieldDescriptor::TypeToCppType(
        static_cast<FieldDescriptor::Type>(type));
  }
  
  inline WireFormatLite::FieldType field_type(FieldType type) {
    GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
    return static_cast<WireFormatLite::FieldType>(type);
  }
  
  #define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE)                            \
    GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED     \
                                    : FieldDescriptor::LABEL_OPTIONAL,      \
              FieldDescriptor::LABEL_##LABEL);                              \
    GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
  
  const MessageLite& ExtensionSet::GetMessage(int number,
                                              const Descriptor* message_type,
                                              MessageFactory* factory) const {
    map<int, Extension>::const_iterator iter = extensions_.find(number);
    if (iter == extensions_.end() || iter->second.is_cleared) {
      // Not present.  Return the default value.
      return *factory->GetPrototype(message_type);
    } else {
      GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
      if (iter->second.is_lazy) {
        return iter->second.lazymessage_value->GetMessage(
            *factory->GetPrototype(message_type));
      } else {
        return *iter->second.message_value;
      }
    }
  }
  
  MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
                                            MessageFactory* factory) {
    Extension* extension;
    if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
      extension->type = descriptor->type();
      GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
      extension->is_repeated = false;
      extension->is_packed = false;
      const MessageLite* prototype =
          factory->GetPrototype(descriptor->message_type());
      extension->is_lazy = false;
      extension->message_value = prototype->New(arena_);
      extension->is_cleared = false;
      return extension->message_value;
    } else {
      GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
      extension->is_cleared = false;
      if (extension->is_lazy) {
        return extension->lazymessage_value->MutableMessage(
            *factory->GetPrototype(descriptor->message_type()));
      } else {
        return extension->message_value;
      }
    }
  }
  
  MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
                                            MessageFactory* factory) {
    map<int, Extension>::iterator iter = extensions_.find(descriptor->number());
    if (iter == extensions_.end()) {
      // Not present.  Return NULL.
      return NULL;
    } else {
      GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
      MessageLite* ret = NULL;
      if (iter->second.is_lazy) {
        ret = iter->second.lazymessage_value->ReleaseMessage(
            *factory->GetPrototype(descriptor->message_type()));
        if (arena_ == NULL) {
          delete iter->second.lazymessage_value;
        }
      } else {
        if (arena_ != NULL) {
          ret = (iter->second.message_value)->New();
          ret->CheckTypeAndMergeFrom(*(iter->second.message_value));
        } else {
          ret = iter->second.message_value;
        }
      }
      extensions_.erase(descriptor->number());
      return ret;
    }
  }
  
  ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(const FieldDescriptor* descriptor) {
    Extension* extension;
    if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
      extension->type = descriptor->type();
      GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
      extension->is_repeated = true;
      extension->repeated_message_value =
          ::google::protobuf::Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
    } else {
      GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
    }
    return extension;
  }
  
  MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
                                        MessageFactory* factory) {
    Extension* extension = MaybeNewRepeatedExtension(descriptor);
  
    // RepeatedPtrField<Message> does not know how to Add() since it cannot
    // allocate an abstract object, so we have to be tricky.
    MessageLite* result = extension->repeated_message_value
        ->AddFromCleared<GenericTypeHandler<MessageLite> >();
    if (result == NULL) {
      const MessageLite* prototype;
      if (extension->repeated_message_value->size() == 0) {
        prototype = factory->GetPrototype(descriptor->message_type());
        GOOGLE_CHECK(prototype != NULL);
      } else {
        prototype = &extension->repeated_message_value->Get(0);
      }
      result = prototype->New(arena_);
      extension->repeated_message_value->AddAllocated(result);
    }
    return result;
  }
  
  void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor,
                                         MessageLite* new_entry) {
    Extension* extension = MaybeNewRepeatedExtension(descriptor);
  
    extension->repeated_message_value->AddAllocated(new_entry);
  }
  
  static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
    return reinterpret_cast<const EnumDescriptor*>(arg)
        ->FindValueByNumber(number) != NULL;
  }
  
  bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
    const FieldDescriptor* extension =
        pool_->FindExtensionByNumber(containing_type_, number);
    if (extension == NULL) {
      return false;
    } else {
      output->type = extension->type();
      output->is_repeated = extension->is_repeated();
      output->is_packed = extension->options().packed();
      output->descriptor = extension;
      if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
        output->message_prototype =
            factory_->GetPrototype(extension->message_type());
        GOOGLE_CHECK(output->message_prototype != NULL)
            << "Extension factory's GetPrototype() returned NULL for extension: "
            << extension->full_name();
      } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
        output->enum_validity_check.func = ValidateEnumUsingDescriptor;
        output->enum_validity_check.arg = extension->enum_type();
      }
  
      return true;
    }
  }
  
  bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
                                const Message* containing_type,
                                UnknownFieldSet* unknown_fields) {
    UnknownFieldSetFieldSkipper skipper(unknown_fields);
    if (input->GetExtensionPool() == NULL) {
      GeneratedExtensionFinder finder(containing_type);
      return ParseField(tag, input, &finder, &skipper);
    } else {
      DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
                                           input->GetExtensionFactory(),
                                           containing_type->GetDescriptor());
      return ParseField(tag, input, &finder, &skipper);
    }
  }
  
  bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
                                     const Message* containing_type,
                                     UnknownFieldSet* unknown_fields) {
    MessageSetFieldSkipper skipper(unknown_fields);
    if (input->GetExtensionPool() == NULL) {
      GeneratedExtensionFinder finder(containing_type);
      return ParseMessageSet(input, &finder, &skipper);
    } else {
      DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
                                           input->GetExtensionFactory(),
                                           containing_type->GetDescriptor());
      return ParseMessageSet(input, &finder, &skipper);
    }
  }
  
  int ExtensionSet::SpaceUsedExcludingSelf() const {
    int total_size =
        extensions_.size() * sizeof(map<int, Extension>::value_type);
    for (map<int, Extension>::const_iterator iter = extensions_.begin(),
         end = extensions_.end();
         iter != end;
         ++iter) {
      total_size += iter->second.SpaceUsedExcludingSelf();
    }
    return total_size;
  }
  
  inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf(
      RepeatedPtrFieldBase* field) {
    return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
  }
  
  int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
    int total_size = 0;
    if (is_repeated) {
      switch (cpp_type(type)) {
  #define HANDLE_TYPE(UPPERCASE, LOWERCASE)                          \
        case FieldDescriptor::CPPTYPE_##UPPERCASE:                   \
          total_size += sizeof(*repeated_##LOWERCASE##_value) +      \
              repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
          break
  
        HANDLE_TYPE(  INT32,   int32);
        HANDLE_TYPE(  INT64,   int64);
        HANDLE_TYPE( UINT32,  uint32);
        HANDLE_TYPE( UINT64,  uint64);
        HANDLE_TYPE(  FLOAT,   float);
        HANDLE_TYPE( DOUBLE,  double);
        HANDLE_TYPE(   BOOL,    bool);
        HANDLE_TYPE(   ENUM,    enum);
        HANDLE_TYPE( STRING,  string);
  #undef HANDLE_TYPE
  
        case FieldDescriptor::CPPTYPE_MESSAGE:
          // repeated_message_value is actually a RepeatedPtrField<MessageLite>,
          // but MessageLite has no SpaceUsed(), so we must directly call
          // RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
          // handler.
          total_size += sizeof(*repeated_message_value) +
              RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value);
          break;
      }
    } else {
      switch (cpp_type(type)) {
        case FieldDescriptor::CPPTYPE_STRING:
          total_size += sizeof(*string_value) +
                        StringSpaceUsedExcludingSelf(*string_value);
          break;
        case FieldDescriptor::CPPTYPE_MESSAGE:
          if (is_lazy) {
            total_size += lazymessage_value->SpaceUsed();
          } else {
            total_size += down_cast<Message*>(message_value)->SpaceUsed();
          }
          break;
        default:
          // No extra storage costs for primitive types.
          break;
      }
    }
    return total_size;
  }
  
  // The Serialize*ToArray methods are only needed in the heavy library, as
  // the lite library only generates SerializeWithCachedSizes.
  uint8* ExtensionSet::SerializeWithCachedSizesToArray(
      int start_field_number, int end_field_number,
      uint8* target) const {
    map<int, Extension>::const_iterator iter;
    for (iter = extensions_.lower_bound(start_field_number);
         iter != extensions_.end() && iter->first < end_field_number;
         ++iter) {
      target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first,
                                                                 target);
    }
    return target;
  }
  
  uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
      uint8* target) const {
    map<int, Extension>::const_iterator iter;
    for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
      target = iter->second.SerializeMessageSetItemWithCachedSizesToArray(
          iter->first, target);
    }
    return target;
  }
  
  uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray(
      int number, uint8* target) const {
    if (is_repeated) {
      if (is_packed) {
        if (cached_size == 0) return target;
  
        target = WireFormatLite::WriteTagToArray(number,
            WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
        target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
  
        switch (real_type(type)) {
  #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
          case FieldDescriptor::TYPE_##UPPERCASE:                             \
            for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
              target = WireFormatLite::Write##CAMELCASE##NoTagToArray(        \
                repeated_##LOWERCASE##_value->Get(i), target);                \
            }                                                                 \
            break
  
          HANDLE_TYPE(   INT32,    Int32,   int32);
          HANDLE_TYPE(   INT64,    Int64,   int64);
          HANDLE_TYPE(  UINT32,   UInt32,  uint32);
          HANDLE_TYPE(  UINT64,   UInt64,  uint64);
          HANDLE_TYPE(  SINT32,   SInt32,   int32);
          HANDLE_TYPE(  SINT64,   SInt64,   int64);
          HANDLE_TYPE( FIXED32,  Fixed32,  uint32);
          HANDLE_TYPE( FIXED64,  Fixed64,  uint64);
          HANDLE_TYPE(SFIXED32, SFixed32,   int32);
          HANDLE_TYPE(SFIXED64, SFixed64,   int64);
          HANDLE_TYPE(   FLOAT,    Float,   float);
          HANDLE_TYPE(  DOUBLE,   Double,  double);
          HANDLE_TYPE(    BOOL,     Bool,    bool);
          HANDLE_TYPE(    ENUM,     Enum,    enum);
  #undef HANDLE_TYPE
  
          case WireFormatLite::TYPE_STRING:
          case WireFormatLite::TYPE_BYTES:
          case WireFormatLite::TYPE_GROUP:
          case WireFormatLite::TYPE_MESSAGE:
            GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
            break;
        }
      } else {
        switch (real_type(type)) {
  #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
          case FieldDescriptor::TYPE_##UPPERCASE:                             \
            for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
              target = WireFormatLite::Write##CAMELCASE##ToArray(number,      \
                repeated_##LOWERCASE##_value->Get(i), target);                \
            }                                                                 \
            break
  
          HANDLE_TYPE(   INT32,    Int32,   int32);
          HANDLE_TYPE(   INT64,    Int64,   int64);
          HANDLE_TYPE(  UINT32,   UInt32,  uint32);
          HANDLE_TYPE(  UINT64,   UInt64,  uint64);
          HANDLE_TYPE(  SINT32,   SInt32,   int32);
          HANDLE_TYPE(  SINT64,   SInt64,   int64);
          HANDLE_TYPE( FIXED32,  Fixed32,  uint32);
          HANDLE_TYPE( FIXED64,  Fixed64,  uint64);
          HANDLE_TYPE(SFIXED32, SFixed32,   int32);
          HANDLE_TYPE(SFIXED64, SFixed64,   int64);
          HANDLE_TYPE(   FLOAT,    Float,   float);
          HANDLE_TYPE(  DOUBLE,   Double,  double);
          HANDLE_TYPE(    BOOL,     Bool,    bool);
          HANDLE_TYPE(  STRING,   String,  string);
          HANDLE_TYPE(   BYTES,    Bytes,  string);
          HANDLE_TYPE(    ENUM,     Enum,    enum);
          HANDLE_TYPE(   GROUP,    Group, message);
          HANDLE_TYPE( MESSAGE,  Message, message);
  #undef HANDLE_TYPE
        }
      }
    } else if (!is_cleared) {
      switch (real_type(type)) {
  #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE)                 \
        case FieldDescriptor::TYPE_##UPPERCASE:                    \
          target = WireFormatLite::Write##CAMELCASE##ToArray(      \
              number, VALUE, target); \
          break
  
        HANDLE_TYPE(   INT32,    Int32,    int32_value);
        HANDLE_TYPE(   INT64,    Int64,    int64_value);
        HANDLE_TYPE(  UINT32,   UInt32,   uint32_value);
        HANDLE_TYPE(  UINT64,   UInt64,   uint64_value);
        HANDLE_TYPE(  SINT32,   SInt32,    int32_value);
        HANDLE_TYPE(  SINT64,   SInt64,    int64_value);
        HANDLE_TYPE( FIXED32,  Fixed32,   uint32_value);
        HANDLE_TYPE( FIXED64,  Fixed64,   uint64_value);
        HANDLE_TYPE(SFIXED32, SFixed32,    int32_value);
        HANDLE_TYPE(SFIXED64, SFixed64,    int64_value);
        HANDLE_TYPE(   FLOAT,    Float,    float_value);
        HANDLE_TYPE(  DOUBLE,   Double,   double_value);
        HANDLE_TYPE(    BOOL,     Bool,     bool_value);
        HANDLE_TYPE(  STRING,   String,  *string_value);
        HANDLE_TYPE(   BYTES,    Bytes,  *string_value);
        HANDLE_TYPE(    ENUM,     Enum,     enum_value);
        HANDLE_TYPE(   GROUP,    Group, *message_value);
  #undef HANDLE_TYPE
        case FieldDescriptor::TYPE_MESSAGE:
          if (is_lazy) {
            target = lazymessage_value->WriteMessageToArray(number, target);
          } else {
            target = WireFormatLite::WriteMessageToArray(
                number, *message_value, target);
          }
          break;
      }
    }
    return target;
  }
  
  uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray(
      int number,
      uint8* target) const {
    if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
      // Not a valid MessageSet extension, but serialize it the normal way.
      GOOGLE_LOG(WARNING) << "Invalid message set extension.";
      return SerializeFieldWithCachedSizesToArray(number, target);
    }
  
    if (is_cleared) return target;
  
    // Start group.
    target = io::CodedOutputStream::WriteTagToArray(
        WireFormatLite::kMessageSetItemStartTag, target);
    // Write type ID.
    target = WireFormatLite::WriteUInt32ToArray(
        WireFormatLite::kMessageSetTypeIdNumber, number, target);
    // Write message.
    if (is_lazy) {
      target = lazymessage_value->WriteMessageToArray(
          WireFormatLite::kMessageSetMessageNumber, target);
    } else {
      target = WireFormatLite::WriteMessageToArray(
          WireFormatLite::kMessageSetMessageNumber, *message_value, target);
    }
    // End group.
    target = io::CodedOutputStream::WriteTagToArray(
        WireFormatLite::kMessageSetItemEndTag, target);
    return target;
  }
  
  
  bool ExtensionSet::ParseFieldMaybeLazily(
      int wire_type, int field_number, io::CodedInputStream* input,
      ExtensionFinder* extension_finder,
      MessageSetFieldSkipper* field_skipper) {
    return ParseField(WireFormatLite::MakeTag(
        field_number, static_cast<WireFormatLite::WireType>(wire_type)),
                      input, extension_finder, field_skipper);
  }
  
  bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
                                     ExtensionFinder* extension_finder,
                                     MessageSetFieldSkipper* field_skipper) {
    while (true) {
      const uint32 tag = input->ReadTag();
      switch (tag) {
        case 0:
          return true;
        case WireFormatLite::kMessageSetItemStartTag:
          if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
            return false;
          }
          break;
        default:
          if (!ParseField(tag, input, extension_finder, field_skipper)) {
            return false;
          }
          break;
      }
    }
  }
  
  bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
                                     const MessageLite* containing_type) {
    MessageSetFieldSkipper skipper(NULL);
    GeneratedExtensionFinder finder(containing_type);
    return ParseMessageSet(input, &finder, &skipper);
  }
  
  bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
                                         ExtensionFinder* extension_finder,
                                         MessageSetFieldSkipper* field_skipper) {
    // TODO(kenton):  It would be nice to share code between this and
    // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
    // differences would be hard to factor out.
  
    // This method parses a group which should contain two fields:
    //   required int32 type_id = 2;
    //   required data message = 3;
  
    uint32 last_type_id = 0;
  
    // If we see message data before the type_id, we'll append it to this so
    // we can parse it later.
    string message_data;
  
    while (true) {
      const uint32 tag = input->ReadTag();
      if (tag == 0) return false;
  
      switch (tag) {
        case WireFormatLite::kMessageSetTypeIdTag: {
          uint32 type_id;
          if (!input->ReadVarint32(&type_id)) return false;
          last_type_id = type_id;
  
          if (!message_data.empty()) {
            // We saw some message data before the type_id.  Have to parse it
            // now.
            io::CodedInputStream sub_input(
                reinterpret_cast<const uint8*>(message_data.data()),
                message_data.size());
            if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
                                       last_type_id, &sub_input,
                                       extension_finder, field_skipper)) {
              return false;
            }
            message_data.clear();
          }
  
          break;
        }
  
        case WireFormatLite::kMessageSetMessageTag: {
          if (last_type_id == 0) {
            // We haven't seen a type_id yet.  Append this data to message_data.
            string temp;
            uint32 length;
            if (!input->ReadVarint32(&length)) return false;
            if (!input->ReadString(&temp, length)) return false;
            io::StringOutputStream output_stream(&message_data);
            io::CodedOutputStream coded_output(&output_stream);
            coded_output.WriteVarint32(length);
            coded_output.WriteString(temp);
          } else {
            // Already saw type_id, so we can parse this directly.
            if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
                                       last_type_id, input,
                                       extension_finder, field_skipper)) {
              return false;
            }
          }
  
          break;
        }
  
        case WireFormatLite::kMessageSetItemEndTag: {
          return true;
        }
  
        default: {
          if (!field_skipper->SkipField(input, tag)) return false;
        }
      }
    }
  }
  
  void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
      int number,
      io::CodedOutputStream* output) const {
    if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
      // Not a valid MessageSet extension, but serialize it the normal way.
      SerializeFieldWithCachedSizes(number, output);
      return;
    }
  
    if (is_cleared) return;
  
    // Start group.
    output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
  
    // Write type ID.
    WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
                                number,
                                output);
    // Write message.
    if (is_lazy) {
      lazymessage_value->WriteMessage(
          WireFormatLite::kMessageSetMessageNumber, output);
    } else {
      WireFormatLite::WriteMessageMaybeToArray(
          WireFormatLite::kMessageSetMessageNumber,
          *message_value,
          output);
    }
  
    // End group.
    output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
  }
  
  int ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
    if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
      // Not a valid MessageSet extension, but compute the byte size for it the
      // normal way.
      return ByteSize(number);
    }
  
    if (is_cleared) return 0;
  
    int our_size = WireFormatLite::kMessageSetItemTagsSize;
  
    // type_id
    our_size += io::CodedOutputStream::VarintSize32(number);
  
    // message
    int message_size = 0;
    if (is_lazy) {
      message_size = lazymessage_value->ByteSize();
    } else {
      message_size = message_value->ByteSize();
    }
  
    our_size += io::CodedOutputStream::VarintSize32(message_size);
    our_size += message_size;
  
    return our_size;
  }
  
  void ExtensionSet::SerializeMessageSetWithCachedSizes(
      io::CodedOutputStream* output) const {
    for (map<int, Extension>::const_iterator iter = extensions_.begin();
         iter != extensions_.end(); ++iter) {
      iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
    }
  }
  
  int ExtensionSet::MessageSetByteSize() const {
    int total_size = 0;
  
    for (map<int, Extension>::const_iterator iter = extensions_.begin();
         iter != extensions_.end(); ++iter) {
      total_size += iter->second.MessageSetItemByteSize(iter->first);
    }
  
    return total_size;
  }
  
  }  // namespace internal
  }  // namespace protobuf
  }  // namespace google
  