164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Protocol Buffers - Google's data interchange format
264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Copyright 2013 Google Inc.  All rights reserved.
3b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// https://developers.google.com/protocol-buffers/
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();
190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (size <= (bufferSize - bufferPos) && size > 0) {
191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // Fast path:  We already have the bytes in a contiguous buffer, so
192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      //   just copy directly from it.
193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      final String result = new String(buffer, bufferPos, size, InternalNano.UTF_8);
194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      bufferPos += size;
195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return result;
196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // Slow path:  Build a byte array first then copy it.
198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return new String(readRawBytes(size), InternalNano.UTF_8);
1999b8022f792896f4a6831abe8e30ee5b7977a3677Nathan Mittler    }
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();
232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (size <= (bufferSize - bufferPos) && size > 0) {
233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // Fast path:  We already have the bytes in a contiguous buffer, so
234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      //   just copy directly from it.
235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      final byte[] result = new byte[size];
236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      System.arraycopy(buffer, bufferPos, result, 0, size);
237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      bufferPos += size;
238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return result;
239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else if (size == 0) {
240584381094c72fdeab18a7bb158c27da82b70aecdAndre Eisenbach      return WireFormatNano.EMPTY_BYTES;
241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // Slow path:  Build a byte array first then copy it.
243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return readRawBytes(size);
24464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
24564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
24664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
24764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Read a {@code uint32} field value from the stream. */
24864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int readUInt32() throws IOException {
24964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return readRawVarint32();
25064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
25164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
25264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
25364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Read an enum field value from the stream.  Caller is responsible
25464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * for converting the numeric value to an actual enum.
25564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
25664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int readEnum() throws IOException {
25764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return readRawVarint32();
25864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
25964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
26064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Read an {@code sfixed32} field value from the stream. */
26164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int readSFixed32() throws IOException {
26264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return readRawLittleEndian32();
26364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
26464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
26564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Read an {@code sfixed64} field value from the stream. */
26664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public long readSFixed64() throws IOException {
26764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return readRawLittleEndian64();
26864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
26964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
27064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Read an {@code sint32} field value from the stream. */
27164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int readSInt32() throws IOException {
27264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return decodeZigZag32(readRawVarint32());
27364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
27464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
27564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Read an {@code sint64} field value from the stream. */
27664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public long readSInt64() throws IOException {
27764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return decodeZigZag64(readRawVarint64());
27864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
27964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
28064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // =================================================================
28164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
28264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
28364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Read a raw Varint from the stream.  If larger than 32 bits, discard the
28464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * upper bits.
28564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
28664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int readRawVarint32() throws IOException {
28764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    byte tmp = readRawByte();
28864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (tmp >= 0) {
28964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      return tmp;
29064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
29164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    int result = tmp & 0x7f;
29264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if ((tmp = readRawByte()) >= 0) {
29364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      result |= tmp << 7;
29464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    } else {
29564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      result |= (tmp & 0x7f) << 7;
29664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      if ((tmp = readRawByte()) >= 0) {
29764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        result |= tmp << 14;
29864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      } else {
29964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        result |= (tmp & 0x7f) << 14;
30064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        if ((tmp = readRawByte()) >= 0) {
30164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci          result |= tmp << 21;
30264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        } else {
30364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci          result |= (tmp & 0x7f) << 21;
30464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci          result |= (tmp = readRawByte()) << 28;
30564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci          if (tmp < 0) {
30664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci            // Discard upper 32 bits.
30764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci            for (int i = 0; i < 5; i++) {
30864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci              if (readRawByte() >= 0) {
30964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci                return result;
31064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci              }
31164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci            }
31264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci            throw InvalidProtocolBufferNanoException.malformedVarint();
31364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci          }
31464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        }
31564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      }
31664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
31764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return result;
31864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
31964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
32064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Read a raw Varint from the stream. */
32164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public long readRawVarint64() throws IOException {
32264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    int shift = 0;
32364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    long result = 0;
32464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    while (shift < 64) {
32564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      final byte b = readRawByte();
32664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      result |= (long)(b & 0x7F) << shift;
32764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      if ((b & 0x80) == 0) {
32864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        return result;
32964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      }
33064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      shift += 7;
33164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
33264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    throw InvalidProtocolBufferNanoException.malformedVarint();
33364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
33464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
33564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Read a 32-bit little-endian integer from the stream. */
33664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int readRawLittleEndian32() throws IOException {
33764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b1 = readRawByte();
33864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b2 = readRawByte();
33964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b3 = readRawByte();
34064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b4 = readRawByte();
34164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return ((b1 & 0xff)      ) |
34264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci           ((b2 & 0xff) <<  8) |
34364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci           ((b3 & 0xff) << 16) |
34464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci           ((b4 & 0xff) << 24);
34564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
34664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
34764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Read a 64-bit little-endian integer from the stream. */
34864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public long readRawLittleEndian64() throws IOException {
34964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b1 = readRawByte();
35064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b2 = readRawByte();
35164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b3 = readRawByte();
35264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b4 = readRawByte();
35364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b5 = readRawByte();
35464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b6 = readRawByte();
35564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b7 = readRawByte();
35664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final byte b8 = readRawByte();
35764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return (((long)b1 & 0xff)      ) |
35864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci           (((long)b2 & 0xff) <<  8) |
35964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci           (((long)b3 & 0xff) << 16) |
36064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci           (((long)b4 & 0xff) << 24) |
36164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci           (((long)b5 & 0xff) << 32) |
36264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci           (((long)b6 & 0xff) << 40) |
36364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci           (((long)b7 & 0xff) << 48) |
36464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci           (((long)b8 & 0xff) << 56);
36564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
36664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
36764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
36864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Decode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
36964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * into values that can be efficiently encoded with varint.  (Otherwise,
37064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * negative values must be sign-extended to 64 bits to be varint encoded,
37164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * thus always taking 10 bytes on the wire.)
37264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
37364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @param n An unsigned 32-bit integer, stored in a signed int because
37464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *          Java has no explicit unsigned support.
37564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @return A signed 32-bit integer.
37664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
37764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static int decodeZigZag32(final int n) {
37864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return (n >>> 1) ^ -(n & 1);
37964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
38064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
38164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
38264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Decode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
38364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * into values that can be efficiently encoded with varint.  (Otherwise,
38464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * negative values must be sign-extended to 64 bits to be varint encoded,
38564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * thus always taking 10 bytes on the wire.)
38664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
38764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @param n An unsigned 64-bit integer, stored in a signed int because
38864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *          Java has no explicit unsigned support.
38964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @return A signed 64-bit integer.
39064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
39164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static long decodeZigZag64(final long n) {
39264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return (n >>> 1) ^ -(n & 1);
39364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
39464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
39564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // -----------------------------------------------------------------
39664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
39764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private final byte[] buffer;
39864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private int bufferStart;
39964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private int bufferSize;
40064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private int bufferSizeAfterLimit;
40164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private int bufferPos;
40264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private int lastTag;
40364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
40464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** The absolute position of the end of the current message. */
40564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private int currentLimit = Integer.MAX_VALUE;
40664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
40764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** See setRecursionLimit() */
40864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private int recursionDepth;
40964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private int recursionLimit = DEFAULT_RECURSION_LIMIT;
41064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
41164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** See setSizeLimit() */
41264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private int sizeLimit = DEFAULT_SIZE_LIMIT;
41364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
41464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private static final int DEFAULT_RECURSION_LIMIT = 64;
41564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private static final int DEFAULT_SIZE_LIMIT = 64 << 20;  // 64MB
41664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
41764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private CodedInputByteBufferNano(final byte[] buffer, final int off, final int len) {
41864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    this.buffer = buffer;
41964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    bufferStart = off;
42064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    bufferSize = off + len;
42164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    bufferPos = off;
42264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
42364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
42464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
42564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Set the maximum message recursion depth.  In order to prevent malicious
42664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * messages from causing stack overflows, {@code CodedInputStream} limits
42764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * how deeply messages may be nested.  The default limit is 64.
42864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
42964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @return the old limit.
43064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
43164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int setRecursionLimit(final int limit) {
43264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (limit < 0) {
43364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw new IllegalArgumentException(
43464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        "Recursion limit cannot be negative: " + limit);
43564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
43664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final int oldLimit = recursionLimit;
43764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    recursionLimit = limit;
43864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return oldLimit;
43964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
44064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
44164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
44264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Set the maximum message size.  In order to prevent malicious
44364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * messages from exhausting memory or causing integer overflows,
44464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * {@code CodedInputStream} limits how large a message may be.
44564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * The default limit is 64MB.  You should set this limit as small
44664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * as you can without harming your app's functionality.  Note that
44764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * size limits only apply when reading from an {@code InputStream}, not
44864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * when constructed around a raw byte array.
44964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * <p>
45064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * If you want to read several messages from a single CodedInputStream, you
45164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * could call {@link #resetSizeCounter()} after each one to avoid hitting the
45264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * size limit.
45364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
45464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @return the old limit.
45564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
45664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int setSizeLimit(final int limit) {
45764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (limit < 0) {
45864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw new IllegalArgumentException(
45964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        "Size limit cannot be negative: " + limit);
46064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
46164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final int oldLimit = sizeLimit;
46264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    sizeLimit = limit;
46364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return oldLimit;
46464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
46564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
46664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
46764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
46864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
46964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public void resetSizeCounter() {
47064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
47164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
47264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
47364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Sets {@code currentLimit} to (current position) + {@code byteLimit}.  This
47464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * is called when descending into a length-delimited embedded message.
47564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
47664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @return the old limit.
47764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
47864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int pushLimit(int byteLimit) throws InvalidProtocolBufferNanoException {
47964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (byteLimit < 0) {
48064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw InvalidProtocolBufferNanoException.negativeSize();
48164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
48264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    byteLimit += bufferPos;
48364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final int oldLimit = currentLimit;
48464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (byteLimit > oldLimit) {
48564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw InvalidProtocolBufferNanoException.truncatedMessage();
48664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
48764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    currentLimit = byteLimit;
48864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
48964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    recomputeBufferSizeAfterLimit();
49064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
49164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return oldLimit;
49264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
49364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
49464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private void recomputeBufferSizeAfterLimit() {
49564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    bufferSize += bufferSizeAfterLimit;
49664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final int bufferEnd = bufferSize;
49764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (bufferEnd > currentLimit) {
49864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      // Limit is in current buffer.
49964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      bufferSizeAfterLimit = bufferEnd - currentLimit;
50064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      bufferSize -= bufferSizeAfterLimit;
50164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    } else {
50264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      bufferSizeAfterLimit = 0;
50364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
50464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
50564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
50664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
50764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Discards the current limit, returning to the previous limit.
50864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
50964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @param oldLimit The old limit, as returned by {@code pushLimit}.
51064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
51164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public void popLimit(final int oldLimit) {
51264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    currentLimit = oldLimit;
51364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    recomputeBufferSizeAfterLimit();
51464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
51564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
51664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
51764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Returns the number of bytes to be read before the current limit.
51864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * If no limit is set, returns -1.
51964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
52064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int getBytesUntilLimit() {
52164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (currentLimit == Integer.MAX_VALUE) {
52264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      return -1;
52364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
52464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
52564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    final int currentAbsolutePosition = bufferPos;
52664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return currentLimit - currentAbsolutePosition;
52764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
52864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
52964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
53064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Returns true if the stream has reached the end of the input.  This is the
53164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * case if either the end of the underlying input source has been reached or
53264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * if the stream has reached a limit created using {@link #pushLimit(int)}.
53364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
53464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public boolean isAtEnd() {
53564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return bufferPos == bufferSize;
53664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
53764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
53864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
53964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Get current position in buffer relative to beginning offset.
54064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
54164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public int getPosition() {
54264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return bufferPos - bufferStart;
54364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
54464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
54564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
546137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson   * Get current (absolute) position in buffer.
547137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson   */
548137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson  public int getAbsolutePosition() {
549137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson    return bufferPos;
550137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson  }
551137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson
552137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson  /**
553137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson   * Return the raw underlying data in the buffer, directly.
554137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson   */
555137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson  public byte[] getBuffer() {
556137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson    return buffer;
557137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson  }
558137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson
559137226a921d0f50c9e8a9f3ae43a3459b48d18a1Jeff Davidson  /**
5600e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * Retrieves a subset of data in the buffer. The returned array is not backed by the original
5610e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * buffer array.
5620e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   *
5630e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * @param offset the position (relative to the buffer start position) to start at.
5640e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * @param length the number of bytes to retrieve.
5650e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   */
5660e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  public byte[] getData(int offset, int length) {
5670e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    if (length == 0) {
5680e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      return WireFormatNano.EMPTY_BYTES;
5690e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
5700e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    byte[] copy = new byte[length];
5710e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    int start = bufferStart + offset;
5720e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    System.arraycopy(buffer, start, copy, 0, length);
5730e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    return copy;
5740e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  }
5750e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
5760e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  /**
57764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Rewind to previous position. Cannot go forward.
57864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
57964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public void rewindToPosition(int position) {
58064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (position > bufferPos - bufferStart) {
58164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw new IllegalArgumentException(
58264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci              "Position " + position + " is beyond current " + (bufferPos - bufferStart));
58364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
58464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (position < 0) {
58564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw new IllegalArgumentException("Bad position " + position);
58664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
58764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    bufferPos = bufferStart + position;
58864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
58964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
59064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
59164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Read one byte from the input.
59264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
59364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @throws InvalidProtocolBufferNanoException The end of the stream or the current
59464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *                                        limit was reached.
59564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
59664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public byte readRawByte() throws IOException {
59764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (bufferPos == bufferSize) {
59864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw InvalidProtocolBufferNanoException.truncatedMessage();
59964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
60064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return buffer[bufferPos++];
60164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
60264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
60364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
60464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Read a fixed size of bytes from the input.
60564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
60664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @throws InvalidProtocolBufferNanoException The end of the stream or the current
60764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *                                        limit was reached.
60864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
60964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public byte[] readRawBytes(final int size) throws IOException {
61064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (size < 0) {
61164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw InvalidProtocolBufferNanoException.negativeSize();
61264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
61364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
61464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (bufferPos + size > currentLimit) {
61564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      // Read to the end of the stream anyway.
61664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      skipRawBytes(currentLimit - bufferPos);
61764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      // Then fail.
61864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw InvalidProtocolBufferNanoException.truncatedMessage();
61964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
62064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
62164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (size <= bufferSize - bufferPos) {
62264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      // We have all the bytes we need already.
62364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      final byte[] bytes = new byte[size];
62464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      System.arraycopy(buffer, bufferPos, bytes, 0, size);
62564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      bufferPos += size;
62664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      return bytes;
62764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    } else {
62864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw InvalidProtocolBufferNanoException.truncatedMessage();
62964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
63064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
63164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
63264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
63364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Reads and discards {@code size} bytes.
63464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
63564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @throws InvalidProtocolBufferNanoException The end of the stream or the current
63664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *                                        limit was reached.
63764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
63864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public void skipRawBytes(final int size) throws IOException {
63964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (size < 0) {
64064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw InvalidProtocolBufferNanoException.negativeSize();
64164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
64264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
64364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (bufferPos + size > currentLimit) {
64464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      // Read to the end of the stream anyway.
64564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      skipRawBytes(currentLimit - bufferPos);
64664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      // Then fail.
64764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw InvalidProtocolBufferNanoException.truncatedMessage();
64864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
64964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
65064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (size <= bufferSize - bufferPos) {
65164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      // We have all the bytes we need already.
65264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      bufferPos += size;
65364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    } else {
65464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      throw InvalidProtocolBufferNanoException.truncatedMessage();
65564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
65664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Read a primitive type.
659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  Object readPrimitiveField(int type) throws IOException {
660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch (type) {
661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_DOUBLE:
662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readDouble();
663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_FLOAT:
664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readFloat();
665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_INT64:
666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readInt64();
667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_UINT64:
668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readUInt64();
669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_INT32:
670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readInt32();
671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_FIXED64:
672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readFixed64();
673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_FIXED32:
674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readFixed32();
675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_BOOL:
676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readBool();
677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_STRING:
678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readString();
679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_BYTES:
680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readBytes();
681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_UINT32:
682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readUInt32();
683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_ENUM:
684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readEnum();
685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_SFIXED32:
686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readSFixed32();
687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_SFIXED64:
688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readSFixed64();
689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_SINT32:
690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readSInt32();
691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case InternalNano.TYPE_SINT64:
692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return readSInt64();
693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      default:
694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          throw new IllegalArgumentException("Unknown type " + type);
695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
69764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci}
698