// 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.AbstractMessageLite.Builder.LimitedInputStream;
import com.google.protobuf.Internal.BooleanList;
import com.google.protobuf.Internal.DoubleList;
import com.google.protobuf.Internal.FloatList;
import com.google.protobuf.Internal.IntList;
import com.google.protobuf.Internal.LongList;
import com.google.protobuf.Internal.ProtobufList;
import com.google.protobuf.WireFormat.FieldType;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Lite version of {@link GeneratedMessage}.
 *
 * @author kenton@google.com Kenton Varda
 */
public abstract class GeneratedMessageLite<
        MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
        BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>>
    extends AbstractMessageLite<MessageType, BuilderType> {

  /** For use by generated code only. Lazily initialized to reduce allocations. */
  protected UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();

  /** For use by generated code only. */
  protected int memoizedSerializedSize = -1;

  @Override
  @SuppressWarnings("unchecked") // Guaranteed by runtime.
  public final Parser<MessageType> getParserForType() {
    return (Parser<MessageType>) dynamicMethod(MethodToInvoke.GET_PARSER);
  }

  @Override
  @SuppressWarnings("unchecked") // Guaranteed by runtime.
  public final MessageType getDefaultInstanceForType() {
    return (MessageType) dynamicMethod(MethodToInvoke.GET_DEFAULT_INSTANCE);
  }

  @Override
  @SuppressWarnings("unchecked") // Guaranteed by runtime.
  public final BuilderType newBuilderForType() {
    return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
  }

  /**
   * A reflective toString function. This is primarily intended as a developer aid, while keeping
   * binary size down. The first line of the {@code toString()} representation includes a commented
   * version of {@code super.toString()} to act as an indicator that this should not be relied on
   * for comparisons.
   *
   * <p>NOTE: This method relies on the field getter methods not being stripped or renamed by
   * proguard. If they are, the fields will not be included in the returned string representation.
   *
   * <p>NOTE: This implementation is liable to change in the future, and should not be relied on in
   * code.
   */
  @Override
  public String toString() {
    return MessageLiteToString.toString(this, super.toString());
  }

  @SuppressWarnings("unchecked") // Guaranteed by runtime
  @Override
  public int hashCode() {
    if (memoizedHashCode != 0) {
      return memoizedHashCode;
    }
    memoizedHashCode = Protobuf.getInstance().schemaFor(this).hashCode(this);
    return memoizedHashCode;
  }

  @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime
  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }

    if (!getDefaultInstanceForType().getClass().isInstance(other)) {
      return false;
    }

    return Protobuf.getInstance().schemaFor(this).equals(this, (MessageType) other);
  }

  // The general strategy for unknown fields is to use an UnknownFieldSetLite that is treated as
  // mutable during the parsing constructor and immutable after. This allows us to avoid
  // any unnecessary intermediary allocations while reducing the generated code size.

  /** Lazily initializes unknown fields. */
  private final void ensureUnknownFieldsInitialized() {
    if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
      unknownFields = UnknownFieldSetLite.newInstance();
    }
  }

  /**
   * Called by subclasses to parse an unknown field. For use by generated code only.
   *
   * @return {@code true} unless the tag is an end-group tag.
   */
  protected boolean parseUnknownField(int tag, CodedInputStream input) throws IOException {
    // This will avoid the allocation of unknown fields when a group tag is encountered.
    if (WireFormat.getTagWireType(tag) == WireFormat.WIRETYPE_END_GROUP) {
      return false;
    }

    ensureUnknownFieldsInitialized();
    return unknownFields.mergeFieldFrom(tag, input);
  }

  /** Called by subclasses to parse an unknown field. For use by generated code only. */
  protected void mergeVarintField(int tag, int value) {
    ensureUnknownFieldsInitialized();
    unknownFields.mergeVarintField(tag, value);
  }

  /** Called by subclasses to parse an unknown field. For use by generated code only. */
  protected void mergeLengthDelimitedField(int fieldNumber, ByteString value) {
    ensureUnknownFieldsInitialized();
    unknownFields.mergeLengthDelimitedField(fieldNumber, value);
  }

  /** Called by subclasses to complete parsing. For use by generated code only. */
  protected void makeImmutable() {
    Protobuf.getInstance().schemaFor(this).makeImmutable(this);
  }

  protected final <
          MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
          BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>>
      BuilderType createBuilder() {
    return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
  }

  protected final <
          MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
          BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>>
      BuilderType createBuilder(MessageType prototype) {
    return ((BuilderType) createBuilder()).mergeFrom(prototype);
  }

  @Override
  public final boolean isInitialized() {
    return isInitialized((MessageType) this, Boolean.TRUE);
  }

  @Override
  @SuppressWarnings("unchecked")
  public final BuilderType toBuilder() {
    BuilderType builder = (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
    builder.mergeFrom((MessageType) this);
    return builder;
  }

  /**
   * Defines which method path to invoke in {@link GeneratedMessageLite
   * #dynamicMethod(MethodToInvoke, Object...)}.
   *
   * <p>For use by generated code only.
   */
  public static enum MethodToInvoke {
    // Rely on/modify instance state
    GET_MEMOIZED_IS_INITIALIZED,
    SET_MEMOIZED_IS_INITIALIZED,

    // Rely on static state
    BUILD_MESSAGE_INFO,
    NEW_MUTABLE_INSTANCE,
    NEW_BUILDER,
    GET_DEFAULT_INSTANCE,
    GET_PARSER;
  }

  /**
   * A method that implements different types of operations described in {@link MethodToInvoke}.
   * Theses different kinds of operations are required to implement message-level operations for
   * builders in the runtime. This method bundles those operations to reduce the generated methods
   * count.
   *
   * <ul>
   *   <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer that has not yet been
   *       made immutable. See {@code MAKE_IMMUTABLE}.
   *   <li>{@code IS_INITIALIZED} returns {@code null} for false and the default instance for true.
   *       It doesn't use or modify any memoized value.
   *   <li>{@code GET_MEMOIZED_IS_INITIALIZED} returns the memoized {@code isInitialized} byte
   *       value.
   *   <li>{@code SET_MEMOIZED_IS_INITIALIZED} sets the memoized {@code isInitilaized} byte value to
   *       1 if the first parameter is not null, or to 0 if the first parameter is null.
   *   <li>{@code NEW_BUILDER} returns a {@code BuilderType} instance.
   * </ul>
   *
   * This method, plus the implementation of the Builder, enables the Builder class to be proguarded
   * away entirely on Android.
   *
   * <p>For use by generated code only.
   */
  protected abstract Object dynamicMethod(MethodToInvoke method, Object arg0, Object arg1);

  /** Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding. */
  protected Object dynamicMethod(MethodToInvoke method, Object arg0) {
    return dynamicMethod(method, arg0, null);
  }

  /** Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding. */
  protected Object dynamicMethod(MethodToInvoke method) {
    return dynamicMethod(method, null, null);
  }

  @Override
  int getMemoizedSerializedSize() {
    return memoizedSerializedSize;
  }

  @Override
  void setMemoizedSerializedSize(int size) {
    memoizedSerializedSize = size;
  }

  public void writeTo(CodedOutputStream output) throws IOException {
    writeToInternal(output);
  }

  public int getSerializedSize() {
    if (memoizedSerializedSize == -1) {
      memoizedSerializedSize = getSerializedSizeInternal();
    }
    return memoizedSerializedSize;
  }

  /** Constructs a {@link MessageInfo} for this message type. */
  Object buildMessageInfo() throws Exception {
    return dynamicMethod(MethodToInvoke.BUILD_MESSAGE_INFO);
  }

  private static Map<Object, GeneratedMessageLite<?, ?>> defaultInstanceMap =
      new ConcurrentHashMap<Object, GeneratedMessageLite<?, ?>>();

  @SuppressWarnings("unchecked")
  static <T extends GeneratedMessageLite<?, ?>> T getDefaultInstance(Class<T> clazz) {
    T result = (T) defaultInstanceMap.get(clazz);
    if (result == null) {
      // Foo.class does not initialize the class so we need to force the initialization in order to
      // get the default instance registered.
      try {
        Class.forName(clazz.getName(), true, clazz.getClassLoader());
      } catch (ClassNotFoundException e) {
        throw new IllegalStateException("Class initialization cannot fail.", e);
      }
      result = (T) defaultInstanceMap.get(clazz);
    }
    if (result == null) {
      // On some Samsung devices, this still doesn't return a valid value for some reason. We add a
      // reflective fallback to keep the device running. See b/114675342.
      result = (T) UnsafeUtil.allocateInstance(clazz).getDefaultInstanceForType();
      // A sanity check to ensure that <clinit> was actually invoked.
      if (result == null) {
        throw new IllegalStateException();
      }
      defaultInstanceMap.put(clazz, result);
    }
    return result;
  }

  protected static <T extends GeneratedMessageLite<?, ?>> void registerDefaultInstance(
      Class<T> clazz, T defaultInstance) {
    defaultInstanceMap.put(clazz, defaultInstance);
  }

  protected static Object newMessageInfo(
      MessageLite defaultInstance, String info, Object[] objects) {
    return new RawMessageInfo(defaultInstance, info, objects);
  }

  /**
   * Merge some unknown fields into the {@link UnknownFieldSetLite} for this message.
   *
   * <p>For use by generated code only.
   */
  protected final void mergeUnknownFields(UnknownFieldSetLite unknownFields) {
    this.unknownFields = UnknownFieldSetLite.mutableCopyOf(this.unknownFields, unknownFields);
  }

  @SuppressWarnings("unchecked")
  public abstract static class Builder<
          MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
          BuilderType extends Builder<MessageType, BuilderType>>
      extends AbstractMessageLite.Builder<MessageType, BuilderType> {

    private final MessageType defaultInstance;
    protected MessageType instance;
    protected boolean isBuilt;

    protected Builder(MessageType defaultInstance) {
      this.defaultInstance = defaultInstance;
      this.instance =
          (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
      isBuilt = false;
    }

    /**
     * Called before any method that would mutate the builder to ensure that it correctly copies any
     * state before the write happens to preserve immutability guarantees.
     */
    protected void copyOnWrite() {
      if (isBuilt) {
        MessageType newInstance =
            (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
        mergeFromInstance(newInstance, instance);
        instance = newInstance;
        isBuilt = false;
      }
    }

    @Override
    public final boolean isInitialized() {
      return GeneratedMessageLite.isInitialized(instance, /* shouldMemoize= */ false);
    }

    @Override
    public final BuilderType clear() {
      // No need to copy on write since we're dropping the instance anyways.
      instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
      return (BuilderType) this;
    }

    @Override
    public BuilderType clone() {
      BuilderType builder = (BuilderType) getDefaultInstanceForType().newBuilderForType();
      builder.mergeFrom(buildPartial());
      return builder;
    }

    @Override
    public MessageType buildPartial() {
      if (isBuilt) {
        return instance;
      }

      instance.makeImmutable();

      isBuilt = true;
      return instance;
    }

    @Override
    public final MessageType build() {
      MessageType result = buildPartial();
      if (!result.isInitialized()) {
        throw newUninitializedMessageException(result);
      }
      return result;
    }

    @Override
    protected BuilderType internalMergeFrom(MessageType message) {
      return mergeFrom(message);
    }

    /** All subclasses implement this. */
    public BuilderType mergeFrom(MessageType message) {
      copyOnWrite();
      mergeFromInstance(instance, message);
      return (BuilderType) this;
    }

    private void mergeFromInstance(MessageType dest, MessageType src) {
      Protobuf.getInstance().schemaFor(dest).mergeFrom(dest, src);
    }

    @Override
    public MessageType getDefaultInstanceForType() {
      return defaultInstance;
    }

    @Override
    public BuilderType mergeFrom(
        byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry)
        throws InvalidProtocolBufferException {
      copyOnWrite();
      try {
        Protobuf.getInstance().schemaFor(instance).mergeFrom(
            instance, input, offset, offset + length,
            new ArrayDecoders.Registers(extensionRegistry));
      } catch (InvalidProtocolBufferException e) {
        throw e;
      } catch (IndexOutOfBoundsException e) {
        throw InvalidProtocolBufferException.truncatedMessage();
      } catch (IOException e) {
        throw new RuntimeException("Reading from byte array should not throw IOException.", e);
      }
      return (BuilderType) this;
    }

    @Override
    public BuilderType mergeFrom(
        byte[] input, int offset, int length)
        throws InvalidProtocolBufferException {
      return mergeFrom(input, offset, length, ExtensionRegistryLite.getEmptyRegistry());
    }

    @Override
    public BuilderType mergeFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws IOException {
      copyOnWrite();
      try {
        // TODO(yilunchong): Try to make input with type CodedInpuStream.ArrayDecoder use
        // fast path.
        Protobuf.getInstance().schemaFor(instance).mergeFrom(
            instance, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
      } catch (RuntimeException e) {
        if (e.getCause() instanceof IOException) {
          throw (IOException) e.getCause();
        }
        throw e;
      }
      return (BuilderType) this;
    }
  }


  // =================================================================
  // Extensions-related stuff

  /** Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}. */
  public interface ExtendableMessageOrBuilder<
          MessageType extends ExtendableMessage<MessageType, BuilderType>,
          BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
      extends MessageLiteOrBuilder {

    /** Check if a singular extension is present. */
    <Type> boolean hasExtension(ExtensionLite<MessageType, Type> extension);

    /** Get the number of elements in a repeated extension. */
    <Type> int getExtensionCount(ExtensionLite<MessageType, List<Type>> extension);

    /** Get the value of an extension. */
    <Type> Type getExtension(ExtensionLite<MessageType, Type> extension);

    /** Get one element of a repeated extension. */
    <Type> Type getExtension(ExtensionLite<MessageType, List<Type>> extension, int index);
  }

  /** Lite equivalent of {@link GeneratedMessage.ExtendableMessage}. */
  public abstract static class ExtendableMessage<
          MessageType extends ExtendableMessage<MessageType, BuilderType>,
          BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
      extends GeneratedMessageLite<MessageType, BuilderType>
      implements ExtendableMessageOrBuilder<MessageType, BuilderType> {

    /** Represents the set of extensions on this message. For use by generated code only. */
    protected FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet();

    @SuppressWarnings("unchecked")
    protected final void mergeExtensionFields(final MessageType other) {
      if (extensions.isImmutable()) {
        extensions = extensions.clone();
      }
      extensions.mergeFrom(((ExtendableMessage) other).extensions);
    }

    /**
     * Parse an unknown field or an extension. For use by generated code only.
     *
     * <p>For use by generated code only.
     *
     * @return {@code true} unless the tag is an end-group tag.
     */
    protected <MessageType extends MessageLite> boolean parseUnknownField(
        MessageType defaultInstance,
        CodedInputStream input,
        ExtensionRegistryLite extensionRegistry,
        int tag)
        throws IOException {
      int fieldNumber = WireFormat.getTagFieldNumber(tag);

      // TODO(dweis): How much bytecode would be saved by not requiring the generated code to
      //     provide the default instance?
      GeneratedExtension<MessageType, ?> extension =
          extensionRegistry.findLiteExtensionByNumber(defaultInstance, fieldNumber);

      return parseExtension(input, extensionRegistry, extension, tag, fieldNumber);
    }

    private boolean parseExtension(
        CodedInputStream input,
        ExtensionRegistryLite extensionRegistry,
        GeneratedExtension<?, ?> extension,
        int tag,
        int fieldNumber)
        throws IOException {
      int wireType = WireFormat.getTagWireType(tag);
      boolean unknown = false;
      boolean packed = false;
      if (extension == null) {
        unknown = true; // Unknown field.
      } else if (wireType
          == FieldSet.getWireFormatForFieldType(
              extension.descriptor.getLiteType(), /* isPacked= */ false)) {
        packed = false; // Normal, unpacked value.
      } else if (extension.descriptor.isRepeated
          && extension.descriptor.type.isPackable()
          && wireType
              == FieldSet.getWireFormatForFieldType(
                  extension.descriptor.getLiteType(), /* isPacked= */ true)) {
        packed = true; // Packed value.
      } else {
        unknown = true; // Wrong wire type.
      }

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

      ensureExtensionsAreMutable();

      if (packed) {
        int length = input.readRawVarint32();
        int limit = input.pushLimit(length);
        if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
          while (input.getBytesUntilLimit() > 0) {
            int rawValue = input.readEnum();
            Object value = extension.descriptor.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;
            }
            extensions.addRepeatedField(
                extension.descriptor, extension.singularToFieldSetType(value));
          }
        } else {
          while (input.getBytesUntilLimit() > 0) {
            Object value =
                FieldSet.readPrimitiveField(
                    input, extension.descriptor.getLiteType(), /*checkUtf8=*/ false);
            extensions.addRepeatedField(extension.descriptor, value);
          }
        }
        input.popLimit(limit);
      } else {
        Object value;
        switch (extension.descriptor.getLiteJavaType()) {
          case MESSAGE:
            {
              MessageLite.Builder subBuilder = null;
              if (!extension.descriptor.isRepeated()) {
                MessageLite existingValue = (MessageLite) extensions.getField(extension.descriptor);
                if (existingValue != null) {
                  subBuilder = existingValue.toBuilder();
                }
              }
              if (subBuilder == null) {
                subBuilder = extension.getMessageDefaultInstance().newBuilderForType();
              }
              if (extension.descriptor.getLiteType() == WireFormat.FieldType.GROUP) {
                input.readGroup(extension.getNumber(), subBuilder, extensionRegistry);
              } else {
                input.readMessage(subBuilder, extensionRegistry);
              }
              value = subBuilder.build();
              break;
            }
          case ENUM:
            int rawValue = input.readEnum();
            value = extension.descriptor.getEnumType().findValueByNumber(rawValue);
            // If the number isn't recognized as a valid value for this enum,
            // write it to unknown fields object.
            if (value == null) {
              mergeVarintField(fieldNumber, rawValue);
              return true;
            }
            break;
          default:
            value =
                FieldSet.readPrimitiveField(
                    input, extension.descriptor.getLiteType(), /*checkUtf8=*/ false);
            break;
        }

        if (extension.descriptor.isRepeated()) {
          extensions.addRepeatedField(
              extension.descriptor, extension.singularToFieldSetType(value));
        } else {
          extensions.setField(extension.descriptor, extension.singularToFieldSetType(value));
        }
      }
      return true;
    }

    /**
     * Parse an unknown field or an extension. For use by generated code only.
     *
     * <p>For use by generated code only.
     *
     * @return {@code true} unless the tag is an end-group tag.
     */
    protected <MessageType extends MessageLite> boolean parseUnknownFieldAsMessageSet(
        MessageType defaultInstance,
        CodedInputStream input,
        ExtensionRegistryLite extensionRegistry,
        int tag)
        throws IOException {

      if (tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
        mergeMessageSetExtensionFromCodedStream(defaultInstance, input, extensionRegistry);
        return true;
      }

      // TODO(dweis): Do we really want to support non message set wire format in message sets?
      // Full runtime does... So we do for now.
      int wireType = WireFormat.getTagWireType(tag);
      if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
        return parseUnknownField(defaultInstance, input, extensionRegistry, tag);
      } else {
        // TODO(dweis): Should we throw on invalid input? Full runtime does not...
        return input.skipField(tag);
      }
    }

    /**
     * Merges the message set from the input stream; requires message set wire format.
     *
     * @param defaultInstance the default instance of the containing message we are parsing in
     * @param input the stream to parse from
     * @param extensionRegistry the registry to use when parsing
     */
    private <MessageType extends MessageLite> void mergeMessageSetExtensionFromCodedStream(
        MessageType defaultInstance,
        CodedInputStream input,
        ExtensionRegistryLite extensionRegistry)
        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"
      GeneratedExtension<?, ?> 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) {
            extension = extensionRegistry.findLiteExtensionByNumber(defaultInstance, typeId);
          }

        } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
          if (typeId != 0) {
            if (extension != null) {
              // We already know the type, so we can parse directly from the
              // input with no copying.  Hooray!
              eagerlyMergeMessageSetExtension(input, extension, extensionRegistry, typeId);
              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, extensionRegistry, extension);
        } else { // We don't know how to parse this. Ignore it.
          if (rawBytes != null) {
            mergeLengthDelimitedField(typeId, rawBytes);
          }
        }
      }
    }

    private void eagerlyMergeMessageSetExtension(
        CodedInputStream input,
        GeneratedExtension<?, ?> extension,
        ExtensionRegistryLite extensionRegistry,
        int typeId)
        throws IOException {
      int fieldNumber = typeId;
      int tag = WireFormat.makeTag(typeId, WireFormat.WIRETYPE_LENGTH_DELIMITED);
      parseExtension(input, extensionRegistry, extension, tag, fieldNumber);
    }

    private void mergeMessageSetExtensionFromBytes(
        ByteString rawBytes,
        ExtensionRegistryLite extensionRegistry,
        GeneratedExtension<?, ?> extension)
        throws IOException {
      MessageLite.Builder subBuilder = null;
      MessageLite existingValue = (MessageLite) extensions.getField(extension.descriptor);
      if (existingValue != null) {
        subBuilder = existingValue.toBuilder();
      }
      if (subBuilder == null) {
        subBuilder = extension.getMessageDefaultInstance().newBuilderForType();
      }
      subBuilder.mergeFrom(rawBytes, extensionRegistry);
      MessageLite value = subBuilder.build();

      ensureExtensionsAreMutable()
          .setField(extension.descriptor, extension.singularToFieldSetType(value));
    }

    FieldSet<ExtensionDescriptor> ensureExtensionsAreMutable() {
      if (extensions.isImmutable()) {
        extensions = extensions.clone();
      }
      return extensions;
    }

    private void verifyExtensionContainingType(final GeneratedExtension<MessageType, ?> extension) {
      if (extension.getContainingTypeDefaultInstance() != getDefaultInstanceForType()) {
        // This can only happen if someone uses unchecked operations.
        throw new IllegalArgumentException(
            "This extension is for a different message type.  Please make "
                + "sure that you are not suppressing any generics type warnings.");
      }
    }

    /** Check if a singular extension is present. */
    @Override
    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) {
      GeneratedExtension<MessageType, Type> extensionLite = checkIsLite(extension);

      verifyExtensionContainingType(extensionLite);
      return extensions.hasField(extensionLite.descriptor);
    }

    /** Get the number of elements in a repeated extension. */
    @Override
    public final <Type> int getExtensionCount(
        final ExtensionLite<MessageType, List<Type>> extension) {
      GeneratedExtension<MessageType, List<Type>> extensionLite = checkIsLite(extension);

      verifyExtensionContainingType(extensionLite);
      return extensions.getRepeatedFieldCount(extensionLite.descriptor);
    }

    /** Get the value of an extension. */
    @Override
    @SuppressWarnings("unchecked")
    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) {
      GeneratedExtension<MessageType, Type> extensionLite = checkIsLite(extension);

      verifyExtensionContainingType(extensionLite);
      final Object value = extensions.getField(extensionLite.descriptor);
      if (value == null) {
        return extensionLite.defaultValue;
      } else {
        return (Type) extensionLite.fromFieldSetType(value);
      }
    }

    /** Get one element of a repeated extension. */
    @Override
    @SuppressWarnings("unchecked")
    public final <Type> Type getExtension(
        final ExtensionLite<MessageType, List<Type>> extension, final int index) {
      GeneratedExtension<MessageType, List<Type>> extensionLite = checkIsLite(extension);

      verifyExtensionContainingType(extensionLite);
      return (Type)
          extensionLite.singularFromFieldSetType(
              extensions.getRepeatedField(extensionLite.descriptor, index));
    }

    /** Called by subclasses to check if all extensions are initialized. */
    protected boolean extensionsAreInitialized() {
      return extensions.isInitialized();
    }

    /**
     * Used by subclasses to serialize extensions. Extension ranges may be interleaved with field
     * numbers, but we must write them in canonical (sorted by field number) order. ExtensionWriter
     * helps us write individual ranges of extensions at once.
     */
    protected class ExtensionWriter {
      // Imagine how much simpler this code would be if Java iterators had
      // a way to get the next element without advancing the iterator.

      private final Iterator<Map.Entry<ExtensionDescriptor, Object>> iter = extensions.iterator();
      private Map.Entry<ExtensionDescriptor, Object> next;
      private final boolean messageSetWireFormat;

      private ExtensionWriter(boolean messageSetWireFormat) {
        if (iter.hasNext()) {
          next = iter.next();
        }
        this.messageSetWireFormat = messageSetWireFormat;
      }

      public void writeUntil(final int end, final CodedOutputStream output) throws IOException {
        while (next != null && next.getKey().getNumber() < end) {
          ExtensionDescriptor extension = next.getKey();
          if (messageSetWireFormat
              && extension.getLiteJavaType() == WireFormat.JavaType.MESSAGE
              && !extension.isRepeated()) {
            output.writeMessageSetExtension(extension.getNumber(), (MessageLite) next.getValue());
          } else {
            FieldSet.writeField(extension, next.getValue(), output);
          }
          if (iter.hasNext()) {
            next = iter.next();
          } else {
            next = null;
          }
        }
      }
    }

    protected ExtensionWriter newExtensionWriter() {
      return new ExtensionWriter(false);
    }

    protected ExtensionWriter newMessageSetExtensionWriter() {
      return new ExtensionWriter(true);
    }

    /** Called by subclasses to compute the size of extensions. */
    protected int extensionsSerializedSize() {
      return extensions.getSerializedSize();
    }

    protected int extensionsSerializedSizeAsMessageSet() {
      return extensions.getMessageSetSerializedSize();
    }
  }

  /** Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}. */
  @SuppressWarnings("unchecked")
  public abstract static class ExtendableBuilder<
          MessageType extends ExtendableMessage<MessageType, BuilderType>,
          BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
      extends Builder<MessageType, BuilderType>
      implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
    protected ExtendableBuilder(MessageType defaultInstance) {
      super(defaultInstance);
    }

    // For immutable message conversion.
    void internalSetExtensionSet(FieldSet<ExtensionDescriptor> extensions) {
      copyOnWrite();
      instance.extensions = extensions;
    }

    @Override
    protected void copyOnWrite() {
      if (!isBuilt) {
        return;
      }

      super.copyOnWrite();
      instance.extensions = instance.extensions.clone();
    }

    private FieldSet<ExtensionDescriptor> ensureExtensionsAreMutable() {
      FieldSet<ExtensionDescriptor> extensions = instance.extensions;
      if (extensions.isImmutable()) {
        extensions = extensions.clone();
        instance.extensions = extensions;
      }
      return extensions;
    }

    @Override
    public final MessageType buildPartial() {
      if (isBuilt) {
        return instance;
      }

      instance.extensions.makeImmutable();
      return super.buildPartial();
    }

    private void verifyExtensionContainingType(final GeneratedExtension<MessageType, ?> extension) {
      if (extension.getContainingTypeDefaultInstance() != getDefaultInstanceForType()) {
        // This can only happen if someone uses unchecked operations.
        throw new IllegalArgumentException(
            "This extension is for a different message type.  Please make "
                + "sure that you are not suppressing any generics type warnings.");
      }
    }

    /** Check if a singular extension is present. */
    @Override
    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) {
      return instance.hasExtension(extension);
    }

    /** Get the number of elements in a repeated extension. */
    @Override
    public final <Type> int getExtensionCount(
        final ExtensionLite<MessageType, List<Type>> extension) {
      return instance.getExtensionCount(extension);
    }

    /** Get the value of an extension. */
    @Override
    @SuppressWarnings("unchecked")
    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) {
      return instance.getExtension(extension);
    }

    /** Get one element of a repeated extension. */
    @Override
    @SuppressWarnings("unchecked")
    public final <Type> Type getExtension(
        final ExtensionLite<MessageType, List<Type>> extension, final int index) {
      return instance.getExtension(extension, index);
    }

    /** Set the value of an extension. */
    public final <Type> BuilderType setExtension(
        final ExtensionLite<MessageType, Type> extension, final Type value) {
      GeneratedExtension<MessageType, Type> extensionLite = checkIsLite(extension);

      verifyExtensionContainingType(extensionLite);
      copyOnWrite();
      ensureExtensionsAreMutable()
          .setField(extensionLite.descriptor, extensionLite.toFieldSetType(value));
      return (BuilderType) this;
    }

    /** Set the value of one element of a repeated extension. */
    public final <Type> BuilderType setExtension(
        final ExtensionLite<MessageType, List<Type>> extension, final int index, final Type value) {
      GeneratedExtension<MessageType, List<Type>> extensionLite = checkIsLite(extension);

      verifyExtensionContainingType(extensionLite);
      copyOnWrite();
      ensureExtensionsAreMutable()
          .setRepeatedField(
              extensionLite.descriptor, index, extensionLite.singularToFieldSetType(value));
      return (BuilderType) this;
    }

    /** Append a value to a repeated extension. */
    public final <Type> BuilderType addExtension(
        final ExtensionLite<MessageType, List<Type>> extension, final Type value) {
      GeneratedExtension<MessageType, List<Type>> extensionLite = checkIsLite(extension);

      verifyExtensionContainingType(extensionLite);
      copyOnWrite();
      ensureExtensionsAreMutable()
          .addRepeatedField(extensionLite.descriptor, extensionLite.singularToFieldSetType(value));
      return (BuilderType) this;
    }

    /** Clear an extension. */
    public final <Type> BuilderType clearExtension(final ExtensionLite<MessageType, ?> extension) {
      GeneratedExtension<MessageType, ?> extensionLite = checkIsLite(extension);

      verifyExtensionContainingType(extensionLite);
      copyOnWrite();
      ensureExtensionsAreMutable().clearField(extensionLite.descriptor);
      return (BuilderType) this;
    }
  }

  // -----------------------------------------------------------------

  /** For use by generated code only. */
  public static <ContainingType extends MessageLite, Type>
      GeneratedExtension<ContainingType, Type> newSingularGeneratedExtension(
          final ContainingType containingTypeDefaultInstance,
          final Type defaultValue,
          final MessageLite messageDefaultInstance,
          final Internal.EnumLiteMap<?> enumTypeMap,
          final int number,
          final WireFormat.FieldType type,
          final Class singularType) {
    return new GeneratedExtension<ContainingType, Type>(
        containingTypeDefaultInstance,
        defaultValue,
        messageDefaultInstance,
        new ExtensionDescriptor(
            enumTypeMap, number, type, /* isRepeated= */ false, /* isPacked= */ false),
        singularType);
  }

  /** For use by generated code only. */
  public static <ContainingType extends MessageLite, Type>
      GeneratedExtension<ContainingType, Type> newRepeatedGeneratedExtension(
          final ContainingType containingTypeDefaultInstance,
          final MessageLite messageDefaultInstance,
          final Internal.EnumLiteMap<?> enumTypeMap,
          final int number,
          final WireFormat.FieldType type,
          final boolean isPacked,
          final Class singularType) {
    @SuppressWarnings("unchecked") // Subclasses ensure Type is a List
    Type emptyList = (Type) Collections.emptyList();
    return new GeneratedExtension<ContainingType, Type>(
        containingTypeDefaultInstance,
        emptyList,
        messageDefaultInstance,
        new ExtensionDescriptor(enumTypeMap, number, type, /* isRepeated= */ true, isPacked),
        singularType);
  }

  static final class ExtensionDescriptor
      implements FieldSet.FieldDescriptorLite<ExtensionDescriptor> {
    ExtensionDescriptor(
        final Internal.EnumLiteMap<?> enumTypeMap,
        final int number,
        final WireFormat.FieldType type,
        final boolean isRepeated,
        final boolean isPacked) {
      this.enumTypeMap = enumTypeMap;
      this.number = number;
      this.type = type;
      this.isRepeated = isRepeated;
      this.isPacked = isPacked;
    }

    final Internal.EnumLiteMap<?> enumTypeMap;
    final int number;
    final WireFormat.FieldType type;
    final boolean isRepeated;
    final boolean isPacked;

    @Override
    public int getNumber() {
      return number;
    }

    @Override
    public WireFormat.FieldType getLiteType() {
      return type;
    }

    @Override
    public WireFormat.JavaType getLiteJavaType() {
      return type.getJavaType();
    }

    @Override
    public boolean isRepeated() {
      return isRepeated;
    }

    @Override
    public boolean isPacked() {
      return isPacked;
    }

    @Override
    public Internal.EnumLiteMap<?> getEnumType() {
      return enumTypeMap;
    }

    @Override
    @SuppressWarnings("unchecked")
    public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) {
      return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
    }


    @Override
    public int compareTo(ExtensionDescriptor other) {
      return number - other.number;
    }
  }

  // =================================================================

  /** Calls Class.getMethod and throws a RuntimeException if it fails. */
  @SuppressWarnings("unchecked")
  static Method getMethodOrDie(Class clazz, String name, Class... params) {
    try {
      return clazz.getMethod(name, params);
    } catch (NoSuchMethodException e) {
      throw new RuntimeException(
          "Generated message class \"" + clazz.getName() + "\" missing method \"" + name + "\".",
          e);
    }
  }

  /** Calls invoke and throws a RuntimeException if it fails. */
  static Object invokeOrDie(Method method, Object object, Object... params) {
    try {
      return method.invoke(object, params);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(
          "Couldn't use Java reflection to implement protocol message reflection.", e);
    } catch (InvocationTargetException e) {
      final Throwable cause = e.getCause();
      if (cause instanceof RuntimeException) {
        throw (RuntimeException) cause;
      } else if (cause instanceof Error) {
        throw (Error) cause;
      } else {
        throw new RuntimeException(
            "Unexpected exception thrown by generated accessor method.", cause);
      }
    }
  }


  /**
   * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}.
   *
   * <p>Users should ignore the contents of this class and only use objects of this type as
   * parameters to extension accessors and ExtensionRegistry.add().
   */
  public static class GeneratedExtension<ContainingType extends MessageLite, Type>
      extends ExtensionLite<ContainingType, Type> {

    /**
     * Create a new instance with the given parameters.
     *
     * <p>The last parameter {@code singularType} is only needed for enum types. We store integer
     * values for enum types in a {@link ExtendableMessage} and use Java reflection to convert an
     * integer value back into a concrete enum object.
     */
    GeneratedExtension(
        final ContainingType containingTypeDefaultInstance,
        final Type defaultValue,
        final MessageLite messageDefaultInstance,
        final ExtensionDescriptor descriptor,
        final Class singularType) {
      // Defensive checks to verify the correct initialization order of
      // GeneratedExtensions and their related GeneratedMessages.
      if (containingTypeDefaultInstance == null) {
        throw new IllegalArgumentException("Null containingTypeDefaultInstance");
      }
      if (descriptor.getLiteType() == WireFormat.FieldType.MESSAGE
          && messageDefaultInstance == null) {
        throw new IllegalArgumentException("Null messageDefaultInstance");
      }
      this.containingTypeDefaultInstance = containingTypeDefaultInstance;
      this.defaultValue = defaultValue;
      this.messageDefaultInstance = messageDefaultInstance;
      this.descriptor = descriptor;
    }

    final ContainingType containingTypeDefaultInstance;
    final Type defaultValue;
    final MessageLite messageDefaultInstance;
    final ExtensionDescriptor descriptor;

    /** Default instance of the type being extended, used to identify that type. */
    public ContainingType getContainingTypeDefaultInstance() {
      return containingTypeDefaultInstance;
    }

    /** Get the field number. */
    @Override
    public int getNumber() {
      return descriptor.getNumber();
    }

    /**
     * If the extension is an embedded message or group, returns the default instance of the
     * message.
     */
    @Override
    public MessageLite getMessageDefaultInstance() {
      return messageDefaultInstance;
    }

    @SuppressWarnings("unchecked")
    Object fromFieldSetType(final Object value) {
      if (descriptor.isRepeated()) {
        if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
          final List result = new ArrayList();
          for (final Object element : (List) value) {
            result.add(singularFromFieldSetType(element));
          }
          return result;
        } else {
          return value;
        }
      } else {
        return singularFromFieldSetType(value);
      }
    }

    Object singularFromFieldSetType(final Object value) {
      if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
        return descriptor.enumTypeMap.findValueByNumber((Integer) value);
      } else {
        return value;
      }
    }

    @SuppressWarnings("unchecked")
    Object toFieldSetType(final Object value) {
      if (descriptor.isRepeated()) {
        if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
          final List result = new ArrayList();
          for (final Object element : (List) value) {
            result.add(singularToFieldSetType(element));
          }
          return result;
        } else {
          return value;
        }
      } else {
        return singularToFieldSetType(value);
      }
    }

    Object singularToFieldSetType(final Object value) {
      if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
        return ((Internal.EnumLite) value).getNumber();
      } else {
        return value;
      }
    }

    @Override
    public FieldType getLiteType() {
      return descriptor.getLiteType();
    }

    @Override
    public boolean isRepeated() {
      return descriptor.isRepeated;
    }

    @Override
    public Type getDefaultValue() {
      return defaultValue;
    }
  }

  /**
   * A serialized (serializable) form of the generated message. Stores the message as a class name
   * and a byte array.
   */
  protected static final class SerializedForm implements Serializable {

    public static SerializedForm of(MessageLite message) {
      return new SerializedForm(message);
    }

    private static final long serialVersionUID = 0L;

    // since v3.6.1
    private final Class<?> messageClass;
    // only included for backwards compatibility before messageClass was added
    private final String messageClassName;
    private final byte[] asBytes;

    /**
     * Creates the serialized form by calling {@link com.google.protobuf.MessageLite#toByteArray}.
     *
     * @param regularForm the message to serialize
     */
    SerializedForm(MessageLite regularForm) {
      messageClass = regularForm.getClass();
      messageClassName = messageClass.getName();
      asBytes = regularForm.toByteArray();
    }

    /**
     * When read from an ObjectInputStream, this method converts this object back to the regular
     * form. Part of Java's serialization magic.
     *
     * @return a GeneratedMessage of the type that was serialized
     */
    @SuppressWarnings("unchecked")
    protected Object readResolve() throws ObjectStreamException {
      try {
        Class<?> messageClass = resolveMessageClass();
        java.lang.reflect.Field defaultInstanceField =
            messageClass.getDeclaredField("DEFAULT_INSTANCE");
        defaultInstanceField.setAccessible(true);
        MessageLite defaultInstance = (MessageLite) defaultInstanceField.get(null);
        return defaultInstance.newBuilderForType().mergeFrom(asBytes).buildPartial();
      } catch (ClassNotFoundException e) {
        throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e);
      } catch (NoSuchFieldException e) {
        return readResolveFallback();
      } catch (SecurityException e) {
        throw new RuntimeException("Unable to call DEFAULT_INSTANCE in " + messageClassName, e);
      } catch (IllegalAccessException e) {
        throw new RuntimeException("Unable to call parsePartialFrom", e);
      } catch (InvalidProtocolBufferException e) {
        throw new RuntimeException("Unable to understand proto buffer", e);
      }
    }

    /**
     * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1 generated code.
     */
    @Deprecated
    private Object readResolveFallback() throws ObjectStreamException {
      try {
        Class<?> messageClass = resolveMessageClass();
        java.lang.reflect.Field defaultInstanceField =
            messageClass.getDeclaredField("defaultInstance");
        defaultInstanceField.setAccessible(true);
        MessageLite defaultInstance = (MessageLite) defaultInstanceField.get(null);
        return defaultInstance.newBuilderForType()
            .mergeFrom(asBytes)
            .buildPartial();
      } catch (ClassNotFoundException e) {
        throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e);
      } catch (NoSuchFieldException e) {
        throw new RuntimeException("Unable to find defaultInstance in " + messageClassName, e);
      } catch (SecurityException e) {
        throw new RuntimeException("Unable to call defaultInstance in " + messageClassName, e);
      } catch (IllegalAccessException e) {
        throw new RuntimeException("Unable to call parsePartialFrom", e);
      } catch (InvalidProtocolBufferException e) {
        throw new RuntimeException("Unable to understand proto buffer", e);
      }
    }

    private Class<?> resolveMessageClass() throws ClassNotFoundException {
      return messageClass != null ? messageClass : Class.forName(messageClassName);
    }
  }

  /** Checks that the {@link Extension} is Lite and returns it as a {@link GeneratedExtension}. */
  private static <
          MessageType extends ExtendableMessage<MessageType, BuilderType>,
          BuilderType extends ExtendableBuilder<MessageType, BuilderType>,
          T>
      GeneratedExtension<MessageType, T> checkIsLite(ExtensionLite<MessageType, T> extension) {
    if (!extension.isLite()) {
      throw new IllegalArgumentException("Expected a lite extension.");
    }

    return (GeneratedExtension<MessageType, T>) extension;
  }

  /**
   * A static helper method for checking if a message is initialized, optionally memoizing.
   *
   * <p>For use by generated code only.
   */
  protected static final <T extends GeneratedMessageLite<T, ?>> boolean isInitialized(
      T message, boolean shouldMemoize) {
    byte memoizedIsInitialized =
        (Byte) message.dynamicMethod(MethodToInvoke.GET_MEMOIZED_IS_INITIALIZED);
    if (memoizedIsInitialized == 1) {
      return true;
    }
    if (memoizedIsInitialized == 0) {
      return false;
    }
    boolean isInitialized = Protobuf.getInstance().schemaFor(message).isInitialized(message);
    if (shouldMemoize) {
      message.dynamicMethod(
          MethodToInvoke.SET_MEMOIZED_IS_INITIALIZED, isInitialized ? message : null);
    }
    return isInitialized;
  }

  protected static IntList emptyIntList() {
    return IntArrayList.emptyList();
  }

  protected static IntList mutableCopy(IntList list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  protected static LongList emptyLongList() {
    return LongArrayList.emptyList();
  }

  protected static LongList mutableCopy(LongList list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  protected static FloatList emptyFloatList() {
    return FloatArrayList.emptyList();
  }

  protected static FloatList mutableCopy(FloatList list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  protected static DoubleList emptyDoubleList() {
    return DoubleArrayList.emptyList();
  }

  protected static DoubleList mutableCopy(DoubleList list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  protected static BooleanList emptyBooleanList() {
    return BooleanArrayList.emptyList();
  }

  protected static BooleanList mutableCopy(BooleanList list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  protected static <E> ProtobufList<E> emptyProtobufList() {
    return ProtobufArrayList.emptyList();
  }

  protected static <E> ProtobufList<E> mutableCopy(ProtobufList<E> list) {
    int size = list.size();
    return list.mutableCopyWithCapacity(
        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
  }

  /**
   * A {@link Parser} implementation that delegates to the default instance.
   *
   * <p>For use by generated code only.
   */
  protected static class DefaultInstanceBasedParser<T extends GeneratedMessageLite<T, ?>>
      extends AbstractParser<T> {

    private final T defaultInstance;

    public DefaultInstanceBasedParser(T defaultInstance) {
      this.defaultInstance = defaultInstance;
    }

    @Override
    public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
        throws InvalidProtocolBufferException {
      return GeneratedMessageLite.parsePartialFrom(defaultInstance, input, extensionRegistry);
    }

    @Override
    public T parsePartialFrom(
        byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry)
        throws InvalidProtocolBufferException {
      return GeneratedMessageLite.parsePartialFrom(
          defaultInstance, input, offset, length, extensionRegistry);
    }
  }

  /**
   * A static helper method for parsing a partial from input using the extension registry and the
   * instance.
   */
  // TODO(dweis): Should this verify that the last tag was 0?
  static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
      T instance, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    @SuppressWarnings("unchecked") // Guaranteed by protoc
    T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
    try {
      // TODO(yilunchong): Try to make input with type CodedInpuStream.ArrayDecoder use
      // fast path.
      Protobuf.getInstance().schemaFor(result).mergeFrom(
          result, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
      result.makeImmutable();
    } catch (IOException e) {
      if (e.getCause() instanceof InvalidProtocolBufferException) {
        throw (InvalidProtocolBufferException) e.getCause();
      }
      throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
    } catch (RuntimeException e) {
      if (e.getCause() instanceof InvalidProtocolBufferException) {
        throw (InvalidProtocolBufferException) e.getCause();
      }
      throw e;
    }
    return result;
  }

  /** A static helper method for parsing a partial from byte array. */
  static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
      T instance, byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    @SuppressWarnings("unchecked") // Guaranteed by protoc
    T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
    try {
      Protobuf.getInstance().schemaFor(result).mergeFrom(
          result, input, offset, offset + length,
          new ArrayDecoders.Registers(extensionRegistry));
      result.makeImmutable();
      if (result.memoizedHashCode != 0) {
        throw new RuntimeException();
      }
    } catch (IOException e) {
      if (e.getCause() instanceof InvalidProtocolBufferException) {
        throw (InvalidProtocolBufferException) e.getCause();
      }
      throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
    } catch (IndexOutOfBoundsException e) {
      throw InvalidProtocolBufferException.truncatedMessage().setUnfinishedMessage(result);
    }
    return result;
  }

  protected static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
      T defaultInstance, CodedInputStream input) throws InvalidProtocolBufferException {
    return parsePartialFrom(defaultInstance, input, ExtensionRegistryLite.getEmptyRegistry());
  }

  /**
   * Helper method to check if message is initialized.
   *
   * @throws InvalidProtocolBufferException if it is not initialized.
   * @return The message to check.
   */
  private static <T extends GeneratedMessageLite<T, ?>> T checkMessageInitialized(T message)
      throws InvalidProtocolBufferException {
    if (message != null && !message.isInitialized()) {
      throw message
          .newUninitializedMessageException()
          .asInvalidProtocolBufferException()
          .setUnfinishedMessage(message);
    }
    return message;
  }

  // Validates last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
      T defaultInstance, ByteBuffer data, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    return checkMessageInitialized(
        parseFrom(defaultInstance, CodedInputStream.newInstance(data), extensionRegistry));
  }

  // Validates last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
      T defaultInstance, ByteBuffer data) throws InvalidProtocolBufferException {
    return parseFrom(defaultInstance, data, ExtensionRegistryLite.getEmptyRegistry());
  }

  // Validates last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
      T defaultInstance, ByteString data) throws InvalidProtocolBufferException {
    return checkMessageInitialized(
        parseFrom(defaultInstance, data, ExtensionRegistryLite.getEmptyRegistry()));
  }

  // Validates last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
      T defaultInstance, ByteString data, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    return checkMessageInitialized(parsePartialFrom(defaultInstance, data, extensionRegistry));
  }

  // This is a special case since we want to verify that the last tag is 0. We assume we exhaust the
  // ByteString.
  private static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
      T defaultInstance, ByteString data, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    T message;
    try {
      CodedInputStream input = data.newCodedInput();
      message = parsePartialFrom(defaultInstance, input, extensionRegistry);
      try {
        input.checkLastTagWas(0);
      } catch (InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(message);
      }
      return message;
    } catch (InvalidProtocolBufferException e) {
      throw e;
    }
  }

  // This is a special case since we want to verify that the last tag is 0. We assume we exhaust the
  // ByteString.
  private static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
      T defaultInstance, byte[] data, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    return checkMessageInitialized(
        parsePartialFrom(defaultInstance, data, 0, data.length, extensionRegistry));
  }

  // Validates last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
      T defaultInstance, byte[] data) throws InvalidProtocolBufferException {
    return checkMessageInitialized(parsePartialFrom(
        defaultInstance, data, 0, data.length, ExtensionRegistryLite.getEmptyRegistry()));
  }

  // Validates last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
      T defaultInstance, byte[] data, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    return checkMessageInitialized(
        parsePartialFrom(defaultInstance, data, 0, data.length, extensionRegistry));
  }

  // Does not validate last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
      T defaultInstance, InputStream input) throws InvalidProtocolBufferException {
    return checkMessageInitialized(
        parsePartialFrom(
            defaultInstance,
            CodedInputStream.newInstance(input),
            ExtensionRegistryLite.getEmptyRegistry()));
  }

  // Does not validate last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
      T defaultInstance, InputStream input, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    return checkMessageInitialized(
        parsePartialFrom(defaultInstance, CodedInputStream.newInstance(input), extensionRegistry));
  }

  // Does not validate last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
      T defaultInstance, CodedInputStream input) throws InvalidProtocolBufferException {
    return parseFrom(defaultInstance, input, ExtensionRegistryLite.getEmptyRegistry());
  }

  // Does not validate last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
      T defaultInstance, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    return checkMessageInitialized(parsePartialFrom(defaultInstance, input, extensionRegistry));
  }

  // Validates last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseDelimitedFrom(
      T defaultInstance, InputStream input) throws InvalidProtocolBufferException {
    return checkMessageInitialized(
        parsePartialDelimitedFrom(
            defaultInstance, input, ExtensionRegistryLite.getEmptyRegistry()));
  }

  // Validates last tag.
  protected static <T extends GeneratedMessageLite<T, ?>> T parseDelimitedFrom(
      T defaultInstance, InputStream input, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    return checkMessageInitialized(
        parsePartialDelimitedFrom(defaultInstance, input, extensionRegistry));
  }

  private static <T extends GeneratedMessageLite<T, ?>> T parsePartialDelimitedFrom(
      T defaultInstance, InputStream input, ExtensionRegistryLite extensionRegistry)
      throws InvalidProtocolBufferException {
    int size;
    try {
      int firstByte = input.read();
      if (firstByte == -1) {
        return null;
      }
      size = CodedInputStream.readRawVarint32(firstByte, input);
    } catch (IOException e) {
      throw new InvalidProtocolBufferException(e.getMessage());
    }
    InputStream limitedInput = new LimitedInputStream(input, size);
    CodedInputStream codedInput = CodedInputStream.newInstance(limitedInput);
    T message = parsePartialFrom(defaultInstance, codedInput, extensionRegistry);
    try {
      codedInput.checkLastTagWas(0);
    } catch (InvalidProtocolBufferException e) {
      throw e.setUnfinishedMessage(message);
    }
    return message;
  }
}
