// 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.

package com.google.protobuf;

import com.google.protobuf.Descriptors.FieldDescriptor;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * Reflection utility methods shared by both mutable and immutable messages.
 *
 * @author liujisi@google.com (Pherl Liu)
 */
class MessageReflection {

  static void writeMessageTo(Message message, CodedOutputStream output,
      boolean alwaysWriteRequiredFields)
      throws IOException {
    final boolean isMessageSet =
        message.getDescriptorForType().getOptions().getMessageSetWireFormat();

    Map<FieldDescriptor, Object> fields = message.getAllFields();
    if (alwaysWriteRequiredFields) {
      fields = new TreeMap<FieldDescriptor, Object>(fields);
      for (final FieldDescriptor field :
          message.getDescriptorForType().getFields()) {
        if (field.isRequired() && !fields.containsKey(field)) {
          fields.put(field, message.getField(field));
        }
      }
    }
    for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
        fields.entrySet()) {
      final Descriptors.FieldDescriptor field = entry.getKey();
      final Object value = entry.getValue();
      if (isMessageSet && field.isExtension() &&
          field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
          !field.isRepeated()) {
        output.writeMessageSetExtension(field.getNumber(), (Message) value);
      } else {
        FieldSet.writeField(field, value, output);
      }
    }

    final UnknownFieldSet unknownFields = message.getUnknownFields();
    if (isMessageSet) {
      unknownFields.writeAsMessageSetTo(output);
    } else {
      unknownFields.writeTo(output);
    }
  }

  static int getSerializedSize(Message message) {
    int size = 0;
    final boolean isMessageSet =
        message.getDescriptorForType().getOptions().getMessageSetWireFormat();

    for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
        message.getAllFields().entrySet()) {
      final Descriptors.FieldDescriptor field = entry.getKey();
      final Object value = entry.getValue();
      if (isMessageSet && field.isExtension() &&
          field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
          !field.isRepeated()) {
        size += CodedOutputStream.computeMessageSetExtensionSize(
            field.getNumber(), (Message) value);
      } else {
        size += FieldSet.computeFieldSize(field, value);
      }
    }

    final UnknownFieldSet unknownFields = message.getUnknownFields();
    if (isMessageSet) {
      size += unknownFields.getSerializedSizeAsMessageSet();
    } else {
      size += unknownFields.getSerializedSize();
    }
    return size;
  }

  static String delimitWithCommas(List<String> parts) {
    StringBuilder result = new StringBuilder();
    for (String part : parts) {
      if (result.length() > 0) {
        result.append(", ");
      }
      result.append(part);
    }
    return result.toString();
  }

  @SuppressWarnings("unchecked")
  static boolean isInitialized(MessageOrBuilder message) {
    // Check that all required fields are present.
    for (final Descriptors.FieldDescriptor field : message
        .getDescriptorForType()
        .getFields()) {
      if (field.isRequired()) {
        if (!message.hasField(field)) {
          return false;
        }
      }
    }

    // Check that embedded messages are initialized.
    for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
        message.getAllFields().entrySet()) {
      final Descriptors.FieldDescriptor field = entry.getKey();
      if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
        if (field.isRepeated()) {
          for (final Message element
              : (List<Message>) entry.getValue()) {
            if (!element.isInitialized()) {
              return false;
            }
          }
        } else {
          if (!((Message) entry.getValue()).isInitialized()) {
            return false;
          }
        }
      }
    }

    return true;
  }

  private static String subMessagePrefix(final String prefix,
      final Descriptors.FieldDescriptor field,
      final int index) {
    final StringBuilder result = new StringBuilder(prefix);
    if (field.isExtension()) {
      result.append('(')
          .append(field.getFullName())
          .append(')');
    } else {
      result.append(field.getName());
    }
    if (index != -1) {
      result.append('[')
          .append(index)
          .append(']');
    }
    result.append('.');
    return result.toString();
  }

  private static void findMissingFields(final MessageOrBuilder message,
      final String prefix,
      final List<String> results) {
    for (final Descriptors.FieldDescriptor field :
        message.getDescriptorForType().getFields()) {
      if (field.isRequired() && !message.hasField(field)) {
        results.add(prefix + field.getName());
      }
    }

    for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
        message.getAllFields().entrySet()) {
      final Descriptors.FieldDescriptor field = entry.getKey();
      final Object value = entry.getValue();

      if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
        if (field.isRepeated()) {
          int i = 0;
          for (final Object element : (List) value) {
            findMissingFields((MessageOrBuilder) element,
                subMessagePrefix(prefix, field, i++),
                results);
          }
        } else {
          if (message.hasField(field)) {
            findMissingFields((MessageOrBuilder) value,
                subMessagePrefix(prefix, field, -1),
                results);
          }
        }
      }
    }
  }

  /**
   * Populates {@code this.missingFields} with the full "path" of each missing
   * required field in the given message.
   */
  static List<String> findMissingFields(
      final MessageOrBuilder message) {
    final List<String> results = new ArrayList<String>();
    findMissingFields(message, "", results);
    return results;
  }

  static interface MergeTarget {
    enum ContainerType {
      MESSAGE, EXTENSION_SET
    }

    /**
     * Returns the descriptor for the target.
     */
    public Descriptors.Descriptor getDescriptorForType();

    public ContainerType getContainerType();

    public ExtensionRegistry.ExtensionInfo findExtensionByName(
        ExtensionRegistry registry, String name);

    public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
        ExtensionRegistry registry, Descriptors.Descriptor containingType,
        int fieldNumber);

    /**
     * Obtains the value of the given field, or the default value if it is not
     * set.  For primitive fields, the boxed primitive value is returned. For
     * enum fields, the EnumValueDescriptor for the value is returned. For
     * embedded message fields, the sub-message is returned.  For repeated
     * fields, a java.util.List is returned.
     */
    public Object getField(Descriptors.FieldDescriptor field);

    /**
     * Returns true if the given field is set.  This is exactly equivalent to
     * calling the generated "has" accessor method corresponding to the field.
     *
     * @throws IllegalArgumentException The field is a repeated field, or {@code
     *     field.getContainingType() != getDescriptorForType()}.
     */
    boolean hasField(Descriptors.FieldDescriptor field);

    /**
     * Sets a field to the given value.  The value must be of the correct type
     * for this field, i.e. the same type that
     * {@link Message#getField(Descriptors.FieldDescriptor)}
     * would return.
     */
    MergeTarget setField(Descriptors.FieldDescriptor field, Object value);

    /**
     * Clears the field.  This is exactly equivalent to calling the generated
     * "clear" accessor method corresponding to the field.
     */
    MergeTarget clearField(Descriptors.FieldDescriptor field);

    /**
     * Sets an element of a repeated field to the given value.  The value must
     * be of the correct type for this field, i.e. the same type that {@link
     * Message#getRepeatedField(Descriptors.FieldDescriptor, int)} would return.
     *
     * @throws IllegalArgumentException The field is not a repeated field, or
     *                                  {@code field.getContainingType() !=
     *                                  getDescriptorForType()}.
     */
    MergeTarget setRepeatedField(Descriptors.FieldDescriptor field,
        int index, Object value);

    /**
     * Like {@code setRepeatedField}, but appends the value as a new element.
     *
     * @throws IllegalArgumentException The field is not a repeated field, or
     *                                  {@code field.getContainingType() !=
     *                                  getDescriptorForType()}.
     */
    MergeTarget addRepeatedField(Descriptors.FieldDescriptor field,
        Object value);

    /**
     * Returns true if the given oneof is set.
     *
     * @throws IllegalArgumentException if
     *           {@code oneof.getContainingType() != getDescriptorForType()}.
     */
    boolean hasOneof(Descriptors.OneofDescriptor oneof);

    /**
     * Clears the oneof.  This is exactly equivalent to calling the generated
     * "clear" accessor method corresponding to the oneof.
     */
    MergeTarget clearOneof(Descriptors.OneofDescriptor oneof);

    /**
     * Obtains the FieldDescriptor if the given oneof is set. Returns null
     * if no field is set.
     */
    Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof);

    /**
     * Parse the input stream into a sub field group defined based on either
     * FieldDescriptor or the default instance.
     */
    Object parseGroup(CodedInputStream input, ExtensionRegistryLite registry,
        Descriptors.FieldDescriptor descriptor, Message defaultInstance)
        throws IOException;

    /**
     * Parse the input stream into a sub field message defined based on either
     * FieldDescriptor or the default instance.
     */
    Object parseMessage(CodedInputStream input, ExtensionRegistryLite registry,
        Descriptors.FieldDescriptor descriptor, Message defaultInstance)
        throws IOException;

    /**
     * Parse from a ByteString into a sub field message defined based on either
     * FieldDescriptor or the default instance.  There isn't a varint indicating
     * the length of the message at the beginning of the input ByteString.
     */
    Object parseMessageFromBytes(
        ByteString bytes, ExtensionRegistryLite registry,
        Descriptors.FieldDescriptor descriptor, Message defaultInstance)
        throws IOException;
    
    /**
     * Read a primitive field from input. Note that builders and mutable
     * messages may use different Java types to represent a primtive field.
     */
    Object readPrimitiveField(
        CodedInputStream input, WireFormat.FieldType type,
        boolean checkUtf8) throws IOException;

    /**
     * Returns a new merge target for a sub-field. When defaultInstance is
     * provided, it indicates the descriptor is for an extension type, and
     * implementations should create a new instance from the defaultInstance
     * prototype directly.
     */
    MergeTarget newMergeTargetForField(
        Descriptors.FieldDescriptor descriptor,
        Message defaultInstance);

    /**
     * Finishes the merge and returns the underlying object.
     */
    Object finish();
  }

  static class BuilderAdapter implements MergeTarget {

    private final Message.Builder builder;

    public Descriptors.Descriptor getDescriptorForType() {
      return builder.getDescriptorForType();
    }

    public BuilderAdapter(Message.Builder builder) {
      this.builder = builder;
    }

    public Object getField(Descriptors.FieldDescriptor field) {
      return builder.getField(field);
    }

    @Override
    public boolean hasField(Descriptors.FieldDescriptor field) {
      return builder.hasField(field);
    }

    public MergeTarget setField(Descriptors.FieldDescriptor field,
        Object value) {
      builder.setField(field, value);
      return this;
    }

    public MergeTarget clearField(Descriptors.FieldDescriptor field) {
      builder.clearField(field);
      return this;
    }

    public MergeTarget setRepeatedField(
        Descriptors.FieldDescriptor field, int index, Object value) {
      builder.setRepeatedField(field, index, value);
      return this;
    }

    public MergeTarget addRepeatedField(
        Descriptors.FieldDescriptor field, Object value) {
      builder.addRepeatedField(field, value);
      return this;
    }

    @Override
    public boolean hasOneof(Descriptors.OneofDescriptor oneof) {
      return builder.hasOneof(oneof);
    }

    @Override
    public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) {
      builder.clearOneof(oneof);
      return this;
    }

    @Override
    public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) {
      return builder.getOneofFieldDescriptor(oneof);
    }

    public ContainerType getContainerType() {
      return ContainerType.MESSAGE;
    }

    public ExtensionRegistry.ExtensionInfo findExtensionByName(
        ExtensionRegistry registry, String name) {
      return registry.findImmutableExtensionByName(name);
    }

    public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
        ExtensionRegistry registry, Descriptors.Descriptor containingType,
        int fieldNumber) {
      return registry.findImmutableExtensionByNumber(containingType,
          fieldNumber);
    }

    public Object parseGroup(CodedInputStream input,
        ExtensionRegistryLite extensionRegistry,
        Descriptors.FieldDescriptor field, Message defaultInstance)
        throws IOException {
      Message.Builder subBuilder;
      // When default instance is not null. The field is an extension field.
      if (defaultInstance != null) {
        subBuilder = defaultInstance.newBuilderForType();
      } else {
        subBuilder = builder.newBuilderForField(field);
      }
      if (!field.isRepeated()) {
        Message originalMessage = (Message) getField(field);
        if (originalMessage != null) {
          subBuilder.mergeFrom(originalMessage);
        }
      }
      input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
      return subBuilder.buildPartial();
    }

    public Object parseMessage(CodedInputStream input,
        ExtensionRegistryLite extensionRegistry,
        Descriptors.FieldDescriptor field, Message defaultInstance)
        throws IOException {
      Message.Builder subBuilder;
      // When default instance is not null. The field is an extension field.
      if (defaultInstance != null) {
        subBuilder = defaultInstance.newBuilderForType();
      } else {
        subBuilder = builder.newBuilderForField(field);
      }
      if (!field.isRepeated()) {
        Message originalMessage = (Message) getField(field);
        if (originalMessage != null) {
          subBuilder.mergeFrom(originalMessage);
        }
      }
      input.readMessage(subBuilder, extensionRegistry);
      return subBuilder.buildPartial();
    }

    public Object parseMessageFromBytes(ByteString bytes,
        ExtensionRegistryLite extensionRegistry,
        Descriptors.FieldDescriptor field, Message defaultInstance)
        throws IOException {
      Message.Builder subBuilder;
      // When default instance is not null. The field is an extension field.
      if (defaultInstance != null) {
        subBuilder = defaultInstance.newBuilderForType();
      } else {
        subBuilder = builder.newBuilderForField(field);
      }
      if (!field.isRepeated()) {
        Message originalMessage = (Message) getField(field);
        if (originalMessage != null) {
          subBuilder.mergeFrom(originalMessage);
        }
      }
      subBuilder.mergeFrom(bytes, extensionRegistry);
      return subBuilder.buildPartial();
    }

    public MergeTarget newMergeTargetForField(Descriptors.FieldDescriptor field,
        Message defaultInstance) {
      if (defaultInstance != null) {
        return new BuilderAdapter(
            defaultInstance.newBuilderForType());
      } else {
        return new BuilderAdapter(builder.newBuilderForField(field));
      }
    }
    
    public Object readPrimitiveField(
        CodedInputStream input, WireFormat.FieldType type,
        boolean checkUtf8) throws IOException {
      return FieldSet.readPrimitiveField(input, type, checkUtf8);
    }

    public Object finish() {
      return builder.buildPartial();
    }
  }


  static class ExtensionAdapter implements MergeTarget {

    private final FieldSet<Descriptors.FieldDescriptor> extensions;

    ExtensionAdapter(FieldSet<Descriptors.FieldDescriptor> extensions) {
      this.extensions = extensions;
    }

    public Descriptors.Descriptor getDescriptorForType() {
      throw new UnsupportedOperationException(
          "getDescriptorForType() called on FieldSet object");
    }

    public Object getField(Descriptors.FieldDescriptor field) {
      return extensions.getField(field);
    }

    public boolean hasField(Descriptors.FieldDescriptor field) {
      return extensions.hasField(field);
    }

    public MergeTarget setField(Descriptors.FieldDescriptor field,
        Object value) {
      extensions.setField(field, value);
      return this;
    }

    public MergeTarget clearField(Descriptors.FieldDescriptor field) {
      extensions.clearField(field);
      return this;
    }

    public MergeTarget setRepeatedField(
        Descriptors.FieldDescriptor field, int index, Object value) {
      extensions.setRepeatedField(field, index, value);
      return this;
    }

    public MergeTarget addRepeatedField(
        Descriptors.FieldDescriptor field, Object value) {
      extensions.addRepeatedField(field, value);
      return this;
    }

    @Override
    public boolean hasOneof(Descriptors.OneofDescriptor oneof) {
      return false;
    }

    @Override
    public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) {
      // Nothing to clear.
      return this;
    }

    @Override
    public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) {
      return null;
    }

    public ContainerType getContainerType() {
      return ContainerType.EXTENSION_SET;
    }

    public ExtensionRegistry.ExtensionInfo findExtensionByName(
        ExtensionRegistry registry, String name) {
      return registry.findImmutableExtensionByName(name);
    }

    public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
        ExtensionRegistry registry, Descriptors.Descriptor containingType,
        int fieldNumber) {
      return registry.findImmutableExtensionByNumber(containingType,
          fieldNumber);
    }

    public Object parseGroup(CodedInputStream input,
        ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
        Message defaultInstance) throws IOException {
      Message.Builder subBuilder =
          defaultInstance.newBuilderForType();
      if (!field.isRepeated()) {
        Message originalMessage = (Message) getField(field);
        if (originalMessage != null) {
          subBuilder.mergeFrom(originalMessage);
        }
      }
      input.readGroup(field.getNumber(), subBuilder, registry);
      return subBuilder.buildPartial();
    }

    public Object parseMessage(CodedInputStream input,
        ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
        Message defaultInstance) throws IOException {
      Message.Builder subBuilder =
          defaultInstance.newBuilderForType();
      if (!field.isRepeated()) {
        Message originalMessage = (Message) getField(field);
        if (originalMessage != null) {
          subBuilder.mergeFrom(originalMessage);
        }
      }
      input.readMessage(subBuilder, registry);
      return subBuilder.buildPartial();
    }

    public Object parseMessageFromBytes(ByteString bytes,
        ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
        Message defaultInstance) throws IOException {
      Message.Builder subBuilder =  defaultInstance.newBuilderForType();
      if (!field.isRepeated()) {
        Message originalMessage = (Message) getField(field);
        if (originalMessage != null) {
          subBuilder.mergeFrom(originalMessage);
        }
      }
      subBuilder.mergeFrom(bytes, registry);
      return subBuilder.buildPartial();
    }

    public MergeTarget newMergeTargetForField(
        Descriptors.FieldDescriptor descriptor, Message defaultInstance) {
      throw new UnsupportedOperationException(
          "newMergeTargetForField() called on FieldSet object");
    }
    
    public Object readPrimitiveField(
        CodedInputStream input, WireFormat.FieldType type,
        boolean checkUtf8) throws IOException {
      return FieldSet.readPrimitiveField(input, type, checkUtf8);
    }

    public Object finish() {
      throw new UnsupportedOperationException(
          "finish() called on FieldSet object");
    }
  }

  /**
   * Parses a single field into MergeTarget. The target can be Message.Builder,
   * FieldSet or MutableMessage.
   *
   * Package-private because it is used by GeneratedMessage.ExtendableMessage.
   *
   * @param tag The tag, which should have already been read.
   * @return {@code true} unless the tag is an end-group tag.
   */
  static boolean mergeFieldFrom(
      CodedInputStream input,
      UnknownFieldSet.Builder unknownFields,
      ExtensionRegistryLite extensionRegistry,
      Descriptors.Descriptor type,
      MergeTarget target,
      int tag) throws IOException {
    if (type.getOptions().getMessageSetWireFormat() &&
        tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
      mergeMessageSetExtensionFromCodedStream(
          input, unknownFields, extensionRegistry, type, target);
      return true;
    }

    final int wireType = WireFormat.getTagWireType(tag);
    final int fieldNumber = WireFormat.getTagFieldNumber(tag);

    final Descriptors.FieldDescriptor field;
    Message defaultInstance = null;

    if (type.isExtensionNumber(fieldNumber)) {
      // extensionRegistry may be either ExtensionRegistry or
      // ExtensionRegistryLite.  Since the type we are parsing is a full
      // message, only a full ExtensionRegistry could possibly contain
      // extensions of it.  Otherwise we will treat the registry as if it
      // were empty.
      if (extensionRegistry instanceof ExtensionRegistry) {
        final ExtensionRegistry.ExtensionInfo extension =
            target.findExtensionByNumber((ExtensionRegistry) extensionRegistry,
                type, fieldNumber);
        if (extension == null) {
          field = null;
        } else {
          field = extension.descriptor;
          defaultInstance = extension.defaultInstance;
          if (defaultInstance == null &&
              field.getJavaType()
                  == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
            throw new IllegalStateException(
                "Message-typed extension lacked default instance: " +
                    field.getFullName());
          }
        }
      } else {
        field = null;
      }
    } else if (target.getContainerType() == MergeTarget.ContainerType.MESSAGE) {
      field = type.findFieldByNumber(fieldNumber);
    } else {
      field = null;
    }

    boolean unknown = false;
    boolean packed = false;
    if (field == null) {
      unknown = true;  // Unknown field.
    } else if (wireType == FieldSet.getWireFormatForFieldType(
        field.getLiteType(),
        false  /* isPacked */)) {
      packed = false;
    } else if (field.isPackable() &&
        wireType == FieldSet.getWireFormatForFieldType(
            field.getLiteType(),
            true  /* isPacked */)) {
      packed = true;
    } else {
      unknown = true;  // Unknown wire type.
    }

    if (unknown) {  // Unknown field or wrong wire type.  Skip.
      return unknownFields.mergeFieldFrom(tag, input);
    }

    if (packed) {
      final int length = input.readRawVarint32();
      final int limit = input.pushLimit(length);
      if (field.getLiteType() == WireFormat.FieldType.ENUM) {
        while (input.getBytesUntilLimit() > 0) {
          final int rawValue = input.readEnum();
          final Object value = field.getEnumType().findValueByNumber(rawValue);
          if (value == null) {
            // If the number isn't recognized as a valid value for this
            // enum, drop it (don't even add it to unknownFields).
            return true;
          }
          target.addRepeatedField(field, value);
        }
      } else {
        while (input.getBytesUntilLimit() > 0) {
          final Object value =
              target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check());
          target.addRepeatedField(field, value);
        }
      }
      input.popLimit(limit);
    } else {
      final Object value;
      switch (field.getType()) {
        case GROUP: {
          value = target
              .parseGroup(input, extensionRegistry, field, defaultInstance);
          break;
        }
        case MESSAGE: {
          value = target
              .parseMessage(input, extensionRegistry, field, defaultInstance);
          break;
        }
        case ENUM:
          final int rawValue = input.readEnum();
          value = field.getEnumType().findValueByNumber(rawValue);
          // If the number isn't recognized as a valid value for this enum,
          // drop it.
          if (value == null) {
            unknownFields.mergeVarintField(fieldNumber, rawValue);
            return true;
          }
          break;
        default:
          value = target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check());
          break;
      }

      if (field.isRepeated()) {
        target.addRepeatedField(field, value);
      } else {
        target.setField(field, value);
      }
    }

    return true;
  }

  /**
   * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension into
   * MergeTarget.
   */
  private static void mergeMessageSetExtensionFromCodedStream(
      CodedInputStream input,
      UnknownFieldSet.Builder unknownFields,
      ExtensionRegistryLite extensionRegistry,
      Descriptors.Descriptor type,
      MergeTarget target) throws IOException {

    // The wire format for MessageSet is:
    //   message MessageSet {
    //     repeated group Item = 1 {
    //       required int32 typeId = 2;
    //       required bytes message = 3;
    //     }
    //   }
    // "typeId" is the extension's field number.  The extension can only be
    // a message type, where "message" contains the encoded bytes of that
    // message.
    //
    // In practice, we will probably never see a MessageSet item in which
    // the message appears before the type ID, or where either field does not
    // appear exactly once.  However, in theory such cases are valid, so we
    // should be prepared to accept them.

    int typeId = 0;
    ByteString rawBytes = null; // If we encounter "message" before "typeId"
    ExtensionRegistry.ExtensionInfo extension = null;

    // Read bytes from input, if we get it's type first then parse it eagerly,
    // otherwise we store the raw bytes in a local variable.
    while (true) {
      final int tag = input.readTag();
      if (tag == 0) {
        break;
      }

      if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
        typeId = input.readUInt32();
        if (typeId != 0) {
          // extensionRegistry may be either ExtensionRegistry or
          // ExtensionRegistryLite. Since the type we are parsing is a full
          // message, only a full ExtensionRegistry could possibly contain
          // extensions of it. Otherwise we will treat the registry as if it
          // were empty.
          if (extensionRegistry instanceof ExtensionRegistry) {
            extension = target.findExtensionByNumber(
                (ExtensionRegistry) extensionRegistry, type, typeId);
          }
        }

      } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
        if (typeId != 0) {
          if (extension != null &&
              ExtensionRegistryLite.isEagerlyParseMessageSets()) {
            // We already know the type, so we can parse directly from the
            // input with no copying.  Hooray!
            eagerlyMergeMessageSetExtension(
                input, extension, extensionRegistry, target);
            rawBytes = null;
            continue;
          }
        }
        // We haven't seen a type ID yet or we want parse message lazily.
        rawBytes = input.readBytes();

      } else { // Unknown tag. Skip it.
        if (!input.skipField(tag)) {
          break; // End of group
        }
      }
    }
    input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);

    // Process the raw bytes.
    if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID.
      if (extension != null) { // We known the type
        mergeMessageSetExtensionFromBytes(
            rawBytes, extension, extensionRegistry, target);
      } else { // We don't know how to parse this. Ignore it.
        if (rawBytes != null) {
          unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder()
              .addLengthDelimited(rawBytes).build());
        }
      }
    }
  }

  private static void mergeMessageSetExtensionFromBytes(
      ByteString rawBytes,
      ExtensionRegistry.ExtensionInfo extension,
      ExtensionRegistryLite extensionRegistry,
      MergeTarget target) throws IOException {

    Descriptors.FieldDescriptor field = extension.descriptor;
    boolean hasOriginalValue = target.hasField(field);

    if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) {
      // If the field already exists, we just parse the field.
      Object value = target.parseMessageFromBytes(
          rawBytes, extensionRegistry,field, extension.defaultInstance);
      target.setField(field, value);
    } else {
      // Use LazyField to load MessageSet lazily.
      LazyField lazyField = new LazyField(
          extension.defaultInstance, extensionRegistry, rawBytes);
      target.setField(field, lazyField);
    }
  }

  private static void eagerlyMergeMessageSetExtension(
      CodedInputStream input,
      ExtensionRegistry.ExtensionInfo extension,
      ExtensionRegistryLite extensionRegistry,
      MergeTarget target) throws IOException {
    Descriptors.FieldDescriptor field = extension.descriptor;
    Object value = target.parseMessage(input, extensionRegistry, field,
                                       extension.defaultInstance);
    target.setField(field, value);
  }
}
