164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Protocol Buffers - Google's data interchange format 264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Copyright 2013 Google Inc. All rights reserved. 364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// http://code.google.com/p/protobuf/ 464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// 564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Redistribution and use in source and binary forms, with or without 664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// modification, are permitted provided that the following conditions are 764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// met: 864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// 964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// * Redistributions of source code must retain the above copyright 1064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// notice, this list of conditions and the following disclaimer. 1164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// * Redistributions in binary form must reproduce the above 1264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// copyright notice, this list of conditions and the following disclaimer 1364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// in the documentation and/or other materials provided with the 1464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// distribution. 1564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// * Neither the name of Google Inc. nor the names of its 1664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// contributors may be used to endorse or promote products derived from 1764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// this software without specific prior written permission. 1864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// 1964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 3164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazcipackage com.google.protobuf.nano; 3264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 3364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazciimport java.io.IOException; 3464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 3564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci/** 3664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Reads and decodes protocol message fields. 3764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 3864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * This class contains two kinds of methods: methods that read specific 3964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * protocol message constructs and field types (e.g. {@link #readTag()} and 4064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * {@link #readInt32()}) and methods that read low-level values (e.g. 4164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading 4264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * encoded protocol messages, you should use the former methods, but if you are 4364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * reading some other format of your own design, use the latter. 4464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 4564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @author kenton@google.com Kenton Varda 4664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 4764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazcipublic final class CodedInputByteBufferNano { 4864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 4964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Create a new CodedInputStream wrapping the given byte array. 5064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 5164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public static CodedInputByteBufferNano newInstance(final byte[] buf) { 5264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return newInstance(buf, 0, buf.length); 5364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 5464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 5564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 5664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Create a new CodedInputStream wrapping the given byte array slice. 5764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 5864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public static CodedInputByteBufferNano newInstance(final byte[] buf, final int off, 5964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int len) { 6064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return new CodedInputByteBufferNano(buf, off, len); 6164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 6264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 6364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // ----------------------------------------------------------------- 6464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 6564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 6664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Attempt to read a field tag, returning zero if we have reached EOF. 6764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Protocol message parsers use this to read tags, since a protocol message 6864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * may legally end wherever a tag occurs, and zero is not a valid tag number. 6964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 7064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int readTag() throws IOException { 7164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (isAtEnd()) { 7264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci lastTag = 0; 7364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return 0; 7464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 7564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 7664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci lastTag = readRawVarint32(); 7764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (lastTag == 0) { 7864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // If we actually read zero, that's not a valid tag. 7964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.invalidTag(); 8064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 8164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return lastTag; 8264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 8364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 8464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 8564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Verifies that the last call to readTag() returned the given tag value. 8664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * This is used to verify that a nested group ended with the correct 8764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * end tag. 8864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 8964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @throws InvalidProtocolBufferNanoException {@code value} does not match the 9064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * last tag. 9164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 9264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public void checkLastTagWas(final int value) 9364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throws InvalidProtocolBufferNanoException { 9464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (lastTag != value) { 9564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.invalidEndTag(); 9664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 9764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 9864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 9964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 10064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Reads and discards a single field, given its tag value. 10164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 10264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @return {@code false} if the tag is an endgroup tag, in which case 10364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * nothing is skipped. Otherwise, returns {@code true}. 10464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 10564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public boolean skipField(final int tag) throws IOException { 10664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci switch (WireFormatNano.getTagWireType(tag)) { 10764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci case WireFormatNano.WIRETYPE_VARINT: 10864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci readInt32(); 10964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return true; 11064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci case WireFormatNano.WIRETYPE_FIXED64: 11164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci readRawLittleEndian64(); 11264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return true; 11364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci case WireFormatNano.WIRETYPE_LENGTH_DELIMITED: 11464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci skipRawBytes(readRawVarint32()); 11564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return true; 11664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci case WireFormatNano.WIRETYPE_START_GROUP: 11764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci skipMessage(); 11864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci checkLastTagWas( 11964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci WireFormatNano.makeTag(WireFormatNano.getTagFieldNumber(tag), 12064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci WireFormatNano.WIRETYPE_END_GROUP)); 12164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return true; 12264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci case WireFormatNano.WIRETYPE_END_GROUP: 12364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return false; 12464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci case WireFormatNano.WIRETYPE_FIXED32: 12564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci readRawLittleEndian32(); 12664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return true; 12764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci default: 12864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.invalidWireType(); 12964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 13064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 13164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 13264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 13364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Reads and discards an entire message. This will read either until EOF 13464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * or until an endgroup tag, whichever comes first. 13564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 13664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public void skipMessage() throws IOException { 13764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci while (true) { 13864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int tag = readTag(); 13964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (tag == 0 || !skipField(tag)) { 14064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return; 14164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 14264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 14364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 14464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 14564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // ----------------------------------------------------------------- 14664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 14764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a {@code double} field value from the stream. */ 14864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public double readDouble() throws IOException { 14964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return Double.longBitsToDouble(readRawLittleEndian64()); 15064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 15164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 15264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a {@code float} field value from the stream. */ 15364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public float readFloat() throws IOException { 15464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return Float.intBitsToFloat(readRawLittleEndian32()); 15564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 15664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 15764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a {@code uint64} field value from the stream. */ 15864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public long readUInt64() throws IOException { 15964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return readRawVarint64(); 16064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 16164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 16264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read an {@code int64} field value from the stream. */ 16364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public long readInt64() throws IOException { 16464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return readRawVarint64(); 16564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 16664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 16764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read an {@code int32} field value from the stream. */ 16864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int readInt32() throws IOException { 16964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return readRawVarint32(); 17064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 17164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 17264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a {@code fixed64} field value from the stream. */ 17364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public long readFixed64() throws IOException { 17464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return readRawLittleEndian64(); 17564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 17664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 17764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a {@code fixed32} field value from the stream. */ 17864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int readFixed32() throws IOException { 17964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return readRawLittleEndian32(); 18064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 18164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 18264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a {@code bool} field value from the stream. */ 18364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public boolean readBool() throws IOException { 18464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return readRawVarint32() != 0; 18564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 18664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 18764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a {@code string} field value from the stream. */ 18864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public String readString() throws IOException { 18964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int size = readRawVarint32(); 1909b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler if (size < 0) { 1919b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler throw InvalidProtocolBufferNanoException.negativeSize(); 19264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 1939b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler if (size > (bufferSize - bufferPos)) { 1949b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler throw InvalidProtocolBufferNanoException.truncatedMessage(); 1959b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler } 1969b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler 1979b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler final String result = new String(buffer, bufferPos, size, "UTF-8"); 1989b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler bufferPos += size; 1999b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler return result; 20064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 20164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 20264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a {@code group} field value from the stream. */ 20364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public void readGroup(final MessageNano msg, final int fieldNumber) 20464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throws IOException { 20564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (recursionDepth >= recursionLimit) { 20664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.recursionLimitExceeded(); 20764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 20864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci ++recursionDepth; 20964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci msg.mergeFrom(this); 21064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci checkLastTagWas( 21164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci WireFormatNano.makeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP)); 21264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci --recursionDepth; 21364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 21464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 21564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public void readMessage(final MessageNano msg) 21664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throws IOException { 21764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int length = readRawVarint32(); 21864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (recursionDepth >= recursionLimit) { 21964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.recursionLimitExceeded(); 22064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 22164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int oldLimit = pushLimit(length); 22264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci ++recursionDepth; 22364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci msg.mergeFrom(this); 22464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci checkLastTagWas(0); 22564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci --recursionDepth; 22664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci popLimit(oldLimit); 22764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 22864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 22964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a {@code bytes} field value from the stream. */ 23064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public byte[] readBytes() throws IOException { 23164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int size = readRawVarint32(); 2329b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler if (size < 0) { 2339b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler throw InvalidProtocolBufferNanoException.negativeSize(); 2349b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler } 2359b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler if (size == 0) { 236584381094c72fdeab18a7bb158c27da82b70aecdAndre Eisenbach return WireFormatNano.EMPTY_BYTES; 23764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 2389b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler if (size > (bufferSize - bufferPos)) { 2399b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler throw InvalidProtocolBufferNanoException.truncatedMessage(); 2409b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler } 2419b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler 2429b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler final byte[] result = new byte[size]; 2439b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler System.arraycopy(buffer, bufferPos, result, 0, size); 2449b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler bufferPos += size; 2459b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler return result; 24664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 24764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 24864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a {@code uint32} field value from the stream. */ 24964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int readUInt32() throws IOException { 25064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return readRawVarint32(); 25164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 25264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 25364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 25464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Read an enum field value from the stream. Caller is responsible 25564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * for converting the numeric value to an actual enum. 25664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 25764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int readEnum() throws IOException { 25864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return readRawVarint32(); 25964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 26064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 26164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read an {@code sfixed32} field value from the stream. */ 26264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int readSFixed32() throws IOException { 26364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return readRawLittleEndian32(); 26464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 26564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 26664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read an {@code sfixed64} field value from the stream. */ 26764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public long readSFixed64() throws IOException { 26864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return readRawLittleEndian64(); 26964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 27064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 27164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read an {@code sint32} field value from the stream. */ 27264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int readSInt32() throws IOException { 27364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return decodeZigZag32(readRawVarint32()); 27464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 27564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 27664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read an {@code sint64} field value from the stream. */ 27764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public long readSInt64() throws IOException { 27864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return decodeZigZag64(readRawVarint64()); 27964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 28064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 28164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // ================================================================= 28264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 28364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 28464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Read a raw Varint from the stream. If larger than 32 bits, discard the 28564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * upper bits. 28664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 28764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int readRawVarint32() throws IOException { 28864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci byte tmp = readRawByte(); 28964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (tmp >= 0) { 29064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return tmp; 29164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 29264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci int result = tmp & 0x7f; 29364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if ((tmp = readRawByte()) >= 0) { 29464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci result |= tmp << 7; 29564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } else { 29664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci result |= (tmp & 0x7f) << 7; 29764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if ((tmp = readRawByte()) >= 0) { 29864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci result |= tmp << 14; 29964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } else { 30064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci result |= (tmp & 0x7f) << 14; 30164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if ((tmp = readRawByte()) >= 0) { 30264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci result |= tmp << 21; 30364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } else { 30464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci result |= (tmp & 0x7f) << 21; 30564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci result |= (tmp = readRawByte()) << 28; 30664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (tmp < 0) { 30764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // Discard upper 32 bits. 30864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci for (int i = 0; i < 5; i++) { 30964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (readRawByte() >= 0) { 31064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return result; 31164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 31264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 31364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.malformedVarint(); 31464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 31564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 31664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 31764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 31864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return result; 31964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 32064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 32164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a raw Varint from the stream. */ 32264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public long readRawVarint64() throws IOException { 32364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci int shift = 0; 32464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci long result = 0; 32564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci while (shift < 64) { 32664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b = readRawByte(); 32764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci result |= (long)(b & 0x7F) << shift; 32864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if ((b & 0x80) == 0) { 32964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return result; 33064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 33164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci shift += 7; 33264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 33364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.malformedVarint(); 33464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 33564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 33664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a 32-bit little-endian integer from the stream. */ 33764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int readRawLittleEndian32() throws IOException { 33864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b1 = readRawByte(); 33964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b2 = readRawByte(); 34064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b3 = readRawByte(); 34164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b4 = readRawByte(); 34264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return ((b1 & 0xff) ) | 34364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci ((b2 & 0xff) << 8) | 34464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci ((b3 & 0xff) << 16) | 34564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci ((b4 & 0xff) << 24); 34664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 34764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 34864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** Read a 64-bit little-endian integer from the stream. */ 34964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public long readRawLittleEndian64() throws IOException { 35064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b1 = readRawByte(); 35164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b2 = readRawByte(); 35264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b3 = readRawByte(); 35364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b4 = readRawByte(); 35464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b5 = readRawByte(); 35564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b6 = readRawByte(); 35664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b7 = readRawByte(); 35764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte b8 = readRawByte(); 35864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return (((long)b1 & 0xff) ) | 35964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci (((long)b2 & 0xff) << 8) | 36064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci (((long)b3 & 0xff) << 16) | 36164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci (((long)b4 & 0xff) << 24) | 36264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci (((long)b5 & 0xff) << 32) | 36364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci (((long)b6 & 0xff) << 40) | 36464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci (((long)b7 & 0xff) << 48) | 36564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci (((long)b8 & 0xff) << 56); 36664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 36764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 36864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 36964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers 37064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * into values that can be efficiently encoded with varint. (Otherwise, 37164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * negative values must be sign-extended to 64 bits to be varint encoded, 37264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * thus always taking 10 bytes on the wire.) 37364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 37464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @param n An unsigned 32-bit integer, stored in a signed int because 37564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Java has no explicit unsigned support. 37664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @return A signed 32-bit integer. 37764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 37864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public static int decodeZigZag32(final int n) { 37964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return (n >>> 1) ^ -(n & 1); 38064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 38164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 38264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 38364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers 38464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * into values that can be efficiently encoded with varint. (Otherwise, 38564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * negative values must be sign-extended to 64 bits to be varint encoded, 38664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * thus always taking 10 bytes on the wire.) 38764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 38864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @param n An unsigned 64-bit integer, stored in a signed int because 38964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Java has no explicit unsigned support. 39064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @return A signed 64-bit integer. 39164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 39264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public static long decodeZigZag64(final long n) { 39364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return (n >>> 1) ^ -(n & 1); 39464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 39564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 39664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // ----------------------------------------------------------------- 39764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 39864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private final byte[] buffer; 39964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private int bufferStart; 40064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private int bufferSize; 40164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private int bufferSizeAfterLimit; 40264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private int bufferPos; 40364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private int lastTag; 40464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 40564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** The absolute position of the end of the current message. */ 40664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private int currentLimit = Integer.MAX_VALUE; 40764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 40864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** See setRecursionLimit() */ 40964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private int recursionDepth; 41064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private int recursionLimit = DEFAULT_RECURSION_LIMIT; 41164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 41264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** See setSizeLimit() */ 41364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private int sizeLimit = DEFAULT_SIZE_LIMIT; 41464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 41564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private static final int DEFAULT_RECURSION_LIMIT = 64; 41664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB 41764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 41864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private CodedInputByteBufferNano(final byte[] buffer, final int off, final int len) { 41964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci this.buffer = buffer; 42064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bufferStart = off; 42164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bufferSize = off + len; 42264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bufferPos = off; 42364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 42464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 42564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 42664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Set the maximum message recursion depth. In order to prevent malicious 42764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * messages from causing stack overflows, {@code CodedInputStream} limits 42864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * how deeply messages may be nested. The default limit is 64. 42964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 43064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @return the old limit. 43164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 43264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int setRecursionLimit(final int limit) { 43364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (limit < 0) { 43464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw new IllegalArgumentException( 43564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci "Recursion limit cannot be negative: " + limit); 43664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 43764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int oldLimit = recursionLimit; 43864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci recursionLimit = limit; 43964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return oldLimit; 44064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 44164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 44264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 44364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Set the maximum message size. In order to prevent malicious 44464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * messages from exhausting memory or causing integer overflows, 44564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * {@code CodedInputStream} limits how large a message may be. 44664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * The default limit is 64MB. You should set this limit as small 44764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * as you can without harming your app's functionality. Note that 44864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * size limits only apply when reading from an {@code InputStream}, not 44964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * when constructed around a raw byte array. 45064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * <p> 45164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * If you want to read several messages from a single CodedInputStream, you 45264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * could call {@link #resetSizeCounter()} after each one to avoid hitting the 45364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * size limit. 45464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 45564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @return the old limit. 45664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 45764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int setSizeLimit(final int limit) { 45864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (limit < 0) { 45964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw new IllegalArgumentException( 46064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci "Size limit cannot be negative: " + limit); 46164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 46264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int oldLimit = sizeLimit; 46364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci sizeLimit = limit; 46464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return oldLimit; 46564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 46664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 46764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 46864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). 46964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 47064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public void resetSizeCounter() { 47164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 47264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 47364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 47464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This 47564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * is called when descending into a length-delimited embedded message. 47664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 47764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @return the old limit. 47864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 47964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int pushLimit(int byteLimit) throws InvalidProtocolBufferNanoException { 48064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (byteLimit < 0) { 48164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.negativeSize(); 48264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 48364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci byteLimit += bufferPos; 48464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int oldLimit = currentLimit; 48564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (byteLimit > oldLimit) { 48664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.truncatedMessage(); 48764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 48864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci currentLimit = byteLimit; 48964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 49064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci recomputeBufferSizeAfterLimit(); 49164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 49264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return oldLimit; 49364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 49464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 49564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci private void recomputeBufferSizeAfterLimit() { 49664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bufferSize += bufferSizeAfterLimit; 49764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int bufferEnd = bufferSize; 49864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (bufferEnd > currentLimit) { 49964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // Limit is in current buffer. 50064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bufferSizeAfterLimit = bufferEnd - currentLimit; 50164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bufferSize -= bufferSizeAfterLimit; 50264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } else { 50364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bufferSizeAfterLimit = 0; 50464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 50564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 50664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 50764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 50864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Discards the current limit, returning to the previous limit. 50964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 51064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @param oldLimit The old limit, as returned by {@code pushLimit}. 51164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 51264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public void popLimit(final int oldLimit) { 51364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci currentLimit = oldLimit; 51464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci recomputeBufferSizeAfterLimit(); 51564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 51664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 51764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 51864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Returns the number of bytes to be read before the current limit. 51964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * If no limit is set, returns -1. 52064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 52164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int getBytesUntilLimit() { 52264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (currentLimit == Integer.MAX_VALUE) { 52364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return -1; 52464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 52564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 52664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final int currentAbsolutePosition = bufferPos; 52764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return currentLimit - currentAbsolutePosition; 52864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 52964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 53064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 53164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Returns true if the stream has reached the end of the input. This is the 53264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * case if either the end of the underlying input source has been reached or 53364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * if the stream has reached a limit created using {@link #pushLimit(int)}. 53464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 53564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public boolean isAtEnd() { 53664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return bufferPos == bufferSize; 53764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 53864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 53964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 54064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Get current position in buffer relative to beginning offset. 54164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 54264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public int getPosition() { 54364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return bufferPos - bufferStart; 54464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 54564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 54664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 5474f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson * Get current (absolute) position in buffer. 5484f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson */ 5494f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson public int getAbsolutePosition() { 5504f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson return bufferPos; 5514f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson } 5524f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson 5534f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson /** 5544f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson * Return the raw underlying data in the buffer, directly. 5554f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson */ 5564f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson public byte[] getBuffer() { 5574f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson return buffer; 5584f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson } 5594f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson 5604f87f0d25b75e045f55cc09c8a9085c1cd7cb238Jeff Davidson /** 5610e055f079f53b07de3705838a7b4742ce56839f8Brian Duff * Retrieves a subset of data in the buffer. The returned array is not backed by the original 5620e055f079f53b07de3705838a7b4742ce56839f8Brian Duff * buffer array. 5630e055f079f53b07de3705838a7b4742ce56839f8Brian Duff * 5640e055f079f53b07de3705838a7b4742ce56839f8Brian Duff * @param offset the position (relative to the buffer start position) to start at. 5650e055f079f53b07de3705838a7b4742ce56839f8Brian Duff * @param length the number of bytes to retrieve. 5660e055f079f53b07de3705838a7b4742ce56839f8Brian Duff */ 5670e055f079f53b07de3705838a7b4742ce56839f8Brian Duff public byte[] getData(int offset, int length) { 5680e055f079f53b07de3705838a7b4742ce56839f8Brian Duff if (length == 0) { 5690e055f079f53b07de3705838a7b4742ce56839f8Brian Duff return WireFormatNano.EMPTY_BYTES; 5700e055f079f53b07de3705838a7b4742ce56839f8Brian Duff } 5710e055f079f53b07de3705838a7b4742ce56839f8Brian Duff byte[] copy = new byte[length]; 5720e055f079f53b07de3705838a7b4742ce56839f8Brian Duff int start = bufferStart + offset; 5730e055f079f53b07de3705838a7b4742ce56839f8Brian Duff System.arraycopy(buffer, start, copy, 0, length); 5740e055f079f53b07de3705838a7b4742ce56839f8Brian Duff return copy; 5750e055f079f53b07de3705838a7b4742ce56839f8Brian Duff } 5760e055f079f53b07de3705838a7b4742ce56839f8Brian Duff 5770e055f079f53b07de3705838a7b4742ce56839f8Brian Duff /** 57864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Rewind to previous position. Cannot go forward. 57964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 58064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public void rewindToPosition(int position) { 58164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (position > bufferPos - bufferStart) { 58264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw new IllegalArgumentException( 58364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci "Position " + position + " is beyond current " + (bufferPos - bufferStart)); 58464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 58564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (position < 0) { 58664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw new IllegalArgumentException("Bad position " + position); 58764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 58864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bufferPos = bufferStart + position; 58964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 59064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 59164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 59264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Read one byte from the input. 59364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 59464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @throws InvalidProtocolBufferNanoException The end of the stream or the current 59564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * limit was reached. 59664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 59764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public byte readRawByte() throws IOException { 59864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (bufferPos == bufferSize) { 59964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.truncatedMessage(); 60064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 60164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return buffer[bufferPos++]; 60264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 60364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 60464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 60564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Read a fixed size of bytes from the input. 60664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 60764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @throws InvalidProtocolBufferNanoException The end of the stream or the current 60864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * limit was reached. 60964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 61064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public byte[] readRawBytes(final int size) throws IOException { 61164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (size < 0) { 61264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.negativeSize(); 61364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 61464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 61564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (bufferPos + size > currentLimit) { 61664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // Read to the end of the stream anyway. 61764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci skipRawBytes(currentLimit - bufferPos); 61864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // Then fail. 61964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.truncatedMessage(); 62064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 62164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 62264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (size <= bufferSize - bufferPos) { 62364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // We have all the bytes we need already. 62464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci final byte[] bytes = new byte[size]; 62564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci System.arraycopy(buffer, bufferPos, bytes, 0, size); 62664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bufferPos += size; 62764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return bytes; 62864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } else { 62964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.truncatedMessage(); 63064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 63164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 63264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 63364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci /** 63464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * Reads and discards {@code size} bytes. 63564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * 63664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @throws InvalidProtocolBufferNanoException The end of the stream or the current 63764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * limit was reached. 63864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */ 63964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci public void skipRawBytes(final int size) throws IOException { 64064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (size < 0) { 64164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.negativeSize(); 64264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 64364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 64464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (bufferPos + size > currentLimit) { 64564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // Read to the end of the stream anyway. 64664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci skipRawBytes(currentLimit - bufferPos); 64764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // Then fail. 64864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.truncatedMessage(); 64964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 65064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 65164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci if (size <= bufferSize - bufferPos) { 65264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci // We have all the bytes we need already. 65364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bufferPos += size; 65464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } else { 65564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci throw InvalidProtocolBufferNanoException.truncatedMessage(); 65664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 65764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci } 65864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci} 659