package com.google.protobuf;
import static com.google.protobuf.Internal.EMPTY_BYTE_ARRAY;
import static com.google.protobuf.Internal.EMPTY_BYTE_BUFFER;
import static com.google.protobuf.Internal.UTF_8;
import static com.google.protobuf.Internal.checkNotNull;
import static com.google.protobuf.WireFormat.FIXED32_SIZE;
import static com.google.protobuf.WireFormat.FIXED64_SIZE;
import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public abstract class CodedInputStream {
private static final int DEFAULT_BUFFER_SIZE = 4096;
private static final int DEFAULT_RECURSION_LIMIT = 100;
private static final int DEFAULT_SIZE_LIMIT = Integer.MAX_VALUE;
int recursionDepth;
int recursionLimit = DEFAULT_RECURSION_LIMIT;
int sizeLimit = DEFAULT_SIZE_LIMIT;
CodedInputStreamReader wrapper;
public static CodedInputStream newInstance(final InputStream input) {
return newInstance(input, DEFAULT_BUFFER_SIZE);
}
public static CodedInputStream newInstance(final InputStream input, int bufferSize) {
if (bufferSize <= 0) {
throw new IllegalArgumentException("bufferSize must be > 0");
}
if (input == null) {
return newInstance(EMPTY_BYTE_ARRAY);
}
return new StreamDecoder(input, bufferSize);
}
public static CodedInputStream newInstance(final Iterable<ByteBuffer> input) {
if (!UnsafeDirectNioDecoder.isSupported()) {
return newInstance(new IterableByteBufferInputStream(input));
}
return newInstance(input, false);
}
static CodedInputStream newInstance(
final Iterable<ByteBuffer> bufs, final boolean bufferIsImmutable) {
int flag = 0;
int totalSize = 0;
for (ByteBuffer buf : bufs) {
totalSize += buf.remaining();
if (buf.hasArray()) {
flag |= 1;
} else if (buf.isDirect()) {
flag |= 2;
} else {
flag |= 4;
}
}
if (flag == 2) {
return new IterableDirectByteBufferDecoder(bufs, totalSize, bufferIsImmutable);
} else {
return newInstance(new IterableByteBufferInputStream(bufs));
}
}
public static CodedInputStream newInstance(final byte[] buf) {
return newInstance(buf, 0, buf.length);
}
public static CodedInputStream newInstance(final byte[] buf, final int off, final int len) {
return newInstance(buf, off, len, false);
}
static CodedInputStream newInstance(
final byte[] buf, final int off, final int len, final boolean bufferIsImmutable) {
ArrayDecoder result = new ArrayDecoder(buf, off, len, bufferIsImmutable);
try {
result.pushLimit(len);
} catch (InvalidProtocolBufferException ex) {
throw new IllegalArgumentException(ex);
}
return result;
}
public static CodedInputStream newInstance(ByteBuffer buf) {
return newInstance(buf, false);
}
static CodedInputStream newInstance(ByteBuffer buf, boolean bufferIsImmutable) {
if (buf.hasArray()) {
return newInstance(
buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), bufferIsImmutable);
}
if (buf.isDirect() && UnsafeDirectNioDecoder.isSupported()) {
return new UnsafeDirectNioDecoder(buf, bufferIsImmutable);
}
byte[] buffer = new byte[buf.remaining()];
buf.duplicate().get(buffer);
return newInstance(buffer, 0, buffer.length, true);
}
private CodedInputStream() {}
public abstract int readTag() throws IOException;
public abstract void checkLastTagWas(final int value) throws InvalidProtocolBufferException;
public abstract int getLastTag();
public abstract boolean skipField(final int tag) throws IOException;
@Deprecated
public abstract boolean skipField(final int tag, final CodedOutputStream output)
throws IOException;
public abstract void skipMessage() throws IOException;
public abstract void skipMessage(CodedOutputStream output) throws IOException;
public abstract double readDouble() throws IOException;
public abstract float readFloat() throws IOException;
public abstract long readUInt64() throws IOException;
public abstract long readInt64() throws IOException;
public abstract int readInt32() throws IOException;
public abstract long readFixed64() throws IOException;
public abstract int readFixed32() throws IOException;
public abstract boolean readBool() throws IOException;
public abstract String readString() throws IOException;
public abstract String readStringRequireUtf8() throws IOException;
public abstract void readGroup(
final int fieldNumber,
final MessageLite.Builder builder,
final ExtensionRegistryLite extensionRegistry)
throws IOException;
public abstract <T extends MessageLite> T readGroup(
final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)
throws IOException;
@Deprecated
public abstract void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
throws IOException;
public abstract void readMessage(
final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
throws IOException;
public abstract <T extends MessageLite> T readMessage(
final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException;
public abstract ByteString readBytes() throws IOException;
public abstract byte[] readByteArray() throws IOException;
public abstract ByteBuffer readByteBuffer() throws IOException;
public abstract int readUInt32() throws IOException;
public abstract int readEnum() throws IOException;
public abstract int readSFixed32() throws IOException;
public abstract long readSFixed64() throws IOException;
public abstract int readSInt32() throws IOException;
public abstract long readSInt64() throws IOException;
public abstract int readRawVarint32() throws IOException;
public abstract long readRawVarint64() throws IOException;
abstract long readRawVarint64SlowPath() throws IOException;
public abstract int readRawLittleEndian32() throws IOException;
public abstract long readRawLittleEndian64() throws IOException;
public abstract void enableAliasing(boolean enabled);
public final int setRecursionLimit(final int limit) {
if (limit < 0) {
throw new IllegalArgumentException("Recursion limit cannot be negative: " + limit);
}
final int oldLimit = recursionLimit;
recursionLimit = limit;
return oldLimit;
}
public final int setSizeLimit(final int limit) {
if (limit < 0) {
throw new IllegalArgumentException("Size limit cannot be negative: " + limit);
}
final int oldLimit = sizeLimit;
sizeLimit = limit;
return oldLimit;
}
private boolean shouldDiscardUnknownFields = false;
final void discardUnknownFields() {
shouldDiscardUnknownFields = true;
}
final void unsetDiscardUnknownFields() {
shouldDiscardUnknownFields = false;
}
final boolean shouldDiscardUnknownFields() {
return shouldDiscardUnknownFields;
}
public abstract void resetSizeCounter();
public abstract int pushLimit(int byteLimit) throws InvalidProtocolBufferException;
public abstract void popLimit(final int oldLimit);
public abstract int getBytesUntilLimit();
public abstract boolean isAtEnd() throws IOException;
public abstract int getTotalBytesRead();
public abstract byte readRawByte() throws IOException;
public abstract byte[] readRawBytes(final int size) throws IOException;
public abstract void skipRawBytes(final int size) throws IOException;
public static int decodeZigZag32(final int n) {
return (n >>> 1) ^ -(n & 1);
}
public static long decodeZigZag64(final long n) {
return (n >>> 1) ^ -(n & 1);
}
public static int readRawVarint32(final int firstByte, final InputStream input)
throws IOException {
if ((firstByte & 0x80) == 0) {
return firstByte;
}
int result = firstByte & 0x7f;
int offset = 7;
for (; offset < 32; offset += 7) {
final int b = input.read();
if (b == -1) {
throw InvalidProtocolBufferException.truncatedMessage();
}
result |= (b & 0x7f) << offset;
if ((b & 0x80) == 0) {
return result;
}
}
for (; offset < 64; offset += 7) {
final int b = input.read();
if (b == -1) {
throw InvalidProtocolBufferException.truncatedMessage();
}
if ((b & 0x80) == 0) {
return result;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
static int readRawVarint32(final InputStream input) throws IOException {
final int firstByte = input.read();
if (firstByte == -1) {
throw InvalidProtocolBufferException.truncatedMessage();
}
return readRawVarint32(firstByte, input);
}
private static final class ArrayDecoder extends CodedInputStream {
private final byte[] buffer;
private final boolean immutable;
private int limit;
private int bufferSizeAfterLimit;
private int pos;
private int startPos;
private int lastTag;
private boolean enableAliasing;
private int currentLimit = Integer.MAX_VALUE;
private ArrayDecoder(final byte[] buffer, final int offset, final int len, boolean immutable) {
this.buffer = buffer;
limit = offset + len;
pos = offset;
startPos = pos;
this.immutable = immutable;
}
@Override
public int readTag() throws IOException {
if (isAtEnd()) {
lastTag = 0;
return 0;
}
lastTag = readRawVarint32();
if (WireFormat.getTagFieldNumber(lastTag) == 0) {
throw InvalidProtocolBufferException.invalidTag();
}
return lastTag;
}
@Override
public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
if (lastTag != value) {
throw InvalidProtocolBufferException.invalidEndTag();
}
}
@Override
public int getLastTag() {
return lastTag;
}
@Override
public boolean skipField(final int tag) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
skipRawVarint();
return true;
case WireFormat.WIRETYPE_FIXED64:
skipRawBytes(FIXED64_SIZE);
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
skipRawBytes(readRawVarint32());
return true;
case WireFormat.WIRETYPE_START_GROUP:
skipMessage();
checkLastTagWas(
WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
return true;
case WireFormat.WIRETYPE_END_GROUP:
return false;
case WireFormat.WIRETYPE_FIXED32:
skipRawBytes(FIXED32_SIZE);
return true;
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}
@Override
public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
{
long value = readInt64();
output.writeRawVarint32(tag);
output.writeUInt64NoTag(value);
return true;
}
case WireFormat.WIRETYPE_FIXED64:
{
long value = readRawLittleEndian64();
output.writeRawVarint32(tag);
output.writeFixed64NoTag(value);
return true;
}
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
{
ByteString value = readBytes();
output.writeRawVarint32(tag);
output.writeBytesNoTag(value);
return true;
}
case WireFormat.WIRETYPE_START_GROUP:
{
output.writeRawVarint32(tag);
skipMessage(output);
int endtag =
WireFormat.makeTag(
WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
checkLastTagWas(endtag);
output.writeRawVarint32(endtag);
return true;
}
case WireFormat.WIRETYPE_END_GROUP:
{
return false;
}
case WireFormat.WIRETYPE_FIXED32:
{
int value = readRawLittleEndian32();
output.writeRawVarint32(tag);
output.writeFixed32NoTag(value);
return true;
}
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}
@Override
public void skipMessage() throws IOException {
while (true) {
final int tag = readTag();
if (tag == 0 || !skipField(tag)) {
return;
}
}
}
@Override
public void skipMessage(CodedOutputStream output) throws IOException {
while (true) {
final int tag = readTag();
if (tag == 0 || !skipField(tag, output)) {
return;
}
}
}
@Override
public double readDouble() throws IOException {
return Double.longBitsToDouble(readRawLittleEndian64());
}
@Override
public float readFloat() throws IOException {
return Float.intBitsToFloat(readRawLittleEndian32());
}
@Override
public long readUInt64() throws IOException {
return readRawVarint64();
}
@Override
public long readInt64() throws IOException {
return readRawVarint64();
}
@Override
public int readInt32() throws IOException {
return readRawVarint32();
}
@Override
public long readFixed64() throws IOException {
return readRawLittleEndian64();
}
@Override
public int readFixed32() throws IOException {
return readRawLittleEndian32();
}
@Override
public boolean readBool() throws IOException {
return readRawVarint64() != 0;
}
@Override
public String readString() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= (limit - pos)) {
final String result = new String(buffer, pos, size, UTF_8);
pos += size;
return result;
}
if (size == 0) {
return "";
}
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public String readStringRequireUtf8() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= (limit - pos)) {
String result = Utf8.decodeUtf8(buffer, pos, size);
pos += size;
return result;
}
if (size == 0) {
return "";
}
if (size <= 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public void readGroup(
final int fieldNumber,
final MessageLite.Builder builder,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
++recursionDepth;
builder.mergeFrom(this, extensionRegistry);
checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
--recursionDepth;
}
@Override
public <T extends MessageLite> T readGroup(
final int fieldNumber,
final Parser<T> parser,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
++recursionDepth;
T result = parser.parsePartialFrom(this, extensionRegistry);
checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
--recursionDepth;
return result;
}
@Deprecated
@Override
public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
throws IOException {
readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
}
@Override
public void readMessage(
final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
throws IOException {
final int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
final int oldLimit = pushLimit(length);
++recursionDepth;
builder.mergeFrom(this, extensionRegistry);
checkLastTagWas(0);
--recursionDepth;
popLimit(oldLimit);
}
@Override
public <T extends MessageLite> T readMessage(
final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
final int oldLimit = pushLimit(length);
++recursionDepth;
T result = parser.parsePartialFrom(this, extensionRegistry);
checkLastTagWas(0);
--recursionDepth;
popLimit(oldLimit);
return result;
}
@Override
public ByteString readBytes() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= (limit - pos)) {
final ByteString result =
immutable && enableAliasing
? ByteString.wrap(buffer, pos, size)
: ByteString.copyFrom(buffer, pos, size);
pos += size;
return result;
}
if (size == 0) {
return ByteString.EMPTY;
}
return ByteString.wrap(readRawBytes(size));
}
@Override
public byte[] readByteArray() throws IOException {
final int size = readRawVarint32();
return readRawBytes(size);
}
@Override
public ByteBuffer readByteBuffer() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= (limit - pos)) {
ByteBuffer result =
!immutable && enableAliasing
? ByteBuffer.wrap(buffer, pos, size).slice()
: ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size));
pos += size;
return result;
}
if (size == 0) {
return EMPTY_BYTE_BUFFER;
}
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public int readUInt32() throws IOException {
return readRawVarint32();
}
@Override
public int readEnum() throws IOException {
return readRawVarint32();
}
@Override
public int readSFixed32() throws IOException {
return readRawLittleEndian32();
}
@Override
public long readSFixed64() throws IOException {
return readRawLittleEndian64();
}
@Override
public int readSInt32() throws IOException {
return decodeZigZag32(readRawVarint32());
}
@Override
public long readSInt64() throws IOException {
return decodeZigZag64(readRawVarint64());
}
@Override
public int readRawVarint32() throws IOException {
fastpath:
{
int tempPos = pos;
if (limit == tempPos) {
break fastpath;
}
final byte[] buffer = this.buffer;
int x;
if ((x = buffer[tempPos++]) >= 0) {
pos = tempPos;
return x;
} else if (limit - tempPos < 9) {
break fastpath;
} else if ((x ^= (buffer[tempPos++] << 7)) < 0) {
x ^= (~0 << 7);
} else if ((x ^= (buffer[tempPos++] << 14)) >= 0) {
x ^= (~0 << 7) ^ (~0 << 14);
} else if ((x ^= (buffer[tempPos++] << 21)) < 0) {
x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
} else {
int y = buffer[tempPos++];
x ^= y << 28;
x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
if (y < 0
&& buffer[tempPos++] < 0
&& buffer[tempPos++] < 0
&& buffer[tempPos++] < 0
&& buffer[tempPos++] < 0
&& buffer[tempPos++] < 0) {
break fastpath;
}
}
pos = tempPos;
return x;
}
return (int) readRawVarint64SlowPath();
}
private void skipRawVarint() throws IOException {
if (limit - pos >= MAX_VARINT_SIZE) {
skipRawVarintFastPath();
} else {
skipRawVarintSlowPath();
}
}
private void skipRawVarintFastPath() throws IOException {
for (int i = 0; i < MAX_VARINT_SIZE; i++) {
if (buffer[pos++] >= 0) {
return;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
private void skipRawVarintSlowPath() throws IOException {
for (int i = 0; i < MAX_VARINT_SIZE; i++) {
if (readRawByte() >= 0) {
return;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
@Override
public long readRawVarint64() throws IOException {
fastpath:
{
int tempPos = pos;
if (limit == tempPos) {
break fastpath;
}
final byte[] buffer = this.buffer;
long x;
int y;
if ((y = buffer[tempPos++]) >= 0) {
pos = tempPos;
return y;
} else if (limit - tempPos < 9) {
break fastpath;
} else if ((y ^= (buffer[tempPos++] << 7)) < 0) {
x = y ^ (~0 << 7);
} else if ((y ^= (buffer[tempPos++] << 14)) >= 0) {
x = y ^ ((~0 << 7) ^ (~0 << 14));
} else if ((y ^= (buffer[tempPos++] << 21)) < 0) {
x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
} else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
} else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
} else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
} else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) {
x ^=
(~0L << 7)
^ (~0L << 14)
^ (~0L << 21)
^ (~0L << 28)
^ (~0L << 35)
^ (~0L << 42)
^ (~0L << 49);
} else {
x ^= ((long) buffer[tempPos++] << 56);
x ^=
(~0L << 7)
^ (~0L << 14)
^ (~0L << 21)
^ (~0L << 28)
^ (~0L << 35)
^ (~0L << 42)
^ (~0L << 49)
^ (~0L << 56);
if (x < 0L) {
if (buffer[tempPos++] < 0L) {
break fastpath;
}
}
}
pos = tempPos;
return x;
}
return readRawVarint64SlowPath();
}
@Override
long readRawVarint64SlowPath() throws IOException {
long result = 0;
for (int shift = 0; shift < 64; shift += 7) {
final byte b = readRawByte();
result |= (long) (b & 0x7F) << shift;
if ((b & 0x80) == 0) {
return result;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
@Override
public int readRawLittleEndian32() throws IOException {
int tempPos = pos;
if (limit - tempPos < FIXED32_SIZE) {
throw InvalidProtocolBufferException.truncatedMessage();
}
final byte[] buffer = this.buffer;
pos = tempPos + FIXED32_SIZE;
return (((buffer[tempPos] & 0xff))
| ((buffer[tempPos + 1] & 0xff) << 8)
| ((buffer[tempPos + 2] & 0xff) << 16)
| ((buffer[tempPos + 3] & 0xff) << 24));
}
@Override
public long readRawLittleEndian64() throws IOException {
int tempPos = pos;
if (limit - tempPos < FIXED64_SIZE) {
throw InvalidProtocolBufferException.truncatedMessage();
}
final byte[] buffer = this.buffer;
pos = tempPos + FIXED64_SIZE;
return (((buffer[tempPos] & 0xffL))
| ((buffer[tempPos + 1] & 0xffL) << 8)
| ((buffer[tempPos + 2] & 0xffL) << 16)
| ((buffer[tempPos + 3] & 0xffL) << 24)
| ((buffer[tempPos + 4] & 0xffL) << 32)
| ((buffer[tempPos + 5] & 0xffL) << 40)
| ((buffer[tempPos + 6] & 0xffL) << 48)
| ((buffer[tempPos + 7] & 0xffL) << 56));
}
@Override
public void enableAliasing(boolean enabled) {
this.enableAliasing = enabled;
}
@Override
public void resetSizeCounter() {
startPos = pos;
}
@Override
public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
if (byteLimit < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
byteLimit += getTotalBytesRead();
final int oldLimit = currentLimit;
if (byteLimit > oldLimit) {
throw InvalidProtocolBufferException.truncatedMessage();
}
currentLimit = byteLimit;
recomputeBufferSizeAfterLimit();
return oldLimit;
}
private void recomputeBufferSizeAfterLimit() {
limit += bufferSizeAfterLimit;
final int bufferEnd = limit - startPos;
if (bufferEnd > currentLimit) {
bufferSizeAfterLimit = bufferEnd - currentLimit;
limit -= bufferSizeAfterLimit;
} else {
bufferSizeAfterLimit = 0;
}
}
@Override
public void popLimit(final int oldLimit) {
currentLimit = oldLimit;
recomputeBufferSizeAfterLimit();
}
@Override
public int getBytesUntilLimit() {
if (currentLimit == Integer.MAX_VALUE) {
return -1;
}
return currentLimit - getTotalBytesRead();
}
@Override
public boolean isAtEnd() throws IOException {
return pos == limit;
}
@Override
public int getTotalBytesRead() {
return pos - startPos;
}
@Override
public byte readRawByte() throws IOException {
if (pos == limit) {
throw InvalidProtocolBufferException.truncatedMessage();
}
return buffer[pos++];
}
@Override
public byte[] readRawBytes(final int length) throws IOException {
if (length > 0 && length <= (limit - pos)) {
final int tempPos = pos;
pos += length;
return Arrays.copyOfRange(buffer, tempPos, pos);
}
if (length <= 0) {
if (length == 0) {
return Internal.EMPTY_BYTE_ARRAY;
} else {
throw InvalidProtocolBufferException.negativeSize();
}
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public void skipRawBytes(final int length) throws IOException {
if (length >= 0 && length <= (limit - pos)) {
pos += length;
return;
}
if (length < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
}
private static final class UnsafeDirectNioDecoder extends CodedInputStream {
private final ByteBuffer buffer;
private final boolean immutable;
private final long address;
private long limit;
private long pos;
private long startPos;
private int bufferSizeAfterLimit;
private int lastTag;
private boolean enableAliasing;
private int currentLimit = Integer.MAX_VALUE;
static boolean isSupported() {
return UnsafeUtil.hasUnsafeByteBufferOperations();
}
private UnsafeDirectNioDecoder(ByteBuffer buffer, boolean immutable) {
this.buffer = buffer;
address = UnsafeUtil.addressOffset(buffer);
limit = address + buffer.limit();
pos = address + buffer.position();
startPos = pos;
this.immutable = immutable;
}
@Override
public int readTag() throws IOException {
if (isAtEnd()) {
lastTag = 0;
return 0;
}
lastTag = readRawVarint32();
if (WireFormat.getTagFieldNumber(lastTag) == 0) {
throw InvalidProtocolBufferException.invalidTag();
}
return lastTag;
}
@Override
public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
if (lastTag != value) {
throw InvalidProtocolBufferException.invalidEndTag();
}
}
@Override
public int getLastTag() {
return lastTag;
}
@Override
public boolean skipField(final int tag) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
skipRawVarint();
return true;
case WireFormat.WIRETYPE_FIXED64:
skipRawBytes(FIXED64_SIZE);
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
skipRawBytes(readRawVarint32());
return true;
case WireFormat.WIRETYPE_START_GROUP:
skipMessage();
checkLastTagWas(
WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
return true;
case WireFormat.WIRETYPE_END_GROUP:
return false;
case WireFormat.WIRETYPE_FIXED32:
skipRawBytes(FIXED32_SIZE);
return true;
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}
@Override
public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
{
long value = readInt64();
output.writeRawVarint32(tag);
output.writeUInt64NoTag(value);
return true;
}
case WireFormat.WIRETYPE_FIXED64:
{
long value = readRawLittleEndian64();
output.writeRawVarint32(tag);
output.writeFixed64NoTag(value);
return true;
}
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
{
ByteString value = readBytes();
output.writeRawVarint32(tag);
output.writeBytesNoTag(value);
return true;
}
case WireFormat.WIRETYPE_START_GROUP:
{
output.writeRawVarint32(tag);
skipMessage(output);
int endtag =
WireFormat.makeTag(
WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
checkLastTagWas(endtag);
output.writeRawVarint32(endtag);
return true;
}
case WireFormat.WIRETYPE_END_GROUP:
{
return false;
}
case WireFormat.WIRETYPE_FIXED32:
{
int value = readRawLittleEndian32();
output.writeRawVarint32(tag);
output.writeFixed32NoTag(value);
return true;
}
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}
@Override
public void skipMessage() throws IOException {
while (true) {
final int tag = readTag();
if (tag == 0 || !skipField(tag)) {
return;
}
}
}
@Override
public void skipMessage(CodedOutputStream output) throws IOException {
while (true) {
final int tag = readTag();
if (tag == 0 || !skipField(tag, output)) {
return;
}
}
}
@Override
public double readDouble() throws IOException {
return Double.longBitsToDouble(readRawLittleEndian64());
}
@Override
public float readFloat() throws IOException {
return Float.intBitsToFloat(readRawLittleEndian32());
}
@Override
public long readUInt64() throws IOException {
return readRawVarint64();
}
@Override
public long readInt64() throws IOException {
return readRawVarint64();
}
@Override
public int readInt32() throws IOException {
return readRawVarint32();
}
@Override
public long readFixed64() throws IOException {
return readRawLittleEndian64();
}
@Override
public int readFixed32() throws IOException {
return readRawLittleEndian32();
}
@Override
public boolean readBool() throws IOException {
return readRawVarint64() != 0;
}
@Override
public String readString() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= remaining()) {
byte[] bytes = new byte[size];
UnsafeUtil.copyMemory(pos, bytes, 0, size);
String result = new String(bytes, UTF_8);
pos += size;
return result;
}
if (size == 0) {
return "";
}
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public String readStringRequireUtf8() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= remaining()) {
final int bufferPos = bufferPos(pos);
String result = Utf8.decodeUtf8(buffer, bufferPos, size);
pos += size;
return result;
}
if (size == 0) {
return "";
}
if (size <= 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public void readGroup(
final int fieldNumber,
final MessageLite.Builder builder,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
++recursionDepth;
builder.mergeFrom(this, extensionRegistry);
checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
--recursionDepth;
}
@Override
public <T extends MessageLite> T readGroup(
final int fieldNumber,
final Parser<T> parser,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
++recursionDepth;
T result = parser.parsePartialFrom(this, extensionRegistry);
checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
--recursionDepth;
return result;
}
@Deprecated
@Override
public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
throws IOException {
readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
}
@Override
public void readMessage(
final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
throws IOException {
final int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
final int oldLimit = pushLimit(length);
++recursionDepth;
builder.mergeFrom(this, extensionRegistry);
checkLastTagWas(0);
--recursionDepth;
popLimit(oldLimit);
}
@Override
public <T extends MessageLite> T readMessage(
final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
final int oldLimit = pushLimit(length);
++recursionDepth;
T result = parser.parsePartialFrom(this, extensionRegistry);
checkLastTagWas(0);
--recursionDepth;
popLimit(oldLimit);
return result;
}
@Override
public ByteString readBytes() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= remaining()) {
if (immutable && enableAliasing) {
final ByteBuffer result = slice(pos, pos + size);
pos += size;
return ByteString.wrap(result);
} else {
byte[] bytes = new byte[size];
UnsafeUtil.copyMemory(pos, bytes, 0, size);
pos += size;
return ByteString.wrap(bytes);
}
}
if (size == 0) {
return ByteString.EMPTY;
}
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public byte[] readByteArray() throws IOException {
return readRawBytes(readRawVarint32());
}
@Override
public ByteBuffer readByteBuffer() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= remaining()) {
if (!immutable && enableAliasing) {
final ByteBuffer result = slice(pos, pos + size);
pos += size;
return result;
} else {
byte[] bytes = new byte[size];
UnsafeUtil.copyMemory(pos, bytes, 0, size);
pos += size;
return ByteBuffer.wrap(bytes);
}
}
if (size == 0) {
return EMPTY_BYTE_BUFFER;
}
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public int readUInt32() throws IOException {
return readRawVarint32();
}
@Override
public int readEnum() throws IOException {
return readRawVarint32();
}
@Override
public int readSFixed32() throws IOException {
return readRawLittleEndian32();
}
@Override
public long readSFixed64() throws IOException {
return readRawLittleEndian64();
}
@Override
public int readSInt32() throws IOException {
return decodeZigZag32(readRawVarint32());
}
@Override
public long readSInt64() throws IOException {
return decodeZigZag64(readRawVarint64());
}
@Override
public int readRawVarint32() throws IOException {
fastpath:
{
long tempPos = pos;
if (limit == tempPos) {
break fastpath;
}
int x;
if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) {
pos = tempPos;
return x;
} else if (limit - tempPos < 9) {
break fastpath;
} else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
x ^= (~0 << 7);
} else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
x ^= (~0 << 7) ^ (~0 << 14);
} else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
} else {
int y = UnsafeUtil.getByte(tempPos++);
x ^= y << 28;
x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
if (y < 0
&& UnsafeUtil.getByte(tempPos++) < 0
&& UnsafeUtil.getByte(tempPos++) < 0
&& UnsafeUtil.getByte(tempPos++) < 0
&& UnsafeUtil.getByte(tempPos++) < 0
&& UnsafeUtil.getByte(tempPos++) < 0) {
break fastpath;
}
}
pos = tempPos;
return x;
}
return (int) readRawVarint64SlowPath();
}
private void skipRawVarint() throws IOException {
if (remaining() >= MAX_VARINT_SIZE) {
skipRawVarintFastPath();
} else {
skipRawVarintSlowPath();
}
}
private void skipRawVarintFastPath() throws IOException {
for (int i = 0; i < MAX_VARINT_SIZE; i++) {
if (UnsafeUtil.getByte(pos++) >= 0) {
return;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
private void skipRawVarintSlowPath() throws IOException {
for (int i = 0; i < MAX_VARINT_SIZE; i++) {
if (readRawByte() >= 0) {
return;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
@Override
public long readRawVarint64() throws IOException {
fastpath:
{
long tempPos = pos;
if (limit == tempPos) {
break fastpath;
}
long x;
int y;
if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) {
pos = tempPos;
return y;
} else if (limit - tempPos < 9) {
break fastpath;
} else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
x = y ^ (~0 << 7);
} else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
x = y ^ ((~0 << 7) ^ (~0 << 14));
} else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
} else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
} else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
} else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
} else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) {
x ^=
(~0L << 7)
^ (~0L << 14)
^ (~0L << 21)
^ (~0L << 28)
^ (~0L << 35)
^ (~0L << 42)
^ (~0L << 49);
} else {
x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56);
x ^=
(~0L << 7)
^ (~0L << 14)
^ (~0L << 21)
^ (~0L << 28)
^ (~0L << 35)
^ (~0L << 42)
^ (~0L << 49)
^ (~0L << 56);
if (x < 0L) {
if (UnsafeUtil.getByte(tempPos++) < 0L) {
break fastpath;
}
}
}
pos = tempPos;
return x;
}
return readRawVarint64SlowPath();
}
@Override
long readRawVarint64SlowPath() throws IOException {
long result = 0;
for (int shift = 0; shift < 64; shift += 7) {
final byte b = readRawByte();
result |= (long) (b & 0x7F) << shift;
if ((b & 0x80) == 0) {
return result;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
@Override
public int readRawLittleEndian32() throws IOException {
long tempPos = pos;
if (limit - tempPos < FIXED32_SIZE) {
throw InvalidProtocolBufferException.truncatedMessage();
}
pos = tempPos + FIXED32_SIZE;
return (((UnsafeUtil.getByte(tempPos) & 0xff))
| ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8)
| ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16)
| ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24));
}
@Override
public long readRawLittleEndian64() throws IOException {
long tempPos = pos;
if (limit - tempPos < FIXED64_SIZE) {
throw InvalidProtocolBufferException.truncatedMessage();
}
pos = tempPos + FIXED64_SIZE;
return (((UnsafeUtil.getByte(tempPos) & 0xffL))
| ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8)
| ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16)
| ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24)
| ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32)
| ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40)
| ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48)
| ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56));
}
@Override
public void enableAliasing(boolean enabled) {
this.enableAliasing = enabled;
}
@Override
public void resetSizeCounter() {
startPos = pos;
}
@Override
public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
if (byteLimit < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
byteLimit += getTotalBytesRead();
final int oldLimit = currentLimit;
if (byteLimit > oldLimit) {
throw InvalidProtocolBufferException.truncatedMessage();
}
currentLimit = byteLimit;
recomputeBufferSizeAfterLimit();
return oldLimit;
}
@Override
public void popLimit(final int oldLimit) {
currentLimit = oldLimit;
recomputeBufferSizeAfterLimit();
}
@Override
public int getBytesUntilLimit() {
if (currentLimit == Integer.MAX_VALUE) {
return -1;
}
return currentLimit - getTotalBytesRead();
}
@Override
public boolean isAtEnd() throws IOException {
return pos == limit;
}
@Override
public int getTotalBytesRead() {
return (int) (pos - startPos);
}
@Override
public byte readRawByte() throws IOException {
if (pos == limit) {
throw InvalidProtocolBufferException.truncatedMessage();
}
return UnsafeUtil.getByte(pos++);
}
@Override
public byte[] readRawBytes(final int length) throws IOException {
if (length >= 0 && length <= remaining()) {
byte[] bytes = new byte[length];
slice(pos, pos + length).get(bytes);
pos += length;
return bytes;
}
if (length <= 0) {
if (length == 0) {
return EMPTY_BYTE_ARRAY;
} else {
throw InvalidProtocolBufferException.negativeSize();
}
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public void skipRawBytes(final int length) throws IOException {
if (length >= 0 && length <= remaining()) {
pos += length;
return;
}
if (length < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
private void recomputeBufferSizeAfterLimit() {
limit += bufferSizeAfterLimit;
final int bufferEnd = (int) (limit - startPos);
if (bufferEnd > currentLimit) {
bufferSizeAfterLimit = bufferEnd - currentLimit;
limit -= bufferSizeAfterLimit;
} else {
bufferSizeAfterLimit = 0;
}
}
private int remaining() {
return (int) (limit - pos);
}
private int bufferPos(long pos) {
return (int) (pos - address);
}
private ByteBuffer slice(long begin, long end) throws IOException {
int prevPos = buffer.position();
int prevLimit = buffer.limit();
try {
buffer.position(bufferPos(begin));
buffer.limit(bufferPos(end));
return buffer.slice();
} catch (IllegalArgumentException e) {
throw InvalidProtocolBufferException.truncatedMessage();
} finally {
buffer.position(prevPos);
buffer.limit(prevLimit);
}
}
}
private static final class StreamDecoder extends CodedInputStream {
private final InputStream input;
private final byte[] buffer;
private int bufferSize;
private int bufferSizeAfterLimit;
private int pos;
private int lastTag;
private int totalBytesRetired;
private int currentLimit = Integer.MAX_VALUE;
private StreamDecoder(final InputStream input, int bufferSize) {
checkNotNull(input, "input");
this.input = input;
this.buffer = new byte[bufferSize];
this.bufferSize = 0;
pos = 0;
totalBytesRetired = 0;
}
@Override
public int readTag() throws IOException {
if (isAtEnd()) {
lastTag = 0;
return 0;
}
lastTag = readRawVarint32();
if (WireFormat.getTagFieldNumber(lastTag) == 0) {
throw InvalidProtocolBufferException.invalidTag();
}
return lastTag;
}
@Override
public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
if (lastTag != value) {
throw InvalidProtocolBufferException.invalidEndTag();
}
}
@Override
public int getLastTag() {
return lastTag;
}
@Override
public boolean skipField(final int tag) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
skipRawVarint();
return true;
case WireFormat.WIRETYPE_FIXED64:
skipRawBytes(FIXED64_SIZE);
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
skipRawBytes(readRawVarint32());
return true;
case WireFormat.WIRETYPE_START_GROUP:
skipMessage();
checkLastTagWas(
WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
return true;
case WireFormat.WIRETYPE_END_GROUP:
return false;
case WireFormat.WIRETYPE_FIXED32:
skipRawBytes(FIXED32_SIZE);
return true;
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}
@Override
public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
{
long value = readInt64();
output.writeRawVarint32(tag);
output.writeUInt64NoTag(value);
return true;
}
case WireFormat.WIRETYPE_FIXED64:
{
long value = readRawLittleEndian64();
output.writeRawVarint32(tag);
output.writeFixed64NoTag(value);
return true;
}
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
{
ByteString value = readBytes();
output.writeRawVarint32(tag);
output.writeBytesNoTag(value);
return true;
}
case WireFormat.WIRETYPE_START_GROUP:
{
output.writeRawVarint32(tag);
skipMessage(output);
int endtag =
WireFormat.makeTag(
WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
checkLastTagWas(endtag);
output.writeRawVarint32(endtag);
return true;
}
case WireFormat.WIRETYPE_END_GROUP:
{
return false;
}
case WireFormat.WIRETYPE_FIXED32:
{
int value = readRawLittleEndian32();
output.writeRawVarint32(tag);
output.writeFixed32NoTag(value);
return true;
}
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}
@Override
public void skipMessage() throws IOException {
while (true) {
final int tag = readTag();
if (tag == 0 || !skipField(tag)) {
return;
}
}
}
@Override
public void skipMessage(CodedOutputStream output) throws IOException {
while (true) {
final int tag = readTag();
if (tag == 0 || !skipField(tag, output)) {
return;
}
}
}
private class SkippedDataSink implements RefillCallback {
private int lastPos = pos;
private ByteArrayOutputStream byteArrayStream;
@Override
public void onRefill() {
if (byteArrayStream == null) {
byteArrayStream = new ByteArrayOutputStream();
}
byteArrayStream.write(buffer, lastPos, pos - lastPos);
lastPos = 0;
}
ByteBuffer getSkippedData() {
if (byteArrayStream == null) {
return ByteBuffer.wrap(buffer, lastPos, pos - lastPos);
} else {
byteArrayStream.write(buffer, lastPos, pos);
return ByteBuffer.wrap(byteArrayStream.toByteArray());
}
}
}
@Override
public double readDouble() throws IOException {
return Double.longBitsToDouble(readRawLittleEndian64());
}
@Override
public float readFloat() throws IOException {
return Float.intBitsToFloat(readRawLittleEndian32());
}
@Override
public long readUInt64() throws IOException {
return readRawVarint64();
}
@Override
public long readInt64() throws IOException {
return readRawVarint64();
}
@Override
public int readInt32() throws IOException {
return readRawVarint32();
}
@Override
public long readFixed64() throws IOException {
return readRawLittleEndian64();
}
@Override
public int readFixed32() throws IOException {
return readRawLittleEndian32();
}
@Override
public boolean readBool() throws IOException {
return readRawVarint64() != 0;
}
@Override
public String readString() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= (bufferSize - pos)) {
final String result = new String(buffer, pos, size, UTF_8);
pos += size;
return result;
}
if (size == 0) {
return "";
}
if (size <= bufferSize) {
refillBuffer(size);
String result = new String(buffer, pos, size, UTF_8);
pos += size;
return result;
}
return new String(readRawBytesSlowPath(size, false), UTF_8);
}
@Override
public String readStringRequireUtf8() throws IOException {
final int size = readRawVarint32();
final byte[] bytes;
final int oldPos = pos;
final int tempPos;
if (size <= (bufferSize - oldPos) && size > 0) {
bytes = buffer;
pos = oldPos + size;
tempPos = oldPos;
} else if (size == 0) {
return "";
} else if (size <= bufferSize) {
refillBuffer(size);
bytes = buffer;
tempPos = 0;
pos = tempPos + size;
} else {
bytes = readRawBytesSlowPath(size, false);
tempPos = 0;
}
return Utf8.decodeUtf8(bytes, tempPos, size);
}
@Override
public void readGroup(
final int fieldNumber,
final MessageLite.Builder builder,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
++recursionDepth;
builder.mergeFrom(this, extensionRegistry);
checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
--recursionDepth;
}
@Override
public <T extends MessageLite> T readGroup(
final int fieldNumber,
final Parser<T> parser,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
++recursionDepth;
T result = parser.parsePartialFrom(this, extensionRegistry);
checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
--recursionDepth;
return result;
}
@Deprecated
@Override
public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
throws IOException {
readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
}
@Override
public void readMessage(
final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
throws IOException {
final int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
final int oldLimit = pushLimit(length);
++recursionDepth;
builder.mergeFrom(this, extensionRegistry);
checkLastTagWas(0);
--recursionDepth;
popLimit(oldLimit);
}
@Override
public <T extends MessageLite> T readMessage(
final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
final int oldLimit = pushLimit(length);
++recursionDepth;
T result = parser.parsePartialFrom(this, extensionRegistry);
checkLastTagWas(0);
--recursionDepth;
popLimit(oldLimit);
return result;
}
@Override
public ByteString readBytes() throws IOException {
final int size = readRawVarint32();
if (size <= (bufferSize - pos) && size > 0) {
final ByteString result = ByteString.copyFrom(buffer, pos, size);
pos += size;
return result;
}
if (size == 0) {
return ByteString.EMPTY;
}
return readBytesSlowPath(size);
}
@Override
public byte[] readByteArray() throws IOException {
final int size = readRawVarint32();
if (size <= (bufferSize - pos) && size > 0) {
final byte[] result = Arrays.copyOfRange(buffer, pos, pos + size);
pos += size;
return result;
} else {
return readRawBytesSlowPath(size, false);
}
}
@Override
public ByteBuffer readByteBuffer() throws IOException {
final int size = readRawVarint32();
if (size <= (bufferSize - pos) && size > 0) {
ByteBuffer result = ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size));
pos += size;
return result;
}
if (size == 0) {
return Internal.EMPTY_BYTE_BUFFER;
}
return ByteBuffer.wrap(readRawBytesSlowPath(size, true));
}
@Override
public int readUInt32() throws IOException {
return readRawVarint32();
}
@Override
public int readEnum() throws IOException {
return readRawVarint32();
}
@Override
public int readSFixed32() throws IOException {
return readRawLittleEndian32();
}
@Override
public long readSFixed64() throws IOException {
return readRawLittleEndian64();
}
@Override
public int readSInt32() throws IOException {
return decodeZigZag32(readRawVarint32());
}
@Override
public long readSInt64() throws IOException {
return decodeZigZag64(readRawVarint64());
}
@Override
public int readRawVarint32() throws IOException {
fastpath:
{
int tempPos = pos;
if (bufferSize == tempPos) {
break fastpath;
}
final byte[] buffer = this.buffer;
int x;
if ((x = buffer[tempPos++]) >= 0) {
pos = tempPos;
return x;
} else if (bufferSize - tempPos < 9) {
break fastpath;
} else if ((x ^= (buffer[tempPos++] << 7)) < 0) {
x ^= (~0 << 7);
} else if ((x ^= (buffer[tempPos++] << 14)) >= 0) {
x ^= (~0 << 7) ^ (~0 << 14);
} else if ((x ^= (buffer[tempPos++] << 21)) < 0) {
x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
} else {
int y = buffer[tempPos++];
x ^= y << 28;
x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
if (y < 0
&& buffer[tempPos++] < 0
&& buffer[tempPos++] < 0
&& buffer[tempPos++] < 0
&& buffer[tempPos++] < 0
&& buffer[tempPos++] < 0) {
break fastpath;
}
}
pos = tempPos;
return x;
}
return (int) readRawVarint64SlowPath();
}
private void skipRawVarint() throws IOException {
if (bufferSize - pos >= MAX_VARINT_SIZE) {
skipRawVarintFastPath();
} else {
skipRawVarintSlowPath();
}
}
private void skipRawVarintFastPath() throws IOException {
for (int i = 0; i < MAX_VARINT_SIZE; i++) {
if (buffer[pos++] >= 0) {
return;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
private void skipRawVarintSlowPath() throws IOException {
for (int i = 0; i < MAX_VARINT_SIZE; i++) {
if (readRawByte() >= 0) {
return;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
@Override
public long readRawVarint64() throws IOException {
fastpath:
{
int tempPos = pos;
if (bufferSize == tempPos) {
break fastpath;
}
final byte[] buffer = this.buffer;
long x;
int y;
if ((y = buffer[tempPos++]) >= 0) {
pos = tempPos;
return y;
} else if (bufferSize - tempPos < 9) {
break fastpath;
} else if ((y ^= (buffer[tempPos++] << 7)) < 0) {
x = y ^ (~0 << 7);
} else if ((y ^= (buffer[tempPos++] << 14)) >= 0) {
x = y ^ ((~0 << 7) ^ (~0 << 14));
} else if ((y ^= (buffer[tempPos++] << 21)) < 0) {
x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
} else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
} else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
} else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
} else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) {
x ^=
(~0L << 7)
^ (~0L << 14)
^ (~0L << 21)
^ (~0L << 28)
^ (~0L << 35)
^ (~0L << 42)
^ (~0L << 49);
} else {
x ^= ((long) buffer[tempPos++] << 56);
x ^=
(~0L << 7)
^ (~0L << 14)
^ (~0L << 21)
^ (~0L << 28)
^ (~0L << 35)
^ (~0L << 42)
^ (~0L << 49)
^ (~0L << 56);
if (x < 0L) {
if (buffer[tempPos++] < 0L) {
break fastpath;
}
}
}
pos = tempPos;
return x;
}
return readRawVarint64SlowPath();
}
@Override
long readRawVarint64SlowPath() throws IOException {
long result = 0;
for (int shift = 0; shift < 64; shift += 7) {
final byte b = readRawByte();
result |= (long) (b & 0x7F) << shift;
if ((b & 0x80) == 0) {
return result;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
@Override
public int readRawLittleEndian32() throws IOException {
int tempPos = pos;
if (bufferSize - tempPos < FIXED32_SIZE) {
refillBuffer(FIXED32_SIZE);
tempPos = pos;
}
final byte[] buffer = this.buffer;
pos = tempPos + FIXED32_SIZE;
return (((buffer[tempPos] & 0xff))
| ((buffer[tempPos + 1] & 0xff) << 8)
| ((buffer[tempPos + 2] & 0xff) << 16)
| ((buffer[tempPos + 3] & 0xff) << 24));
}
@Override
public long readRawLittleEndian64() throws IOException {
int tempPos = pos;
if (bufferSize - tempPos < FIXED64_SIZE) {
refillBuffer(FIXED64_SIZE);
tempPos = pos;
}
final byte[] buffer = this.buffer;
pos = tempPos + FIXED64_SIZE;
return (((buffer[tempPos] & 0xffL))
| ((buffer[tempPos + 1] & 0xffL) << 8)
| ((buffer[tempPos + 2] & 0xffL) << 16)
| ((buffer[tempPos + 3] & 0xffL) << 24)
| ((buffer[tempPos + 4] & 0xffL) << 32)
| ((buffer[tempPos + 5] & 0xffL) << 40)
| ((buffer[tempPos + 6] & 0xffL) << 48)
| ((buffer[tempPos + 7] & 0xffL) << 56));
}
@Override
public void enableAliasing(boolean enabled) {
}
@Override
public void resetSizeCounter() {
totalBytesRetired = -pos;
}
@Override
public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
if (byteLimit < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
byteLimit += totalBytesRetired + pos;
final int oldLimit = currentLimit;
if (byteLimit > oldLimit) {
throw InvalidProtocolBufferException.truncatedMessage();
}
currentLimit = byteLimit;
recomputeBufferSizeAfterLimit();
return oldLimit;
}
private void recomputeBufferSizeAfterLimit() {
bufferSize += bufferSizeAfterLimit;
final int bufferEnd = totalBytesRetired + bufferSize;
if (bufferEnd > currentLimit) {
bufferSizeAfterLimit = bufferEnd - currentLimit;
bufferSize -= bufferSizeAfterLimit;
} else {
bufferSizeAfterLimit = 0;
}
}
@Override
public void popLimit(final int oldLimit) {
currentLimit = oldLimit;
recomputeBufferSizeAfterLimit();
}
@Override
public int getBytesUntilLimit() {
if (currentLimit == Integer.MAX_VALUE) {
return -1;
}
final int currentAbsolutePosition = totalBytesRetired + pos;
return currentLimit - currentAbsolutePosition;
}
@Override
public boolean isAtEnd() throws IOException {
return pos == bufferSize && !tryRefillBuffer(1);
}
@Override
public int getTotalBytesRead() {
return totalBytesRetired + pos;
}
private interface RefillCallback {
void onRefill();
}
private RefillCallback refillCallback = null;
private void refillBuffer(int n) throws IOException {
if (!tryRefillBuffer(n)) {
if (n > sizeLimit - totalBytesRetired - pos) {
throw InvalidProtocolBufferException.sizeLimitExceeded();
} else {
throw InvalidProtocolBufferException.truncatedMessage();
}
}
}
private boolean tryRefillBuffer(int n) throws IOException {
if (pos + n <= bufferSize) {
throw new IllegalStateException(
"refillBuffer() called when " + n + " bytes were already available in buffer");
}
if (n > sizeLimit - totalBytesRetired - pos) {
return false;
}
if (totalBytesRetired + pos + n > currentLimit) {
return false;
}
if (refillCallback != null) {
refillCallback.onRefill();
}
int tempPos = pos;
if (tempPos > 0) {
if (bufferSize > tempPos) {
System.arraycopy(buffer, tempPos, buffer, 0, bufferSize - tempPos);
}
totalBytesRetired += tempPos;
bufferSize -= tempPos;
pos = 0;
}
int bytesRead =
input.read(
buffer,
bufferSize,
Math.min(
buffer.length - bufferSize,
sizeLimit - totalBytesRetired - bufferSize));
if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
throw new IllegalStateException(
input.getClass()
+ "#read(byte[]) returned invalid result: "
+ bytesRead
+ "\nThe InputStream implementation is buggy.");
}
if (bytesRead > 0) {
bufferSize += bytesRead;
recomputeBufferSizeAfterLimit();
return (bufferSize >= n) ? true : tryRefillBuffer(n);
}
return false;
}
@Override
public byte readRawByte() throws IOException {
if (pos == bufferSize) {
refillBuffer(1);
}
return buffer[pos++];
}
@Override
public byte[] readRawBytes(final int size) throws IOException {
final int tempPos = pos;
if (size <= (bufferSize - tempPos) && size > 0) {
pos = tempPos + size;
return Arrays.copyOfRange(buffer, tempPos, tempPos + size);
} else {
return readRawBytesSlowPath(size, false);
}
}
private byte[] readRawBytesSlowPath(
final int size, boolean ensureNoLeakedReferences) throws IOException {
byte[] result = readRawBytesSlowPathOneChunk(size);
if (result != null) {
return ensureNoLeakedReferences ? result.clone() : result;
}
final int originalBufferPos = pos;
final int bufferedBytes = bufferSize - pos;
totalBytesRetired += bufferSize;
pos = 0;
bufferSize = 0;
int sizeLeft = size - bufferedBytes;
List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
final byte[] bytes = new byte[size];
System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
int tempPos = bufferedBytes;
for (final byte[] chunk : chunks) {
System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
tempPos += chunk.length;
}
return bytes;
}
private byte[] readRawBytesSlowPathOneChunk(final int size) throws IOException {
if (size == 0) {
return Internal.EMPTY_BYTE_ARRAY;
}
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
int currentMessageSize = totalBytesRetired + pos + size;
if (currentMessageSize - sizeLimit > 0) {
throw InvalidProtocolBufferException.sizeLimitExceeded();
}
if (currentMessageSize > currentLimit) {
skipRawBytes(currentLimit - totalBytesRetired - pos);
throw InvalidProtocolBufferException.truncatedMessage();
}
final int bufferedBytes = bufferSize - pos;
int sizeLeft = size - bufferedBytes;
if (sizeLeft < DEFAULT_BUFFER_SIZE || sizeLeft <= input.available()) {
final byte[] bytes = new byte[size];
System.arraycopy(buffer, pos, bytes, 0, bufferedBytes);
totalBytesRetired += bufferSize;
pos = 0;
bufferSize = 0;
int tempPos = bufferedBytes;
while (tempPos < bytes.length) {
int n = input.read(bytes, tempPos, size - tempPos);
if (n == -1) {
throw InvalidProtocolBufferException.truncatedMessage();
}
totalBytesRetired += n;
tempPos += n;
}
return bytes;
}
return null;
}
private List<byte[]> readRawBytesSlowPathRemainingChunks(int sizeLeft) throws IOException {
final List<byte[]> chunks = new ArrayList<byte[]>();
while (sizeLeft > 0) {
final byte[] chunk = new byte[Math.min(sizeLeft, DEFAULT_BUFFER_SIZE)];
int tempPos = 0;
while (tempPos < chunk.length) {
final int n = input.read(chunk, tempPos, chunk.length - tempPos);
if (n == -1) {
throw InvalidProtocolBufferException.truncatedMessage();
}
totalBytesRetired += n;
tempPos += n;
}
sizeLeft -= chunk.length;
chunks.add(chunk);
}
return chunks;
}
private ByteString readBytesSlowPath(final int size) throws IOException {
final byte[] result = readRawBytesSlowPathOneChunk(size);
if (result != null) {
return ByteString.copyFrom(result);
}
final int originalBufferPos = pos;
final int bufferedBytes = bufferSize - pos;
totalBytesRetired += bufferSize;
pos = 0;
bufferSize = 0;
int sizeLeft = size - bufferedBytes;
List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
final byte[] bytes = new byte[size];
System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
int tempPos = bufferedBytes;
for (final byte[] chunk : chunks) {
System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
tempPos += chunk.length;
}
return ByteString.wrap(bytes);
}
@Override
public void skipRawBytes(final int size) throws IOException {
if (size <= (bufferSize - pos) && size >= 0) {
pos += size;
} else {
skipRawBytesSlowPath(size);
}
}
private void skipRawBytesSlowPath(final int size) throws IOException {
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
if (totalBytesRetired + pos + size > currentLimit) {
skipRawBytes(currentLimit - totalBytesRetired - pos);
throw InvalidProtocolBufferException.truncatedMessage();
}
int totalSkipped = 0;
if (refillCallback == null) {
totalBytesRetired += pos;
totalSkipped = bufferSize - pos;
bufferSize = 0;
pos = 0;
try {
while (totalSkipped < size) {
int toSkip = size - totalSkipped;
long skipped = input.skip(toSkip);
if (skipped < 0 || skipped > toSkip) {
throw new IllegalStateException(
input.getClass()
+ "#skip returned invalid result: "
+ skipped
+ "\nThe InputStream implementation is buggy.");
} else if (skipped == 0) {
break;
}
totalSkipped += (int) skipped;
}
} finally {
totalBytesRetired += totalSkipped;
recomputeBufferSizeAfterLimit();
}
}
if (totalSkipped < size) {
int tempPos = bufferSize - pos;
pos = bufferSize;
refillBuffer(1);
while (size - tempPos > bufferSize) {
tempPos += bufferSize;
pos = bufferSize;
refillBuffer(1);
}
pos = size - tempPos;
}
}
}
private static final class IterableDirectByteBufferDecoder extends CodedInputStream {
private Iterable<ByteBuffer> input;
private Iterator<ByteBuffer> iterator;
private ByteBuffer currentByteBuffer;
private boolean immutable;
private boolean enableAliasing;
private int totalBufferSize;
private int bufferSizeAfterCurrentLimit;
private int currentLimit = Integer.MAX_VALUE;
private int lastTag;
private int totalBytesRead;
private int startOffset;
private long currentByteBufferPos;
private long currentByteBufferStartPos;
private long currentAddress;
private long currentByteBufferLimit;
private IterableDirectByteBufferDecoder(
Iterable<ByteBuffer> inputBufs, int size, boolean immutableFlag) {
totalBufferSize = size;
input = inputBufs;
iterator = input.iterator();
immutable = immutableFlag;
startOffset = totalBytesRead = 0;
if (size == 0) {
currentByteBuffer = EMPTY_BYTE_BUFFER;
currentByteBufferPos = 0;
currentByteBufferStartPos = 0;
currentByteBufferLimit = 0;
currentAddress = 0;
} else {
tryGetNextByteBuffer();
}
}
private void getNextByteBuffer() throws InvalidProtocolBufferException {
if (!iterator.hasNext()) {
throw InvalidProtocolBufferException.truncatedMessage();
}
tryGetNextByteBuffer();
}
private void tryGetNextByteBuffer() {
currentByteBuffer = iterator.next();
totalBytesRead += (int) (currentByteBufferPos - currentByteBufferStartPos);
currentByteBufferPos = currentByteBuffer.position();
currentByteBufferStartPos = currentByteBufferPos;
currentByteBufferLimit = currentByteBuffer.limit();
currentAddress = UnsafeUtil.addressOffset(currentByteBuffer);
currentByteBufferPos += currentAddress;
currentByteBufferStartPos += currentAddress;
currentByteBufferLimit += currentAddress;
}
@Override
public int readTag() throws IOException {
if (isAtEnd()) {
lastTag = 0;
return 0;
}
lastTag = readRawVarint32();
if (WireFormat.getTagFieldNumber(lastTag) == 0) {
throw InvalidProtocolBufferException.invalidTag();
}
return lastTag;
}
@Override
public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
if (lastTag != value) {
throw InvalidProtocolBufferException.invalidEndTag();
}
}
@Override
public int getLastTag() {
return lastTag;
}
@Override
public boolean skipField(final int tag) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
skipRawVarint();
return true;
case WireFormat.WIRETYPE_FIXED64:
skipRawBytes(FIXED64_SIZE);
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
skipRawBytes(readRawVarint32());
return true;
case WireFormat.WIRETYPE_START_GROUP:
skipMessage();
checkLastTagWas(
WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
return true;
case WireFormat.WIRETYPE_END_GROUP:
return false;
case WireFormat.WIRETYPE_FIXED32:
skipRawBytes(FIXED32_SIZE);
return true;
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}
@Override
public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
{
long value = readInt64();
output.writeRawVarint32(tag);
output.writeUInt64NoTag(value);
return true;
}
case WireFormat.WIRETYPE_FIXED64:
{
long value = readRawLittleEndian64();
output.writeRawVarint32(tag);
output.writeFixed64NoTag(value);
return true;
}
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
{
ByteString value = readBytes();
output.writeRawVarint32(tag);
output.writeBytesNoTag(value);
return true;
}
case WireFormat.WIRETYPE_START_GROUP:
{
output.writeRawVarint32(tag);
skipMessage(output);
int endtag =
WireFormat.makeTag(
WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
checkLastTagWas(endtag);
output.writeRawVarint32(endtag);
return true;
}
case WireFormat.WIRETYPE_END_GROUP:
{
return false;
}
case WireFormat.WIRETYPE_FIXED32:
{
int value = readRawLittleEndian32();
output.writeRawVarint32(tag);
output.writeFixed32NoTag(value);
return true;
}
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}
@Override
public void skipMessage() throws IOException {
while (true) {
final int tag = readTag();
if (tag == 0 || !skipField(tag)) {
return;
}
}
}
@Override
public void skipMessage(CodedOutputStream output) throws IOException {
while (true) {
final int tag = readTag();
if (tag == 0 || !skipField(tag, output)) {
return;
}
}
}
@Override
public double readDouble() throws IOException {
return Double.longBitsToDouble(readRawLittleEndian64());
}
@Override
public float readFloat() throws IOException {
return Float.intBitsToFloat(readRawLittleEndian32());
}
@Override
public long readUInt64() throws IOException {
return readRawVarint64();
}
@Override
public long readInt64() throws IOException {
return readRawVarint64();
}
@Override
public int readInt32() throws IOException {
return readRawVarint32();
}
@Override
public long readFixed64() throws IOException {
return readRawLittleEndian64();
}
@Override
public int readFixed32() throws IOException {
return readRawLittleEndian32();
}
@Override
public boolean readBool() throws IOException {
return readRawVarint64() != 0;
}
@Override
public String readString() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) {
byte[] bytes = new byte[size];
UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size);
String result = new String(bytes, UTF_8);
currentByteBufferPos += size;
return result;
} else if (size > 0 && size <= remaining()) {
byte[] bytes = new byte[size];
readRawBytesTo(bytes, 0, size);
String result = new String(bytes, UTF_8);
return result;
}
if (size == 0) {
return "";
}
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public String readStringRequireUtf8() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) {
final int bufferPos = (int) (currentByteBufferPos - currentByteBufferStartPos);
String result = Utf8.decodeUtf8(currentByteBuffer, bufferPos, size);
currentByteBufferPos += size;
return result;
}
if (size >= 0 && size <= remaining()) {
byte[] bytes = new byte[size];
readRawBytesTo(bytes, 0, size);
return Utf8.decodeUtf8(bytes, 0, size);
}
if (size == 0) {
return "";
}
if (size <= 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public void readGroup(
final int fieldNumber,
final MessageLite.Builder builder,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
++recursionDepth;
builder.mergeFrom(this, extensionRegistry);
checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
--recursionDepth;
}
@Override
public <T extends MessageLite> T readGroup(
final int fieldNumber,
final Parser<T> parser,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
++recursionDepth;
T result = parser.parsePartialFrom(this, extensionRegistry);
checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
--recursionDepth;
return result;
}
@Deprecated
@Override
public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
throws IOException {
readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
}
@Override
public void readMessage(
final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
throws IOException {
final int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
final int oldLimit = pushLimit(length);
++recursionDepth;
builder.mergeFrom(this, extensionRegistry);
checkLastTagWas(0);
--recursionDepth;
popLimit(oldLimit);
}
@Override
public <T extends MessageLite> T readMessage(
final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.recursionLimitExceeded();
}
final int oldLimit = pushLimit(length);
++recursionDepth;
T result = parser.parsePartialFrom(this, extensionRegistry);
checkLastTagWas(0);
--recursionDepth;
popLimit(oldLimit);
return result;
}
@Override
public ByteString readBytes() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) {
if (immutable && enableAliasing) {
final int idx = (int) (currentByteBufferPos - currentAddress);
final ByteString result = ByteString.wrap(slice(idx, idx + size));
currentByteBufferPos += size;
return result;
} else {
byte[] bytes;
bytes = new byte[size];
UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size);
currentByteBufferPos += size;
return ByteString.wrap(bytes);
}
} else if (size > 0 && size <= remaining()) {
byte[] temp = new byte[size];
readRawBytesTo(temp, 0, size);
return ByteString.wrap(temp);
}
if (size == 0) {
return ByteString.EMPTY;
}
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public byte[] readByteArray() throws IOException {
return readRawBytes(readRawVarint32());
}
@Override
public ByteBuffer readByteBuffer() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= currentRemaining()) {
if (!immutable && enableAliasing) {
currentByteBufferPos += size;
return slice(
(int) (currentByteBufferPos - currentAddress - size),
(int) (currentByteBufferPos - currentAddress));
} else {
byte[] bytes = new byte[size];
UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size);
currentByteBufferPos += size;
return ByteBuffer.wrap(bytes);
}
} else if (size > 0 && size <= remaining()) {
byte[] temp = new byte[size];
readRawBytesTo(temp, 0, size);
return ByteBuffer.wrap(temp);
}
if (size == 0) {
return EMPTY_BYTE_BUFFER;
}
if (size < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public int readUInt32() throws IOException {
return readRawVarint32();
}
@Override
public int readEnum() throws IOException {
return readRawVarint32();
}
@Override
public int readSFixed32() throws IOException {
return readRawLittleEndian32();
}
@Override
public long readSFixed64() throws IOException {
return readRawLittleEndian64();
}
@Override
public int readSInt32() throws IOException {
return decodeZigZag32(readRawVarint32());
}
@Override
public long readSInt64() throws IOException {
return decodeZigZag64(readRawVarint64());
}
@Override
public int readRawVarint32() throws IOException {
fastpath:
{
long tempPos = currentByteBufferPos;
if (currentByteBufferLimit == currentByteBufferPos) {
break fastpath;
}
int x;
if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) {
currentByteBufferPos++;
return x;
} else if (currentByteBufferLimit - currentByteBufferPos < 10) {
break fastpath;
} else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
x ^= (~0 << 7);
} else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
x ^= (~0 << 7) ^ (~0 << 14);
} else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
} else {
int y = UnsafeUtil.getByte(tempPos++);
x ^= y << 28;
x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
if (y < 0
&& UnsafeUtil.getByte(tempPos++) < 0
&& UnsafeUtil.getByte(tempPos++) < 0
&& UnsafeUtil.getByte(tempPos++) < 0
&& UnsafeUtil.getByte(tempPos++) < 0
&& UnsafeUtil.getByte(tempPos++) < 0) {
break fastpath;
}
}
currentByteBufferPos = tempPos;
return x;
}
return (int) readRawVarint64SlowPath();
}
@Override
public long readRawVarint64() throws IOException {
fastpath:
{
long tempPos = currentByteBufferPos;
if (currentByteBufferLimit == currentByteBufferPos) {
break fastpath;
}
long x;
int y;
if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) {
currentByteBufferPos++;
return y;
} else if (currentByteBufferLimit - currentByteBufferPos < 10) {
break fastpath;
} else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
x = y ^ (~0 << 7);
} else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
x = y ^ ((~0 << 7) ^ (~0 << 14));
} else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
} else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
} else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
} else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) {
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
} else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) {
x ^=
(~0L << 7)
^ (~0L << 14)
^ (~0L << 21)
^ (~0L << 28)
^ (~0L << 35)
^ (~0L << 42)
^ (~0L << 49);
} else {
x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56);
x ^=
(~0L << 7)
^ (~0L << 14)
^ (~0L << 21)
^ (~0L << 28)
^ (~0L << 35)
^ (~0L << 42)
^ (~0L << 49)
^ (~0L << 56);
if (x < 0L) {
if (UnsafeUtil.getByte(tempPos++) < 0L) {
break fastpath;
}
}
}
currentByteBufferPos = tempPos;
return x;
}
return readRawVarint64SlowPath();
}
@Override
long readRawVarint64SlowPath() throws IOException {
long result = 0;
for (int shift = 0; shift < 64; shift += 7) {
final byte b = readRawByte();
result |= (long) (b & 0x7F) << shift;
if ((b & 0x80) == 0) {
return result;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
@Override
public int readRawLittleEndian32() throws IOException {
if (currentRemaining() >= FIXED32_SIZE) {
long tempPos = currentByteBufferPos;
currentByteBufferPos += FIXED32_SIZE;
return (((UnsafeUtil.getByte(tempPos) & 0xff))
| ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8)
| ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16)
| ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24));
}
return ((readRawByte() & 0xff)
| ((readRawByte() & 0xff) << 8)
| ((readRawByte() & 0xff) << 16)
| ((readRawByte() & 0xff) << 24));
}
@Override
public long readRawLittleEndian64() throws IOException {
if (currentRemaining() >= FIXED64_SIZE) {
long tempPos = currentByteBufferPos;
currentByteBufferPos += FIXED64_SIZE;
return (((UnsafeUtil.getByte(tempPos) & 0xffL))
| ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8)
| ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16)
| ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24)
| ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32)
| ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40)
| ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48)
| ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56));
}
return ((readRawByte() & 0xffL)
| ((readRawByte() & 0xffL) << 8)
| ((readRawByte() & 0xffL) << 16)
| ((readRawByte() & 0xffL) << 24)
| ((readRawByte() & 0xffL) << 32)
| ((readRawByte() & 0xffL) << 40)
| ((readRawByte() & 0xffL) << 48)
| ((readRawByte() & 0xffL) << 56));
}
@Override
public void enableAliasing(boolean enabled) {
this.enableAliasing = enabled;
}
@Override
public void resetSizeCounter() {
startOffset = (int) (totalBytesRead + currentByteBufferPos - currentByteBufferStartPos);
}
@Override
public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
if (byteLimit < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
byteLimit += getTotalBytesRead();
final int oldLimit = currentLimit;
if (byteLimit > oldLimit) {
throw InvalidProtocolBufferException.truncatedMessage();
}
currentLimit = byteLimit;
recomputeBufferSizeAfterLimit();
return oldLimit;
}
private void recomputeBufferSizeAfterLimit() {
totalBufferSize += bufferSizeAfterCurrentLimit;
final int bufferEnd = totalBufferSize - startOffset;
if (bufferEnd > currentLimit) {
bufferSizeAfterCurrentLimit = bufferEnd - currentLimit;
totalBufferSize -= bufferSizeAfterCurrentLimit;
} else {
bufferSizeAfterCurrentLimit = 0;
}
}
@Override
public void popLimit(final int oldLimit) {
currentLimit = oldLimit;
recomputeBufferSizeAfterLimit();
}
@Override
public int getBytesUntilLimit() {
if (currentLimit == Integer.MAX_VALUE) {
return -1;
}
return currentLimit - getTotalBytesRead();
}
@Override
public boolean isAtEnd() throws IOException {
return totalBytesRead + currentByteBufferPos - currentByteBufferStartPos == totalBufferSize;
}
@Override
public int getTotalBytesRead() {
return (int)
(totalBytesRead - startOffset + currentByteBufferPos - currentByteBufferStartPos);
}
@Override
public byte readRawByte() throws IOException {
if (currentRemaining() == 0) {
getNextByteBuffer();
}
return UnsafeUtil.getByte(currentByteBufferPos++);
}
@Override
public byte[] readRawBytes(final int length) throws IOException {
if (length >= 0 && length <= currentRemaining()) {
byte[] bytes = new byte[length];
UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, length);
currentByteBufferPos += length;
return bytes;
}
if (length >= 0 && length <= remaining()) {
byte[] bytes = new byte[length];
readRawBytesTo(bytes, 0, length);
return bytes;
}
if (length <= 0) {
if (length == 0) {
return EMPTY_BYTE_ARRAY;
} else {
throw InvalidProtocolBufferException.negativeSize();
}
}
throw InvalidProtocolBufferException.truncatedMessage();
}
private void readRawBytesTo(byte[] bytes, int offset, final int length) throws IOException {
if (length >= 0 && length <= remaining()) {
int l = length;
while (l > 0) {
if (currentRemaining() == 0) {
getNextByteBuffer();
}
int bytesToCopy = Math.min(l, (int) currentRemaining());
UnsafeUtil.copyMemory(currentByteBufferPos, bytes, length - l + offset, bytesToCopy);
l -= bytesToCopy;
currentByteBufferPos += bytesToCopy;
}
return;
}
if (length <= 0) {
if (length == 0) {
return;
} else {
throw InvalidProtocolBufferException.negativeSize();
}
}
throw InvalidProtocolBufferException.truncatedMessage();
}
@Override
public void skipRawBytes(final int length) throws IOException {
if (length >= 0
&& length
<= (totalBufferSize
- totalBytesRead
- currentByteBufferPos
+ currentByteBufferStartPos)) {
int l = length;
while (l > 0) {
if (currentRemaining() == 0) {
getNextByteBuffer();
}
int rl = Math.min(l, (int) currentRemaining());
l -= rl;
currentByteBufferPos += rl;
}
return;
}
if (length < 0) {
throw InvalidProtocolBufferException.negativeSize();
}
throw InvalidProtocolBufferException.truncatedMessage();
}
private void skipRawVarint() throws IOException {
for (int i = 0; i < MAX_VARINT_SIZE; i++) {
if (readRawByte() >= 0) {
return;
}
}
throw InvalidProtocolBufferException.malformedVarint();
}
private int remaining() {
return (int)
(totalBufferSize - totalBytesRead - currentByteBufferPos + currentByteBufferStartPos);
}
private long currentRemaining() {
return (currentByteBufferLimit - currentByteBufferPos);
}
private ByteBuffer slice(int begin, int end) throws IOException {
int prevPos = currentByteBuffer.position();
int prevLimit = currentByteBuffer.limit();
try {
currentByteBuffer.position(begin);
currentByteBuffer.limit(end);
return currentByteBuffer.slice();
} catch (IllegalArgumentException e) {
throw InvalidProtocolBufferException.truncatedMessage();
} finally {
currentByteBuffer.position(prevPos);
currentByteBuffer.limit(prevLimit);
}
}
}
}