// 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 static com.google.protobuf.WireFormat.FIXED32_SIZE;
import static com.google.protobuf.WireFormat.FIXED64_SIZE;
import static com.google.protobuf.WireFormat.WIRETYPE_END_GROUP;
import static com.google.protobuf.WireFormat.WIRETYPE_FIXED32;
import static com.google.protobuf.WireFormat.WIRETYPE_FIXED64;
import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED;
import static com.google.protobuf.WireFormat.WIRETYPE_START_GROUP;
import static com.google.protobuf.WireFormat.WIRETYPE_VARINT;

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

/** An adapter between the {@link Reader} interface and {@link CodedInputStream}. */
@ExperimentalApi
final class CodedInputStreamReader implements Reader {
  private static final int FIXED32_MULTIPLE_MASK = FIXED32_SIZE - 1;
  private static final int FIXED64_MULTIPLE_MASK = FIXED64_SIZE - 1;
  private static final int NEXT_TAG_UNSET = 0;

  private final CodedInputStream input;
  private int tag;
  private int endGroupTag;
  private int nextTag = NEXT_TAG_UNSET;

  public static CodedInputStreamReader forCodedInput(CodedInputStream input) {
    if (input.wrapper != null) {
      return input.wrapper;
    }
    return new CodedInputStreamReader(input);
  }

  private CodedInputStreamReader(CodedInputStream input) {
    this.input = Internal.checkNotNull(input, "input");
    this.input.wrapper = this;
  }

  @Override
  public boolean shouldDiscardUnknownFields() {
    return input.shouldDiscardUnknownFields();
  }

  @Override
  public int getFieldNumber() throws IOException {
    if (nextTag != NEXT_TAG_UNSET) {
      tag = nextTag;
      nextTag = NEXT_TAG_UNSET;
    } else {
      tag = input.readTag();
    }
    if (tag == 0 || tag == endGroupTag) {
      return Reader.READ_DONE;
    }
    return WireFormat.getTagFieldNumber(tag);
  }

  @Override
  public int getTag() {
    return tag;
  }

  @Override
  public boolean skipField() throws IOException {
    if (input.isAtEnd() || tag == endGroupTag) {
      return false;
    }
    return input.skipField(tag);
  }

  private void requireWireType(int requiredWireType) throws IOException {
    if (WireFormat.getTagWireType(tag) != requiredWireType) {
      throw InvalidProtocolBufferException.invalidWireType();
    }
  }

  @Override
  public double readDouble() throws IOException {
    requireWireType(WIRETYPE_FIXED64);
    return input.readDouble();
  }

  @Override
  public float readFloat() throws IOException {
    requireWireType(WIRETYPE_FIXED32);
    return input.readFloat();
  }

  @Override
  public long readUInt64() throws IOException {
    requireWireType(WIRETYPE_VARINT);
    return input.readUInt64();
  }

  @Override
  public long readInt64() throws IOException {
    requireWireType(WIRETYPE_VARINT);
    return input.readInt64();
  }

  @Override
  public int readInt32() throws IOException {
    requireWireType(WIRETYPE_VARINT);
    return input.readInt32();
  }

  @Override
  public long readFixed64() throws IOException {
    requireWireType(WIRETYPE_FIXED64);
    return input.readFixed64();
  }

  @Override
  public int readFixed32() throws IOException {
    requireWireType(WIRETYPE_FIXED32);
    return input.readFixed32();
  }

  @Override
  public boolean readBool() throws IOException {
    requireWireType(WIRETYPE_VARINT);
    return input.readBool();
  }

  @Override
  public String readString() throws IOException {
    requireWireType(WIRETYPE_LENGTH_DELIMITED);
    return input.readString();
  }

  @Override
  public String readStringRequireUtf8() throws IOException {
    requireWireType(WIRETYPE_LENGTH_DELIMITED);
    return input.readStringRequireUtf8();
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> T readMessage(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
      throws IOException {
    requireWireType(WIRETYPE_LENGTH_DELIMITED);
    return readMessage(Protobuf.getInstance().schemaFor(clazz), extensionRegistry);
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> T readMessageBySchemaWithCheck(
      Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
    requireWireType(WIRETYPE_LENGTH_DELIMITED);
    return readMessage(schema, extensionRegistry);
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> T readGroup(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
      throws IOException {
    requireWireType(WIRETYPE_START_GROUP);
    return readGroup(Protobuf.getInstance().schemaFor(clazz), extensionRegistry);
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> T readGroupBySchemaWithCheck(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
      throws IOException {
    requireWireType(WIRETYPE_START_GROUP);
    return readGroup(schema, extensionRegistry);
  }

  // Should have the same semantics of CodedInputStream#readMessage()
  private <T> T readMessage(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
      throws IOException {
    int size = input.readUInt32();
    if (input.recursionDepth >= input.recursionLimit) {
      throw InvalidProtocolBufferException.recursionLimitExceeded();
    }

    // Push the new limit.
    final int prevLimit = input.pushLimit(size);
    // Allocate and read the message.
    T message = schema.newInstance();
    ++input.recursionDepth;
    schema.mergeFrom(message, this, extensionRegistry);
    schema.makeImmutable(message);
    input.checkLastTagWas(0);
    --input.recursionDepth;
    // Restore the previous limit.
    input.popLimit(prevLimit);
    return message;
  }

  private <T> T readGroup(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
      throws IOException {
    int prevEndGroupTag = endGroupTag;
    endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP);

    try {
      // Allocate and read the message.
      T message = schema.newInstance();
      schema.mergeFrom(message, this, extensionRegistry);
      schema.makeImmutable(message);

      if (tag != endGroupTag) {
        throw InvalidProtocolBufferException.parseFailure();
      }
      return message;
    } finally {
      // Restore the old end group tag.
      endGroupTag = prevEndGroupTag;
    }
  }

  @Override
  public ByteString readBytes() throws IOException {
    requireWireType(WIRETYPE_LENGTH_DELIMITED);
    return input.readBytes();
  }

  @Override
  public int readUInt32() throws IOException {
    requireWireType(WIRETYPE_VARINT);
    return input.readUInt32();
  }

  @Override
  public int readEnum() throws IOException {
    requireWireType(WIRETYPE_VARINT);
    return input.readEnum();
  }

  @Override
  public int readSFixed32() throws IOException {
    requireWireType(WIRETYPE_FIXED32);
    return input.readSFixed32();
  }

  @Override
  public long readSFixed64() throws IOException {
    requireWireType(WIRETYPE_FIXED64);
    return input.readSFixed64();
  }

  @Override
  public int readSInt32() throws IOException {
    requireWireType(WIRETYPE_VARINT);
    return input.readSInt32();
  }

  @Override
  public long readSInt64() throws IOException {
    requireWireType(WIRETYPE_VARINT);
    return input.readSInt64();
  }

  @Override
  public void readDoubleList(List<Double> target) throws IOException {
    if (target instanceof DoubleArrayList) {
      DoubleArrayList plist = (DoubleArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed64Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addDouble(input.readDouble());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED64:
          while (true) {
            plist.addDouble(input.readDouble());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed64Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readDouble());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED64:
          while (true) {
            target.add(input.readDouble());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readFloatList(List<Float> target) throws IOException {
    if (target instanceof FloatArrayList) {
      FloatArrayList plist = (FloatArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed32Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addFloat(input.readFloat());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED32:
          while (true) {
            plist.addFloat(input.readFloat());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed32Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readFloat());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED32:
          while (true) {
            target.add(input.readFloat());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readUInt64List(List<Long> target) throws IOException {
    if (target instanceof LongArrayList) {
      LongArrayList plist = (LongArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addLong(input.readUInt64());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            plist.addLong(input.readUInt64());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readUInt64());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            target.add(input.readUInt64());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readInt64List(List<Long> target) throws IOException {
    if (target instanceof LongArrayList) {
      LongArrayList plist = (LongArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addLong(input.readInt64());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            plist.addLong(input.readInt64());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readInt64());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            target.add(input.readInt64());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readInt32List(List<Integer> target) throws IOException {
    if (target instanceof IntArrayList) {
      IntArrayList plist = (IntArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addInt(input.readInt32());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            plist.addInt(input.readInt32());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readInt32());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            target.add(input.readInt32());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readFixed64List(List<Long> target) throws IOException {
    if (target instanceof LongArrayList) {
      LongArrayList plist = (LongArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed64Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addLong(input.readFixed64());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED64:
          while (true) {
            plist.addLong(input.readFixed64());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed64Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readFixed64());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED64:
          while (true) {
            target.add(input.readFixed64());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readFixed32List(List<Integer> target) throws IOException {
    if (target instanceof IntArrayList) {
      IntArrayList plist = (IntArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed32Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addInt(input.readFixed32());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED32:
          while (true) {
            plist.addInt(input.readFixed32());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed32Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readFixed32());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED32:
          while (true) {
            target.add(input.readFixed32());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readBoolList(List<Boolean> target) throws IOException {
    if (target instanceof BooleanArrayList) {
      BooleanArrayList plist = (BooleanArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addBoolean(input.readBool());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            plist.addBoolean(input.readBool());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readBool());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            target.add(input.readBool());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readStringList(List<String> target) throws IOException {
    readStringListInternal(target, false);
  }

  @Override
  public void readStringListRequireUtf8(List<String> target) throws IOException {
    readStringListInternal(target, true);
  }

  public void readStringListInternal(List<String> target, boolean requireUtf8) throws IOException {
    if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
      throw InvalidProtocolBufferException.invalidWireType();
    }

    if (target instanceof LazyStringList && !requireUtf8) {
      LazyStringList lazyList = (LazyStringList) target;
      while (true) {
        lazyList.add(readBytes());
        if (input.isAtEnd()) {
          return;
        }
        int nextTag = input.readTag();
        if (nextTag != tag) {
          // We've reached the end of the repeated field. Save the next tag value.
          this.nextTag = nextTag;
          return;
        }
      }
    } else {
      while (true) {
        target.add(requireUtf8 ? readStringRequireUtf8() : readString());
        if (input.isAtEnd()) {
          return;
        }
        int nextTag = input.readTag();
        if (nextTag != tag) {
          // We've reached the end of the repeated field. Save the next tag value.
          this.nextTag = nextTag;
          return;
        }
      }
    }
  }

  @Override
  public <T> void readMessageList(
      List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
      throws IOException {
    final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
    readMessageList(target, schema, extensionRegistry);
  }

  @Override
  public <T> void readMessageList(
      List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
      throws IOException {
    if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
      throw InvalidProtocolBufferException.invalidWireType();
    }
    final int listTag = tag;
    while (true) {
      target.add(readMessage(schema, extensionRegistry));
      if (input.isAtEnd() || nextTag != NEXT_TAG_UNSET) {
        return;
      }
      int nextTag = input.readTag();
      if (nextTag != listTag) {
        // We've reached the end of the repeated field. Save the next tag value.
        this.nextTag = nextTag;
        return;
      }
    }
  }

  @Override
  public <T> void readGroupList(
      List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
      throws IOException {
    final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
    readGroupList(target, schema, extensionRegistry);
  }

  @Override
  public <T> void readGroupList(
      List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
      throws IOException {
    if (WireFormat.getTagWireType(tag) != WIRETYPE_START_GROUP) {
      throw InvalidProtocolBufferException.invalidWireType();
    }
    final int listTag = tag;
    while (true) {
      target.add(readGroup(schema, extensionRegistry));
      if (input.isAtEnd() || nextTag != NEXT_TAG_UNSET) {
        return;
      }
      int nextTag = input.readTag();
      if (nextTag != listTag) {
        // We've reached the end of the repeated field. Save the next tag value.
        this.nextTag = nextTag;
        return;
      }
    }
  }

  @Override
  public void readBytesList(List<ByteString> target) throws IOException {
    if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
      throw InvalidProtocolBufferException.invalidWireType();
    }

    while (true) {
      target.add(readBytes());
      if (input.isAtEnd()) {
        return;
      }
      int nextTag = input.readTag();
      if (nextTag != tag) {
        // We've reached the end of the repeated field. Save the next tag value.
        this.nextTag = nextTag;
        return;
      }
    }
  }

  @Override
  public void readUInt32List(List<Integer> target) throws IOException {
    if (target instanceof IntArrayList) {
      IntArrayList plist = (IntArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addInt(input.readUInt32());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            plist.addInt(input.readUInt32());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readUInt32());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            target.add(input.readUInt32());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readEnumList(List<Integer> target) throws IOException {
    if (target instanceof IntArrayList) {
      IntArrayList plist = (IntArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addInt(input.readEnum());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            plist.addInt(input.readEnum());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readEnum());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            target.add(input.readEnum());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readSFixed32List(List<Integer> target) throws IOException {
    if (target instanceof IntArrayList) {
      IntArrayList plist = (IntArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed32Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addInt(input.readSFixed32());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED32:
          while (true) {
            plist.addInt(input.readSFixed32());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed32Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readSFixed32());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED32:
          while (true) {
            target.add(input.readSFixed32());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readSFixed64List(List<Long> target) throws IOException {
    if (target instanceof LongArrayList) {
      LongArrayList plist = (LongArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed64Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addLong(input.readSFixed64());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED64:
          while (true) {
            plist.addLong(input.readSFixed64());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          verifyPackedFixed64Length(bytes);
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readSFixed64());
          } while (input.getTotalBytesRead() < endPos);
          break;
        case WIRETYPE_FIXED64:
          while (true) {
            target.add(input.readSFixed64());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readSInt32List(List<Integer> target) throws IOException {
    if (target instanceof IntArrayList) {
      IntArrayList plist = (IntArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addInt(input.readSInt32());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            plist.addInt(input.readSInt32());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readSInt32());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            target.add(input.readSInt32());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  @Override
  public void readSInt64List(List<Long> target) throws IOException {
    if (target instanceof LongArrayList) {
      LongArrayList plist = (LongArrayList) target;
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            plist.addLong(input.readSInt64());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            plist.addLong(input.readSInt64());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    } else {
      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_LENGTH_DELIMITED:
          final int bytes = input.readUInt32();
          int endPos = input.getTotalBytesRead() + bytes;
          do {
            target.add(input.readSInt64());
          } while (input.getTotalBytesRead() < endPos);
          requirePosition(endPos);
          break;
        case WIRETYPE_VARINT:
          while (true) {
            target.add(input.readSInt64());
            if (input.isAtEnd()) {
              return;
            }
            int nextTag = input.readTag();
            if (nextTag != tag) {
              // We've reached the end of the repeated field. Save the next tag value.
              this.nextTag = nextTag;
              return;
            }
          }
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }
  }

  private void verifyPackedFixed64Length(int bytes) throws IOException {
    if ((bytes & FIXED64_MULTIPLE_MASK) != 0) {
      // Require that the number of bytes be a multiple of 8.
      throw InvalidProtocolBufferException.parseFailure();
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public <K, V> void readMap(
      Map<K, V> target,
      MapEntryLite.Metadata<K, V> metadata,
      ExtensionRegistryLite extensionRegistry)
      throws IOException {
    requireWireType(WIRETYPE_LENGTH_DELIMITED);
    int size = input.readUInt32();
    final int prevLimit = input.pushLimit(size);
    K key = metadata.defaultKey;
    V value = metadata.defaultValue;
    try {
      while (true) {
        int number = getFieldNumber();
        if (number == READ_DONE || input.isAtEnd()) {
          break;
        }
        try {
          switch (number) {
            case 1:
              key = (K) readField(metadata.keyType, null, null);
              break;
            case 2:
              value =
                  (V)
                      readField(
                          metadata.valueType, metadata.defaultValue.getClass(), extensionRegistry);
              break;
            default:
              if (!skipField()) {
                throw new InvalidProtocolBufferException("Unable to parse map entry.");
              }
              break;
          }
        } catch (InvalidProtocolBufferException.InvalidWireTypeException ignore) {
          // the type doesn't match, skip the field.
          if (!skipField()) {
            throw new InvalidProtocolBufferException("Unable to parse map entry.");
          }
        }
      }
      target.put(key, value);
    } finally {
      // Restore the previous limit.
      input.popLimit(prevLimit);
    }
  }

  private Object readField(
      WireFormat.FieldType fieldType, Class<?> messageType, ExtensionRegistryLite extensionRegistry)
      throws IOException {
    switch (fieldType) {
      case BOOL:
        return readBool();
      case BYTES:
        return readBytes();
      case DOUBLE:
        return readDouble();
      case ENUM:
        return readEnum();
      case FIXED32:
        return readFixed32();
      case FIXED64:
        return readFixed64();
      case FLOAT:
        return readFloat();
      case INT32:
        return readInt32();
      case INT64:
        return readInt64();
      case MESSAGE:
        return readMessage(messageType, extensionRegistry);
      case SFIXED32:
        return readSFixed32();
      case SFIXED64:
        return readSFixed64();
      case SINT32:
        return readSInt32();
      case SINT64:
        return readSInt64();
      case STRING:
        return readStringRequireUtf8();
      case UINT32:
        return readUInt32();
      case UINT64:
        return readUInt64();
      default:
        throw new RuntimeException("unsupported field type.");
    }
  }

  private void verifyPackedFixed32Length(int bytes) throws IOException {
    if ((bytes & FIXED32_MULTIPLE_MASK) != 0) {
      // Require that the number of bytes be a multiple of 4.
      throw InvalidProtocolBufferException.parseFailure();
    }
  }

  private void requirePosition(int expectedPosition) throws IOException {
    if (input.getTotalBytesRead() != expectedPosition) {
      throw InvalidProtocolBufferException.truncatedMessage();
    }
  }
}
