// 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.nio.ByteBuffer;
import java.util.List;
import java.util.Map;

/**
 * A {@link Reader} that reads from a buffer containing a message serialized with the binary
 * protocol.
 */
@ExperimentalApi
abstract class BinaryReader implements Reader {
  private static final int FIXED32_MULTIPLE_MASK = FIXED32_SIZE - 1;
  private static final int FIXED64_MULTIPLE_MASK = FIXED64_SIZE - 1;

  /**
   * Creates a new reader using the given {@code buffer} as input.
   *
   * @param buffer the input buffer. The buffer (including position, limit, etc.) will not be
   *     modified. To increment the buffer position after the read completes, use the value returned
   *     by {@link #getTotalBytesRead()}.
   * @param bufferIsImmutable if {@code true} the reader assumes that the content of {@code buffer}
   *     will never change and any allocated {@link ByteString} instances will by directly wrap
   *     slices of {@code buffer}.
   * @return the reader
   */
  public static BinaryReader newInstance(ByteBuffer buffer, boolean bufferIsImmutable) {
    if (buffer.hasArray()) {
      // TODO(nathanmittler): Add support for unsafe operations.
      return new SafeHeapReader(buffer, bufferIsImmutable);
    }
    // TODO(nathanmittler): Add support for direct buffers
    throw new IllegalArgumentException("Direct buffers not yet supported");
  }

  /** Only allow subclassing for inner classes. */
  private BinaryReader() {}

  /** Returns the total number of bytes read so far from the input buffer. */
  public abstract int getTotalBytesRead();

  @Override
  public boolean shouldDiscardUnknownFields() {
    return false;
  }

  /**
   * A {@link BinaryReader} implementation that operates on a heap {@link ByteBuffer}. Uses only
   * safe operations on the underlying array.
   */
  private static final class SafeHeapReader extends BinaryReader {
    private final boolean bufferIsImmutable;
    private final byte[] buffer;
    private int pos;
    private final int initialPos;
    private int limit;
    private int tag;
    private int endGroupTag;

    public SafeHeapReader(ByteBuffer bytebuf, boolean bufferIsImmutable) {
      this.bufferIsImmutable = bufferIsImmutable;
      buffer = bytebuf.array();
      initialPos = pos = bytebuf.arrayOffset() + bytebuf.position();
      limit = bytebuf.arrayOffset() + bytebuf.limit();
    }

    private boolean isAtEnd() {
      return pos == limit;
    }

    @Override
    public int getTotalBytesRead() {
      return pos - initialPos;
    }

    @Override
    public int getFieldNumber() throws IOException {
      if (isAtEnd()) {
        return Reader.READ_DONE;
      }
      tag = readVarint32();
      if (tag == endGroupTag) {
        return Reader.READ_DONE;
      }
      return WireFormat.getTagFieldNumber(tag);
    }

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

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

      switch (WireFormat.getTagWireType(tag)) {
        case WIRETYPE_VARINT:
          skipVarint();
          return true;
        case WIRETYPE_FIXED64:
          skipBytes(FIXED64_SIZE);
          return true;
        case WIRETYPE_LENGTH_DELIMITED:
          skipBytes(readVarint32());
          return true;
        case WIRETYPE_FIXED32:
          skipBytes(FIXED32_SIZE);
          return true;
        case WIRETYPE_START_GROUP:
          skipGroup();
          return true;
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }

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

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

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

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

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

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

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

    @Override
    public boolean readBool() throws IOException {
      requireWireType(WIRETYPE_VARINT);
      return readVarint32() != 0;
    }

    @Override
    public String readString() throws IOException {
      return readStringInternal(false);
    }

    @Override
    public String readStringRequireUtf8() throws IOException {
      return readStringInternal(true);
    }

    public String readStringInternal(boolean requireUtf8) throws IOException {
      requireWireType(WIRETYPE_LENGTH_DELIMITED);
      final int size = readVarint32();
      if (size == 0) {
        return "";
      }

      requireBytes(size);
      if (requireUtf8 && !Utf8.isValidUtf8(buffer, pos, pos + size)) {
        throw InvalidProtocolBufferException.invalidUtf8();
      }
      String result = new String(buffer, pos, size, Internal.UTF_8);
      pos += size;
      return result;
    }

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

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

    private <T> T readMessage(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
        throws IOException {
      int size = readVarint32();
      requireBytes(size);

      // Update the limit.
      int prevLimit = limit;
      int newLimit = pos + size;
      limit = newLimit;

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

        if (pos != newLimit) {
          throw InvalidProtocolBufferException.parseFailure();
        }
        return message;
      } finally {
        // Restore the limit.
        limit = prevLimit;
      }
    }

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

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

    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);
      int size = readVarint32();
      if (size == 0) {
        return ByteString.EMPTY;
      }

      requireBytes(size);
      ByteString bytes =
          bufferIsImmutable
              ? ByteString.wrap(buffer, pos, size)
              : ByteString.copyFrom(buffer, pos, size);
      pos += size;
      return bytes;
    }

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

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

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

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

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

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

    @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 = readVarint32();
            verifyPackedFixed64Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addDouble(Double.longBitsToDouble(readLittleEndian64_NoCheck()));
            }
            break;
          case WIRETYPE_FIXED64:
            while (true) {
              plist.addDouble(readDouble());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            verifyPackedFixed64Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(Double.longBitsToDouble(readLittleEndian64_NoCheck()));
            }
            break;
          case WIRETYPE_FIXED64:
            while (true) {
              target.add(readDouble());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            verifyPackedFixed32Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addFloat(Float.intBitsToFloat(readLittleEndian32_NoCheck()));
            }
            break;
          case WIRETYPE_FIXED32:
            while (true) {
              plist.addFloat(readFloat());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            verifyPackedFixed32Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(Float.intBitsToFloat(readLittleEndian32_NoCheck()));
            }
            break;
          case WIRETYPE_FIXED32:
            while (true) {
              target.add(readFloat());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addLong(readVarint64());
            }
            requirePosition(fieldEndPos);
            break;
          case WIRETYPE_VARINT:
            while (true) {
              plist.addLong(readUInt64());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(readVarint64());
            }
            requirePosition(fieldEndPos);
            break;
          case WIRETYPE_VARINT:
            while (true) {
              target.add(readUInt64());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addLong(readVarint64());
            }
            requirePosition(fieldEndPos);
            break;
          case WIRETYPE_VARINT:
            while (true) {
              plist.addLong(readInt64());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(readVarint64());
            }
            requirePosition(fieldEndPos);
            break;
          case WIRETYPE_VARINT:
            while (true) {
              target.add(readInt64());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addInt(readVarint32());
            }
            requirePosition(fieldEndPos);
            break;
          case WIRETYPE_VARINT:
            while (true) {
              plist.addInt(readInt32());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(readVarint32());
            }
            requirePosition(fieldEndPos);
            break;
          case WIRETYPE_VARINT:
            while (true) {
              target.add(readInt32());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            verifyPackedFixed64Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addLong(readLittleEndian64_NoCheck());
            }
            break;
          case WIRETYPE_FIXED64:
            while (true) {
              plist.addLong(readFixed64());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            verifyPackedFixed64Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(readLittleEndian64_NoCheck());
            }
            break;
          case WIRETYPE_FIXED64:
            while (true) {
              target.add(readFixed64());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            verifyPackedFixed32Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addInt(readLittleEndian32_NoCheck());
            }
            break;
          case WIRETYPE_FIXED32:
            while (true) {
              plist.addInt(readFixed32());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            verifyPackedFixed32Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(readLittleEndian32_NoCheck());
            }
            break;
          case WIRETYPE_FIXED32:
            while (true) {
              target.add(readFixed32());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addBoolean(readVarint32() != 0);
            }
            requirePosition(fieldEndPos);
            break;
          case WIRETYPE_VARINT:
            while (true) {
              plist.addBoolean(readBool());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(readVarint32() != 0);
            }
            requirePosition(fieldEndPos);
            break;
          case WIRETYPE_VARINT:
            while (true) {
              target.add(readBool());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 (isAtEnd()) {
            return;
          }
          int prevPos = pos;
          int nextTag = readVarint32();
          if (nextTag != tag) {
            // We've reached the end of the repeated field. Rewind the buffer position to before
            // the new tag.
            pos = prevPos;
            return;
          }
        }
      } else {
        while (true) {
          target.add(readStringInternal(requireUtf8));

          if (isAtEnd()) {
            return;
          }
          int prevPos = pos;
          int nextTag = readVarint32();
          if (nextTag != tag) {
            // We've reached the end of the repeated field. Rewind the buffer position to before
            // the new tag.
            pos = prevPos;
            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 (isAtEnd()) {
          return;
        }
        int prevPos = pos;
        int nextTag = readVarint32();
        if (nextTag != listTag) {
          // We've reached the end of the repeated field. Rewind the buffer position to before
          // the new tag.
          pos = prevPos;
          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 (isAtEnd()) {
          return;
        }
        int prevPos = pos;
        int nextTag = readVarint32();
        if (nextTag != listTag) {
          // We've reached the end of the repeated field. Rewind the buffer position to before
          // the new tag.
          pos = prevPos;
          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 (isAtEnd()) {
          return;
        }
        int prevPos = pos;
        int nextTag = readVarint32();
        if (nextTag != tag) {
          // We've reached the end of the repeated field. Rewind the buffer position to before
          // the new tag.
          pos = prevPos;
          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 = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addInt(readVarint32());
            }
            break;
          case WIRETYPE_VARINT:
            while (true) {
              plist.addInt(readUInt32());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(readVarint32());
            }
            break;
          case WIRETYPE_VARINT:
            while (true) {
              target.add(readUInt32());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addInt(readVarint32());
            }
            break;
          case WIRETYPE_VARINT:
            while (true) {
              plist.addInt(readEnum());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(readVarint32());
            }
            break;
          case WIRETYPE_VARINT:
            while (true) {
              target.add(readEnum());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            verifyPackedFixed32Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addInt(readLittleEndian32_NoCheck());
            }
            break;
          case WIRETYPE_FIXED32:
            while (true) {
              plist.addInt(readSFixed32());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            verifyPackedFixed32Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(readLittleEndian32_NoCheck());
            }
            break;
          case WIRETYPE_FIXED32:
            while (true) {
              target.add(readSFixed32());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            verifyPackedFixed64Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addLong(readLittleEndian64_NoCheck());
            }
            break;
          case WIRETYPE_FIXED64:
            while (true) {
              plist.addLong(readSFixed64());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            verifyPackedFixed64Length(bytes);
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(readLittleEndian64_NoCheck());
            }
            break;
          case WIRETYPE_FIXED64:
            while (true) {
              target.add(readSFixed64());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addInt(CodedInputStream.decodeZigZag32(readVarint32()));
            }
            break;
          case WIRETYPE_VARINT:
            while (true) {
              plist.addInt(readSInt32());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(CodedInputStream.decodeZigZag32(readVarint32()));
            }
            break;
          case WIRETYPE_VARINT:
            while (true) {
              target.add(readSInt32());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                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 = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              plist.addLong(CodedInputStream.decodeZigZag64(readVarint64()));
            }
            break;
          case WIRETYPE_VARINT:
            while (true) {
              plist.addLong(readSInt64());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      } else {
        switch (WireFormat.getTagWireType(tag)) {
          case WIRETYPE_LENGTH_DELIMITED:
            final int bytes = readVarint32();
            final int fieldEndPos = pos + bytes;
            while (pos < fieldEndPos) {
              target.add(CodedInputStream.decodeZigZag64(readVarint64()));
            }
            break;
          case WIRETYPE_VARINT:
            while (true) {
              target.add(readSInt64());

              if (isAtEnd()) {
                return;
              }
              int prevPos = pos;
              int nextTag = readVarint32();
              if (nextTag != tag) {
                // We've reached the end of the repeated field. Rewind the buffer position to before
                // the new tag.
                pos = prevPos;
                return;
              }
            }
          default:
            throw InvalidProtocolBufferException.invalidWireType();
        }
      }
    }

    @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 = readVarint32();
      requireBytes(size);

      // Update the limit.
      int prevLimit = limit;
      int newLimit = pos + size;
      limit = newLimit;

      try {
        K key = metadata.defaultKey;
        V value = metadata.defaultValue;
        while (true) {
          int number = getFieldNumber();
          if (number == READ_DONE) {
            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 limit.
        limit = 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.");
      }
    }

    /** Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits. */
    private int readVarint32() throws IOException {
      // See implementation notes for readRawVarint64
      int i = pos;

      if (limit == pos) {
        throw InvalidProtocolBufferException.truncatedMessage();
      }

      int x;
      if ((x = buffer[i++]) >= 0) {
        pos = i;
        return x;
      } else if (limit - i < 9) {
        return (int) readVarint64SlowPath();
      } else if ((x ^= (buffer[i++] << 7)) < 0) {
        x ^= (~0 << 7);
      } else if ((x ^= (buffer[i++] << 14)) >= 0) {
        x ^= (~0 << 7) ^ (~0 << 14);
      } else if ((x ^= (buffer[i++] << 21)) < 0) {
        x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
      } else {
        int y = buffer[i++];
        x ^= y << 28;
        x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
        if (y < 0
            && buffer[i++] < 0
            && buffer[i++] < 0
            && buffer[i++] < 0
            && buffer[i++] < 0
            && buffer[i++] < 0) {
          throw InvalidProtocolBufferException.malformedVarint();
        }
      }
      pos = i;
      return x;
    }

    public long readVarint64() throws IOException {
      // Implementation notes:
      //
      // Optimized for one-byte values, expected to be common.
      // The particular code below was selected from various candidates
      // empirically, by winning VarintBenchmark.
      //
      // Sign extension of (signed) Java bytes is usually a nuisance, but
      // we exploit it here to more easily obtain the sign of bytes read.
      // Instead of cleaning up the sign extension bits by masking eagerly,
      // we delay until we find the final (positive) byte, when we clear all
      // accumulated bits with one xor.  We depend on javac to constant fold.
      int i = pos;

      if (limit == i) {
        throw InvalidProtocolBufferException.truncatedMessage();
      }

      final byte[] buffer = this.buffer;
      long x;
      int y;
      if ((y = buffer[i++]) >= 0) {
        pos = i;
        return y;
      } else if (limit - i < 9) {
        return readVarint64SlowPath();
      } else if ((y ^= (buffer[i++] << 7)) < 0) {
        x = y ^ (~0 << 7);
      } else if ((y ^= (buffer[i++] << 14)) >= 0) {
        x = y ^ ((~0 << 7) ^ (~0 << 14));
      } else if ((y ^= (buffer[i++] << 21)) < 0) {
        x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
      } else if ((x = y ^ ((long) buffer[i++] << 28)) >= 0L) {
        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
      } else if ((x ^= ((long) buffer[i++] << 35)) < 0L) {
        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
      } else if ((x ^= ((long) buffer[i++] << 42)) >= 0L) {
        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
      } else if ((x ^= ((long) buffer[i++] << 49)) < 0L) {
        x ^=
            (~0L << 7)
                ^ (~0L << 14)
                ^ (~0L << 21)
                ^ (~0L << 28)
                ^ (~0L << 35)
                ^ (~0L << 42)
                ^ (~0L << 49);
      } else {
        x ^= ((long) buffer[i++] << 56);
        x ^=
            (~0L << 7)
                ^ (~0L << 14)
                ^ (~0L << 21)
                ^ (~0L << 28)
                ^ (~0L << 35)
                ^ (~0L << 42)
                ^ (~0L << 49)
                ^ (~0L << 56);
        if (x < 0L) {
          if (buffer[i++] < 0L) {
            throw InvalidProtocolBufferException.malformedVarint();
          }
        }
      }
      pos = i;
      return x;
    }

    private long readVarint64SlowPath() throws IOException {
      long result = 0;
      for (int shift = 0; shift < 64; shift += 7) {
        final byte b = readByte();
        result |= (long) (b & 0x7F) << shift;
        if ((b & 0x80) == 0) {
          return result;
        }
      }
      throw InvalidProtocolBufferException.malformedVarint();
    }

    private byte readByte() throws IOException {
      if (pos == limit) {
        throw InvalidProtocolBufferException.truncatedMessage();
      }
      return buffer[pos++];
    }

    private int readLittleEndian32() throws IOException {
      requireBytes(FIXED32_SIZE);
      return readLittleEndian32_NoCheck();
    }

    private long readLittleEndian64() throws IOException {
      requireBytes(FIXED64_SIZE);
      return readLittleEndian64_NoCheck();
    }

    private int readLittleEndian32_NoCheck() {
      int p = pos;
      final byte[] buffer = this.buffer;
      pos = p + FIXED32_SIZE;
      return (((buffer[p] & 0xff))
          | ((buffer[p + 1] & 0xff) << 8)
          | ((buffer[p + 2] & 0xff) << 16)
          | ((buffer[p + 3] & 0xff) << 24));
    }

    private long readLittleEndian64_NoCheck() {
      int p = pos;
      final byte[] buffer = this.buffer;
      pos = p + FIXED64_SIZE;
      return (((buffer[p] & 0xffL))
          | ((buffer[p + 1] & 0xffL) << 8)
          | ((buffer[p + 2] & 0xffL) << 16)
          | ((buffer[p + 3] & 0xffL) << 24)
          | ((buffer[p + 4] & 0xffL) << 32)
          | ((buffer[p + 5] & 0xffL) << 40)
          | ((buffer[p + 6] & 0xffL) << 48)
          | ((buffer[p + 7] & 0xffL) << 56));
    }

    private void skipVarint() throws IOException {
      if (limit - pos >= 10) {
        final byte[] buffer = this.buffer;
        int p = pos;
        for (int i = 0; i < 10; i++) {
          if (buffer[p++] >= 0) {
            pos = p;
            return;
          }
        }
      }
      skipVarintSlowPath();
    }

    private void skipVarintSlowPath() throws IOException {
      for (int i = 0; i < 10; i++) {
        if (readByte() >= 0) {
          return;
        }
      }
      throw InvalidProtocolBufferException.malformedVarint();
    }

    private void skipBytes(final int size) throws IOException {
      requireBytes(size);

      pos += size;
    }

    private void skipGroup() throws IOException {
      int prevEndGroupTag = endGroupTag;
      endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP);
      while (true) {
        if (getFieldNumber() == READ_DONE || !skipField()) {
          break;
        }
      }
      if (tag != endGroupTag) {
        throw InvalidProtocolBufferException.parseFailure();
      }
      endGroupTag = prevEndGroupTag;
    }

    private void requireBytes(int size) throws IOException {
      if (size < 0 || size > (limit - pos)) {
        throw InvalidProtocolBufferException.truncatedMessage();
      }
    }

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

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

    private void verifyPackedFixed32Length(int bytes) throws IOException {
      requireBytes(bytes);
      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 (pos != expectedPosition) {
        throw InvalidProtocolBufferException.truncatedMessage();
      }
    }
  }
}
