1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc.  All rights reserved.
3afb4b72037e3f13db208590fc782c4bc8e27f862Jeff Davidson// https://developers.google.com/protocol-buffers/
4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without
6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are
7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met:
8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions of source code must retain the above copyright
10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer.
11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions in binary form must reproduce the above
12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer
13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the
14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution.
15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Neither the name of Google Inc. nor the names of its
16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from
17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission.
18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillepackage com.google.protobuf;
32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
33a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.io.ByteArrayOutputStream;
34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.io.IOException;
35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.io.InputStream;
36a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.nio.ByteBuffer;
37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.util.ArrayList;
38a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.util.Arrays;
39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.util.List;
40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville/**
42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Reads and decodes protocol message fields.
43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *
44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * This class contains two kinds of methods:  methods that read specific
45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * protocol message constructs and field types (e.g. {@link #readTag()} and
46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@link #readInt32()}) and methods that read low-level values (e.g.
47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * {@link #readRawVarint32()} and {@link #readRawBytes}).  If you are reading
48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * encoded protocol messages, you should use the former methods, but if you are
49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * reading some other format of your own design, use the latter.
50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *
51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @author kenton@google.com Kenton Varda
52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */
53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillepublic final class CodedInputStream {
54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Create a new CodedInputStream wrapping the given InputStream.
56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public static CodedInputStream newInstance(final InputStream input) {
58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return new CodedInputStream(input);
59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Create a new CodedInputStream wrapping the given byte array.
63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public static CodedInputStream newInstance(final byte[] buf) {
65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return newInstance(buf, 0, buf.length);
66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Create a new CodedInputStream wrapping the given byte array slice.
70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public static CodedInputStream newInstance(final byte[] buf, final int off,
72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                                             final int len) {
73a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    CodedInputStream result = new CodedInputStream(buf, off, len);
74a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    try {
75a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // Some uses of CodedInputStream can be more efficient if they know
76a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // exactly how many bytes are available.  By pushing the end point of the
77a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // buffer as a limit, we allow them to get this information via
78a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // getBytesUntilLimit().  Pushing a limit that we know is at the end of
79a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // the stream can never hurt, since we can never past that point anyway.
80a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      result.pushLimit(len);
81a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } catch (InvalidProtocolBufferException ex) {
82a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // The only reason pushLimit() might throw an exception here is if len
83a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // is negative. Normally pushLimit()'s parameter comes directly off the
84a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // wire, so it's important to catch exceptions in case of corrupt or
85a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // malicious data. However, in this case, we expect that len is not a
86a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // user-supplied value, so we can assume that it being negative indicates
87a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // a programming error. Therefore, throwing an unchecked exception is
88a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // appropriate.
89a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throw new IllegalArgumentException(ex);
90a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
91a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return result;
92a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
93a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
94a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
95a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Create a new CodedInputStream wrapping the given ByteBuffer. The data
96a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * starting from the ByteBuffer's current position to its limit will be read.
97a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * The returned CodedInputStream may or may not share the underlying data
98a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * in the ByteBuffer, therefore the ByteBuffer cannot be changed while the
99a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * CodedInputStream is in use.
100a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Note that the ByteBuffer's position won't be changed by this function.
101a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Concurrent calls with the same ByteBuffer object are safe if no other
102a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * thread is trying to alter the ByteBuffer's status.
103a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
104a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static CodedInputStream newInstance(ByteBuffer buf) {
105a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (buf.hasArray()) {
106a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return newInstance(buf.array(), buf.arrayOffset() + buf.position(),
107a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          buf.remaining());
108a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
109a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      ByteBuffer temp = buf.duplicate();
110a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      byte[] buffer = new byte[temp.remaining()];
111a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      temp.get(buffer);
112a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return newInstance(buffer);
113a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
114a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
115a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
116a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
117a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Create a new CodedInputStream wrapping a LiteralByteString.
118a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
119a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  static CodedInputStream newInstance(LiteralByteString byteString) {
120a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    CodedInputStream result = new CodedInputStream(byteString);
121a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    try {
122a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // Some uses of CodedInputStream can be more efficient if they know
123a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // exactly how many bytes are available.  By pushing the end point of the
124a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // buffer as a limit, we allow them to get this information via
125a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // getBytesUntilLimit().  Pushing a limit that we know is at the end of
126a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // the stream can never hurt, since we can never past that point anyway.
127a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      result.pushLimit(byteString.size());
128a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } catch (InvalidProtocolBufferException ex) {
129a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // The only reason pushLimit() might throw an exception here is if len
130a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // is negative. Normally pushLimit()'s parameter comes directly off the
131a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // wire, so it's important to catch exceptions in case of corrupt or
132a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // malicious data. However, in this case, we expect that len is not a
133a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // user-supplied value, so we can assume that it being negative indicates
134a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // a programming error. Therefore, throwing an unchecked exception is
135a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // appropriate.
136a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throw new IllegalArgumentException(ex);
137a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
138a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return result;
139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // -----------------------------------------------------------------
142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Attempt to read a field tag, returning zero if we have reached EOF.
145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Protocol message parsers use this to read tags, since a protocol message
146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * may legally end wherever a tag occurs, and zero is not a valid tag number.
147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int readTag() throws IOException {
149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (isAtEnd()) {
150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      lastTag = 0;
151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return 0;
152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    lastTag = readRawVarint32();
155d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (WireFormat.getTagFieldNumber(lastTag) == 0) {
156d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // If we actually read zero (or any tag number corresponding to field
157d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // number zero), that's not a valid tag.
158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw InvalidProtocolBufferException.invalidTag();
159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return lastTag;
161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Verifies that the last call to readTag() returned the given tag value.
165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * This is used to verify that a nested group ended with the correct
166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * end tag.
167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @throws InvalidProtocolBufferException {@code value} does not match the
169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *                                        last tag.
170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public void checkLastTagWas(final int value)
172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                              throws InvalidProtocolBufferException {
173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (lastTag != value) {
174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw InvalidProtocolBufferException.invalidEndTag();
175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
178a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public int getLastTag() {
179a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return lastTag;
180a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
181a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Reads and discards a single field, given its tag value.
184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @return {@code false} if the tag is an endgroup tag, in which case
186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *         nothing is skipped.  Otherwise, returns {@code true}.
187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public boolean skipField(final int tag) throws IOException {
189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    switch (WireFormat.getTagWireType(tag)) {
190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      case WireFormat.WIRETYPE_VARINT:
191a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        skipRawVarint();
192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        return true;
193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      case WireFormat.WIRETYPE_FIXED64:
194a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        skipRawBytes(8);
195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        return true;
196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      case WireFormat.WIRETYPE_LENGTH_DELIMITED:
197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        skipRawBytes(readRawVarint32());
198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        return true;
199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      case WireFormat.WIRETYPE_START_GROUP:
200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        skipMessage();
201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        checkLastTagWas(
202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          WireFormat.makeTag(WireFormat.getTagFieldNumber(tag),
203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                             WireFormat.WIRETYPE_END_GROUP));
204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        return true;
205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      case WireFormat.WIRETYPE_END_GROUP:
206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        return false;
207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      case WireFormat.WIRETYPE_FIXED32:
208a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        skipRawBytes(4);
209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        return true;
210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      default:
211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        throw InvalidProtocolBufferException.invalidWireType();
212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
216a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Reads a single field and writes it to output in wire format,
217a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * given its tag value.
218a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
219a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return {@code false} if the tag is an endgroup tag, in which case
220a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *         nothing is skipped.  Otherwise, returns {@code true}.
221a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
222a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public boolean skipField(final int tag, final CodedOutputStream output)
223a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throws IOException {
224a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    switch (WireFormat.getTagWireType(tag)) {
225a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      case WireFormat.WIRETYPE_VARINT: {
226a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        long value = readInt64();
227a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        output.writeRawVarint32(tag);
228a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        output.writeUInt64NoTag(value);
229a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return true;
230a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
231a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      case WireFormat.WIRETYPE_FIXED64: {
232a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        long value = readRawLittleEndian64();
233a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        output.writeRawVarint32(tag);
234a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        output.writeFixed64NoTag(value);
235a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return true;
236a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
237a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      case WireFormat.WIRETYPE_LENGTH_DELIMITED: {
238a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        ByteString value = readBytes();
239a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        output.writeRawVarint32(tag);
240a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        output.writeBytesNoTag(value);
241a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return true;
242a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
243a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      case WireFormat.WIRETYPE_START_GROUP: {
244a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        output.writeRawVarint32(tag);
245a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        skipMessage(output);
246a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        int endtag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag),
247a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson                                        WireFormat.WIRETYPE_END_GROUP);
248a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        checkLastTagWas(endtag);
249a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        output.writeRawVarint32(endtag);
250a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return true;
251a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
252a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      case WireFormat.WIRETYPE_END_GROUP: {
253a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return false;
254a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
255a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      case WireFormat.WIRETYPE_FIXED32: {
256a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        int value = readRawLittleEndian32();
257a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        output.writeRawVarint32(tag);
258a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        output.writeFixed32NoTag(value);
259a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return true;
260a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
261a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      default:
262a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        throw InvalidProtocolBufferException.invalidWireType();
263a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
264a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
265a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
266a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Reads and discards an entire message.  This will read either until EOF
268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * or until an endgroup tag, whichever comes first.
269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public void skipMessage() throws IOException {
271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    while (true) {
272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      final int tag = readTag();
273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      if (tag == 0 || !skipField(tag)) {
274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        return;
275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
279a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
280a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Reads an entire message and writes it to output in wire format.
281a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * This will read either until EOF or until an endgroup tag,
282a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * whichever comes first.
283a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
284a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public void skipMessage(CodedOutputStream output) throws IOException {
285a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    while (true) {
286a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final int tag = readTag();
287a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (tag == 0 || !skipField(tag, output)) {
288a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return;
289a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
290a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
291a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
292a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
293a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
294a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Collects the bytes skipped and returns the data in a ByteBuffer.
295a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
296a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private class SkippedDataSink implements RefillCallback {
297a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private int lastPos = bufferPos;
298a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private ByteArrayOutputStream byteArrayStream;
299a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
300a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
301a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public void onRefill() {
302a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (byteArrayStream == null) {
303a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        byteArrayStream = new ByteArrayOutputStream();
304a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
305a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      byteArrayStream.write(buffer, lastPos, bufferPos - lastPos);
306a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      lastPos = 0;
307a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
308a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
309a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    /**
310a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * Gets skipped data in a ByteBuffer. This method should only be
311a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * called once.
312a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     */
313a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    ByteBuffer getSkippedData() {
314a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (byteArrayStream == null) {
315a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return ByteBuffer.wrap(buffer, lastPos, bufferPos - lastPos);
316a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else {
317a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        byteArrayStream.write(buffer, lastPos, bufferPos);
318a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return ByteBuffer.wrap(byteArrayStream.toByteArray());
319a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
320a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
321a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
322a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
323a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
324fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // -----------------------------------------------------------------
325fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
326fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a {@code double} field value from the stream. */
327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public double readDouble() throws IOException {
328fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return Double.longBitsToDouble(readRawLittleEndian64());
329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a {@code float} field value from the stream. */
332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public float readFloat() throws IOException {
333fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return Float.intBitsToFloat(readRawLittleEndian32());
334fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
335fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
336fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a {@code uint64} field value from the stream. */
337fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public long readUInt64() throws IOException {
338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return readRawVarint64();
339fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
340fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
341fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read an {@code int64} field value from the stream. */
342fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public long readInt64() throws IOException {
343fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return readRawVarint64();
344fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
345fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
346fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read an {@code int32} field value from the stream. */
347fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int readInt32() throws IOException {
348fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return readRawVarint32();
349fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
350fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
351fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a {@code fixed64} field value from the stream. */
352fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public long readFixed64() throws IOException {
353fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return readRawLittleEndian64();
354fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
355fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
356fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a {@code fixed32} field value from the stream. */
357fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int readFixed32() throws IOException {
358fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return readRawLittleEndian32();
359fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
360fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
361fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a {@code bool} field value from the stream. */
362fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public boolean readBool() throws IOException {
363a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return readRawVarint64() != 0;
364fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
365fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
366a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
367a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Read a {@code string} field value from the stream.
368a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * If the stream contains malformed UTF-8,
369a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * replace the offending bytes with the standard UTF-8 replacement character.
370a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
371fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public String readString() throws IOException {
372fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    final int size = readRawVarint32();
373fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (size <= (bufferSize - bufferPos) && size > 0) {
374fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Fast path:  We already have the bytes in a contiguous buffer, so
375fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      //   just copy directly from it.
376fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      final String result = new String(buffer, bufferPos, size, "UTF-8");
377fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bufferPos += size;
378fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return result;
379a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else if (size == 0) {
380a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return "";
381fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    } else {
382fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Slow path:  Build a byte array first then copy it.
383a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return new String(readRawBytesSlowPath(size), "UTF-8");
384a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
385a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
386a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
387a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
388a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Read a {@code string} field value from the stream.
389a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * If the stream contains malformed UTF-8,
390a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * throw exception {@link InvalidProtocolBufferException}.
391a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
392a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public String readStringRequireUtf8() throws IOException {
393a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    final int size = readRawVarint32();
394a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    final byte[] bytes;
395a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    int pos = bufferPos;
396a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (size <= (bufferSize - pos) && size > 0) {
397a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // Fast path:  We already have the bytes in a contiguous buffer, so
398a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      //   just copy directly from it.
399a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bytes = buffer;
400a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos = pos + size;
401a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else if (size == 0) {
402a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return "";
403a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
404a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // Slow path:  Build a byte array first then copy it.
405a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bytes = readRawBytesSlowPath(size);
406a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      pos = 0;
407a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
408a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // TODO(martinrb): We could save a pass by validating while decoding.
409a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (!Utf8.isValidUtf8(bytes, pos, pos + size)) {
410a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throw InvalidProtocolBufferException.invalidUtf8();
411fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
412a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return new String(bytes, pos, size, "UTF-8");
413fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
414fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
415fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a {@code group} field value from the stream. */
416fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public void readGroup(final int fieldNumber,
417fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                        final MessageLite.Builder builder,
418fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                        final ExtensionRegistryLite extensionRegistry)
419fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throws IOException {
420fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (recursionDepth >= recursionLimit) {
421fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw InvalidProtocolBufferException.recursionLimitExceeded();
422fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
423fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ++recursionDepth;
424fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    builder.mergeFrom(this, extensionRegistry);
425fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    checkLastTagWas(
426fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
427fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    --recursionDepth;
428fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
429fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
430a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
431a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /** Read a {@code group} field value from the stream. */
432a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public <T extends MessageLite> T readGroup(
433a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final int fieldNumber,
434a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final Parser<T> parser,
435a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final ExtensionRegistryLite extensionRegistry)
436a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throws IOException {
437a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (recursionDepth >= recursionLimit) {
438a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throw InvalidProtocolBufferException.recursionLimitExceeded();
439a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
440a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    ++recursionDepth;
441a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    T result = parser.parsePartialFrom(this, extensionRegistry);
442a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    checkLastTagWas(
443a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
444a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    --recursionDepth;
445a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return result;
446a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
447a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
448fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
449fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Reads a {@code group} field value from the stream and merges it into the
450fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * given {@link UnknownFieldSet}.
451fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
452fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so
453fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *             you can just call {@link #readGroup}.
454fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
455fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  @Deprecated
456fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public void readUnknownGroup(final int fieldNumber,
457fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                               final MessageLite.Builder builder)
458fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throws IOException {
459fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // We know that UnknownFieldSet will ignore any ExtensionRegistry so it
460fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // is safe to pass null here.  (We can't call
461fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // ExtensionRegistry.getEmptyRegistry() because that would make this
462fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // class depend on ExtensionRegistry, which is not part of the lite
463fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // library.)
464fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    readGroup(fieldNumber, builder, null);
465fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
466fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
467fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read an embedded message field value from the stream. */
468fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public void readMessage(final MessageLite.Builder builder,
469fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                          final ExtensionRegistryLite extensionRegistry)
470fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throws IOException {
471fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    final int length = readRawVarint32();
472fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (recursionDepth >= recursionLimit) {
473fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw InvalidProtocolBufferException.recursionLimitExceeded();
474fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
475fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    final int oldLimit = pushLimit(length);
476fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ++recursionDepth;
477fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    builder.mergeFrom(this, extensionRegistry);
478fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    checkLastTagWas(0);
479fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    --recursionDepth;
480fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    popLimit(oldLimit);
481fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
482fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
483a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
484a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /** Read an embedded message field value from the stream. */
485a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public <T extends MessageLite> T readMessage(
486a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final Parser<T> parser,
487a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final ExtensionRegistryLite extensionRegistry)
488a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throws IOException {
489a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    int length = readRawVarint32();
490a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (recursionDepth >= recursionLimit) {
491a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throw InvalidProtocolBufferException.recursionLimitExceeded();
492a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
493a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    final int oldLimit = pushLimit(length);
494a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    ++recursionDepth;
495a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    T result = parser.parsePartialFrom(this, extensionRegistry);
496a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    checkLastTagWas(0);
497a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    --recursionDepth;
498a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    popLimit(oldLimit);
499a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return result;
500a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
501a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
502fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a {@code bytes} field value from the stream. */
503fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public ByteString readBytes() throws IOException {
504fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    final int size = readRawVarint32();
505fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (size <= (bufferSize - bufferPos) && size > 0) {
506fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Fast path:  We already have the bytes in a contiguous buffer, so
507fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      //   just copy directly from it.
508a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final ByteString result = bufferIsImmutable && enableAliasing
509a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          ? new BoundedByteString(buffer, bufferPos, size)
510a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          : ByteString.copyFrom(buffer, bufferPos, size);
511fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bufferPos += size;
512fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return result;
513a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else if (size == 0) {
514a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return ByteString.EMPTY;
515fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    } else {
516fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Slow path:  Build a byte array first then copy it.
517a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return new LiteralByteString(readRawBytesSlowPath(size));
518a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
519a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
520a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
521a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /** Read a {@code bytes} field value from the stream. */
522a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public byte[] readByteArray() throws IOException {
523a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    final int size = readRawVarint32();
524a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (size <= (bufferSize - bufferPos) && size > 0) {
525a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // Fast path: We already have the bytes in a contiguous buffer, so
526a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // just copy directly from it.
527a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final byte[] result =
528a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          Arrays.copyOfRange(buffer, bufferPos, bufferPos + size);
529a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos += size;
530a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return result;
531a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
532a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // Slow path: Build a byte array first then copy it.
533a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return readRawBytesSlowPath(size);
534a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
535a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
536a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
537a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /** Read a {@code bytes} field value from the stream. */
538a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public ByteBuffer readByteBuffer() throws IOException {
539a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    final int size = readRawVarint32();
540a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (size <= (bufferSize - bufferPos) && size > 0) {
541a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // Fast path: We already have the bytes in a contiguous buffer.
542a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // When aliasing is enabled, we can return a ByteBuffer pointing directly
543a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // into the underlying byte array without copy if the CodedInputStream is
544a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // constructed from a byte array. If aliasing is disabled or the input is
545a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // from an InputStream or ByteString, we have to make a copy of the bytes.
546a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      ByteBuffer result = input == null && !bufferIsImmutable && enableAliasing
547a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          ? ByteBuffer.wrap(buffer, bufferPos, size).slice()
548a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          : ByteBuffer.wrap(Arrays.copyOfRange(
549a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson              buffer, bufferPos, bufferPos + size));
550a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos += size;
551a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return result;
552a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else if (size == 0) {
553a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return Internal.EMPTY_BYTE_BUFFER;
554a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
555a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // Slow path: Build a byte array first then copy it.
556a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return ByteBuffer.wrap(readRawBytesSlowPath(size));
557fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
558fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
559fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
560fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a {@code uint32} field value from the stream. */
561fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int readUInt32() throws IOException {
562fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return readRawVarint32();
563fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
564fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
565fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
566fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Read an enum field value from the stream.  Caller is responsible
567fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * for converting the numeric value to an actual enum.
568fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
569fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int readEnum() throws IOException {
570fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return readRawVarint32();
571fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
572fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
573fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read an {@code sfixed32} field value from the stream. */
574fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int readSFixed32() throws IOException {
575fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return readRawLittleEndian32();
576fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
577fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
578fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read an {@code sfixed64} field value from the stream. */
579fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public long readSFixed64() throws IOException {
580fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return readRawLittleEndian64();
581fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
582fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
583fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read an {@code sint32} field value from the stream. */
584fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int readSInt32() throws IOException {
585fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return decodeZigZag32(readRawVarint32());
586fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
587fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
588fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read an {@code sint64} field value from the stream. */
589fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public long readSInt64() throws IOException {
590fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return decodeZigZag64(readRawVarint64());
591fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
592fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
593fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // =================================================================
594fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
595fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
596fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Read a raw Varint from the stream.  If larger than 32 bits, discard the
597fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * upper bits.
598fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
599fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int readRawVarint32() throws IOException {
600a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // See implementation notes for readRawVarint64
601a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson fastpath: {
602a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int pos = bufferPos;
603a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
604a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (bufferSize == pos) {
605a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        break fastpath;
606a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
607a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
608a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final byte[] buffer = this.buffer;
609a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int x;
610a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if ((x = buffer[pos++]) >= 0) {
611a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        bufferPos = pos;
612a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return x;
613a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if (bufferSize - pos < 9) {
614a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        break fastpath;
615a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if ((x ^= (buffer[pos++] << 7)) < 0L) {
616a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7);
617a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if ((x ^= (buffer[pos++] << 14)) >= 0L) {
618a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7) ^ (~0L << 14);
619a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if ((x ^= (buffer[pos++] << 21)) < 0L) {
620a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21);
621fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      } else {
622a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        int y = buffer[pos++];
623a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= y << 28;
624a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
625a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        if (y < 0 &&
626a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            buffer[pos++] < 0 &&
627a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            buffer[pos++] < 0 &&
628a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            buffer[pos++] < 0 &&
629a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            buffer[pos++] < 0 &&
630a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            buffer[pos++] < 0) {
631a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          break fastpath;  // Will throw malformedVarint()
632fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        }
633fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
634a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos = pos;
635a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return x;
636fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
637a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return (int) readRawVarint64SlowPath();
638a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
639a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
640a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private void skipRawVarint() throws IOException {
641a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (bufferSize - bufferPos >= 10) {
642a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final byte[] buffer = this.buffer;
643a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int pos = bufferPos;
644a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      for (int i = 0; i < 10; i++) {
645a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        if (buffer[pos++] >= 0) {
646a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          bufferPos = pos;
647a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          return;
648a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        }
649a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
650a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
651a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    skipRawVarintSlowPath();
652a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
653a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
654a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private void skipRawVarintSlowPath() throws IOException {
655a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    for (int i = 0; i < 10; i++) {
656a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (readRawByte() >= 0) {
657a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return;
658a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
659a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
660a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    throw InvalidProtocolBufferException.malformedVarint();
661fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
662fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
663fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
664fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Reads a varint from the input one byte at a time, so that it does not
665fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * read any bytes after the end of the varint.  If you simply wrapped the
666fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)}
667fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * then you would probably end up reading past the end of the varint since
668fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * CodedInputStream buffers its input.
669fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
670fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  static int readRawVarint32(final InputStream input) throws IOException {
671d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    final int firstByte = input.read();
672d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (firstByte == -1) {
673d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      throw InvalidProtocolBufferException.truncatedMessage();
674d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
675d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return readRawVarint32(firstByte, input);
676d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
677d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
678d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  /**
679d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * Like {@link #readRawVarint32(InputStream)}, but expects that the caller
680d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * has already read one byte.  This allows the caller to determine if EOF
681d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * has been reached before attempting to read.
682d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   */
683a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static int readRawVarint32(
684a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final int firstByte, final InputStream input) throws IOException {
685d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if ((firstByte & 0x80) == 0) {
686d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return firstByte;
687d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
688d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
689d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    int result = firstByte & 0x7f;
690d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    int offset = 7;
691fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (; offset < 32; offset += 7) {
692fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      final int b = input.read();
693fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      if (b == -1) {
694fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        throw InvalidProtocolBufferException.truncatedMessage();
695fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
696fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      result |= (b & 0x7f) << offset;
697fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      if ((b & 0x80) == 0) {
698fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        return result;
699fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
700fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
701fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // Keep reading up to 64 bits.
702fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (; offset < 64; offset += 7) {
703fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      final int b = input.read();
704fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      if (b == -1) {
705fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        throw InvalidProtocolBufferException.truncatedMessage();
706fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
707fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      if ((b & 0x80) == 0) {
708fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        return result;
709fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
710fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
711fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    throw InvalidProtocolBufferException.malformedVarint();
712fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
713fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
714fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a raw Varint from the stream. */
715fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public long readRawVarint64() throws IOException {
716a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // Implementation notes:
717a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    //
718a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // Optimized for one-byte values, expected to be common.
719a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // The particular code below was selected from various candidates
720a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // empirically, by winning VarintBenchmark.
721a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    //
722a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // Sign extension of (signed) Java bytes is usually a nuisance, but
723a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // we exploit it here to more easily obtain the sign of bytes read.
724a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // Instead of cleaning up the sign extension bits by masking eagerly,
725a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // we delay until we find the final (positive) byte, when we clear all
726a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // accumulated bits with one xor.  We depend on javac to constant fold.
727a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson fastpath: {
728a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int pos = bufferPos;
729a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
730a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (bufferSize == pos) {
731a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        break fastpath;
732a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
733a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
734a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final byte[] buffer = this.buffer;
735a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      long x;
736a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int y;
737a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if ((y = buffer[pos++]) >= 0) {
738a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        bufferPos = pos;
739a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return y;
740a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if (bufferSize - pos < 9) {
741a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        break fastpath;
742a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if ((x = y ^ (buffer[pos++] << 7)) < 0L) {
743a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7);
744a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if ((x ^= (buffer[pos++] << 14)) >= 0L) {
745a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7) ^ (~0L << 14);
746a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if ((x ^= (buffer[pos++] << 21)) < 0L) {
747a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21);
748a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if ((x ^= ((long) buffer[pos++] << 28)) >= 0L) {
749a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
750a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if ((x ^= ((long) buffer[pos++] << 35)) < 0L) {
751a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
752a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if ((x ^= ((long) buffer[pos++] << 42)) >= 0L) {
753a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
754a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else if ((x ^= ((long) buffer[pos++] << 49)) < 0L) {
755a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42)
756a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            ^ (~0L << 49);
757a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else {
758a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= ((long) buffer[pos++] << 56);
759a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42)
760a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            ^ (~0L << 49) ^ (~0L << 56);
761a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        if (x < 0L) {
762a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          if (buffer[pos++] < 0L) {
763a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            break fastpath;  // Will throw malformedVarint()
764a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          }
765a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        }
766a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
767a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos = pos;
768a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return x;
769a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
770a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return readRawVarint64SlowPath();
771a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
772a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
773a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /** Variant of readRawVarint64 for when uncomfortably close to the limit. */
774a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /* Visible for testing */
775a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  long readRawVarint64SlowPath() throws IOException {
776fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    long result = 0;
777a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    for (int shift = 0; shift < 64; shift += 7) {
778fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      final byte b = readRawByte();
779a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      result |= (long) (b & 0x7F) << shift;
780fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      if ((b & 0x80) == 0) {
781fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        return result;
782fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
783fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
784fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    throw InvalidProtocolBufferException.malformedVarint();
785fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
786fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
787fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a 32-bit little-endian integer from the stream. */
788fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int readRawLittleEndian32() throws IOException {
789a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    int pos = bufferPos;
790a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
791a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // hand-inlined ensureAvailable(4);
792a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (bufferSize - pos < 4) {
793a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      refillBuffer(4);
794a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      pos = bufferPos;
795a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
796a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
797a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    final byte[] buffer = this.buffer;
798a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    bufferPos = pos + 4;
799a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return (((buffer[pos]     & 0xff))       |
800a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            ((buffer[pos + 1] & 0xff) <<  8) |
801a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            ((buffer[pos + 2] & 0xff) << 16) |
802a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            ((buffer[pos + 3] & 0xff) << 24));
803fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
804fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
805fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** Read a 64-bit little-endian integer from the stream. */
806fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public long readRawLittleEndian64() throws IOException {
807a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    int pos = bufferPos;
808a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
809a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // hand-inlined ensureAvailable(8);
810a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (bufferSize - pos < 8) {
811a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      refillBuffer(8);
812a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      pos = bufferPos;
813a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
814a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
815a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    final byte[] buffer = this.buffer;
816a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    bufferPos = pos + 8;
817a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return ((((long) buffer[pos]     & 0xffL))       |
818a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            (((long) buffer[pos + 1] & 0xffL) <<  8) |
819a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            (((long) buffer[pos + 2] & 0xffL) << 16) |
820a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            (((long) buffer[pos + 3] & 0xffL) << 24) |
821a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            (((long) buffer[pos + 4] & 0xffL) << 32) |
822a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            (((long) buffer[pos + 5] & 0xffL) << 40) |
823a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            (((long) buffer[pos + 6] & 0xffL) << 48) |
824a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            (((long) buffer[pos + 7] & 0xffL) << 56));
825fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
826fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
827fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
828fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Decode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
829fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * into values that can be efficiently encoded with varint.  (Otherwise,
830fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * negative values must be sign-extended to 64 bits to be varint encoded,
831fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * thus always taking 10 bytes on the wire.)
832fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
833fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @param n An unsigned 32-bit integer, stored in a signed int because
834fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *          Java has no explicit unsigned support.
835fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @return A signed 32-bit integer.
836fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
837fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public static int decodeZigZag32(final int n) {
838fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return (n >>> 1) ^ -(n & 1);
839fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
840fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
841fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
842fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Decode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
843fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * into values that can be efficiently encoded with varint.  (Otherwise,
844fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * negative values must be sign-extended to 64 bits to be varint encoded,
845fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * thus always taking 10 bytes on the wire.)
846fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
847fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @param n An unsigned 64-bit integer, stored in a signed int because
848fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *          Java has no explicit unsigned support.
849fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @return A signed 64-bit integer.
850fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
851fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public static long decodeZigZag64(final long n) {
852fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return (n >>> 1) ^ -(n & 1);
853fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
854fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
855fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // -----------------------------------------------------------------
856fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
857fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private final byte[] buffer;
858a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private final boolean bufferIsImmutable;
859fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private int bufferSize;
860fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private int bufferSizeAfterLimit;
861fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private int bufferPos;
862fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private final InputStream input;
863fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private int lastTag;
864a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private boolean enableAliasing = false;
865fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
866fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
867fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * The total number of bytes read before the current buffer.  The total
868fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * bytes read up to the current position can be computed as
869d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * {@code totalBytesRetired + bufferPos}.  This value may be negative if
870d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * reading started in the middle of the current buffer (e.g. if the
871d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * constructor that takes a byte array and an offset was used).
872fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
873fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private int totalBytesRetired;
874fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
875fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** The absolute position of the end of the current message. */
876fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private int currentLimit = Integer.MAX_VALUE;
877fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
878fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** See setRecursionLimit() */
879fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private int recursionDepth;
880fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private int recursionLimit = DEFAULT_RECURSION_LIMIT;
881fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
882fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** See setSizeLimit() */
883fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private int sizeLimit = DEFAULT_SIZE_LIMIT;
884fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
885fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private static final int DEFAULT_RECURSION_LIMIT = 64;
886fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private static final int DEFAULT_SIZE_LIMIT = 64 << 20;  // 64MB
887fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private static final int BUFFER_SIZE = 4096;
888fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
889fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private CodedInputStream(final byte[] buffer, final int off, final int len) {
890fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    this.buffer = buffer;
891fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    bufferSize = off + len;
892fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    bufferPos = off;
893d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    totalBytesRetired = -off;
894fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    input = null;
895a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    bufferIsImmutable = false;
896fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
897fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
898fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private CodedInputStream(final InputStream input) {
899fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    buffer = new byte[BUFFER_SIZE];
900fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    bufferSize = 0;
901fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    bufferPos = 0;
902d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    totalBytesRetired = 0;
903fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    this.input = input;
904a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    bufferIsImmutable = false;
905a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
906a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
907a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private CodedInputStream(final LiteralByteString byteString) {
908a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    buffer = byteString.bytes;
909a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    bufferPos = byteString.getOffsetIntoBytes();
910a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    bufferSize = bufferPos + byteString.size();
911a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    totalBytesRetired = -bufferPos;
912a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    input = null;
913a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    bufferIsImmutable = true;
914a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
915a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
916a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public void enableAliasing(boolean enabled) {
917a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    this.enableAliasing = enabled;
918fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
919fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
920fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
921fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Set the maximum message recursion depth.  In order to prevent malicious
922fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * messages from causing stack overflows, {@code CodedInputStream} limits
923fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * how deeply messages may be nested.  The default limit is 64.
924fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
925fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @return the old limit.
926fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
927fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int setRecursionLimit(final int limit) {
928fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (limit < 0) {
929fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw new IllegalArgumentException(
930fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        "Recursion limit cannot be negative: " + limit);
931fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
932fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    final int oldLimit = recursionLimit;
933fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    recursionLimit = limit;
934fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return oldLimit;
935fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
936fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
937fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
938fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Set the maximum message size.  In order to prevent malicious
939fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * messages from exhausting memory or causing integer overflows,
940fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * {@code CodedInputStream} limits how large a message may be.
941fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * The default limit is 64MB.  You should set this limit as small
942fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * as you can without harming your app's functionality.  Note that
943fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * size limits only apply when reading from an {@code InputStream}, not
944fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * when constructed around a raw byte array (nor with
945fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * {@link ByteString#newCodedInput}).
946fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * <p>
947fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * If you want to read several messages from a single CodedInputStream, you
948fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * could call {@link #resetSizeCounter()} after each one to avoid hitting the
949fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * size limit.
950fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
951fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @return the old limit.
952fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
953fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int setSizeLimit(final int limit) {
954fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (limit < 0) {
955fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw new IllegalArgumentException(
956fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        "Size limit cannot be negative: " + limit);
957fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
958fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    final int oldLimit = sizeLimit;
959fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    sizeLimit = limit;
960fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return oldLimit;
961fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
962fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
963fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
964fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
965fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
966fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public void resetSizeCounter() {
967d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    totalBytesRetired = -bufferPos;
968fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
969fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
970fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
971fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Sets {@code currentLimit} to (current position) + {@code byteLimit}.  This
972fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * is called when descending into a length-delimited embedded message.
973fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
974d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * <p>Note that {@code pushLimit()} does NOT affect how many bytes the
975d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * {@code CodedInputStream} reads from an underlying {@code InputStream} when
976d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * refreshing its buffer.  If you need to prevent reading past a certain
977d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * point in the underlying {@code InputStream} (e.g. because you expect it to
978d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * contain more data after the end of the message which you need to handle
979a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * differently) then you must place a wrapper around your {@code InputStream}
980d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * which limits the amount of data that can be read from it.
981d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   *
982fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @return the old limit.
983fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
984fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
985fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (byteLimit < 0) {
986fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw InvalidProtocolBufferException.negativeSize();
987fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
988fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    byteLimit += totalBytesRetired + bufferPos;
989fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    final int oldLimit = currentLimit;
990fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (byteLimit > oldLimit) {
991fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw InvalidProtocolBufferException.truncatedMessage();
992fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
993fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    currentLimit = byteLimit;
994fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
995fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    recomputeBufferSizeAfterLimit();
996fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
997fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return oldLimit;
998fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
999fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1000fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  private void recomputeBufferSizeAfterLimit() {
1001fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    bufferSize += bufferSizeAfterLimit;
1002fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    final int bufferEnd = totalBytesRetired + bufferSize;
1003fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (bufferEnd > currentLimit) {
1004fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Limit is in current buffer.
1005fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bufferSizeAfterLimit = bufferEnd - currentLimit;
1006fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bufferSize -= bufferSizeAfterLimit;
1007fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    } else {
1008fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bufferSizeAfterLimit = 0;
1009fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1010fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1011fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1012fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
1013fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Discards the current limit, returning to the previous limit.
1014fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
1015fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @param oldLimit The old limit, as returned by {@code pushLimit}.
1016fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
1017fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public void popLimit(final int oldLimit) {
1018fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    currentLimit = oldLimit;
1019fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    recomputeBufferSizeAfterLimit();
1020fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1021fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1022fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
1023fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Returns the number of bytes to be read before the current limit.
1024fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * If no limit is set, returns -1.
1025fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
1026fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public int getBytesUntilLimit() {
1027fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (currentLimit == Integer.MAX_VALUE) {
1028fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return -1;
1029fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1030fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1031fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    final int currentAbsolutePosition = totalBytesRetired + bufferPos;
1032fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return currentLimit - currentAbsolutePosition;
1033fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1034fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1035fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
1036fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Returns true if the stream has reached the end of the input.  This is the
1037fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * case if either the end of the underlying input source has been reached or
1038fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * if the stream has reached a limit created using {@link #pushLimit(int)}.
1039fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
1040fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public boolean isAtEnd() throws IOException {
1041a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return bufferPos == bufferSize && !tryRefillBuffer(1);
1042fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1043d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1044d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  /**
1045d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * The total bytes read up to the current position. Calling
1046d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * {@link #resetSizeCounter()} resets this value to zero.
1047d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   */
1048d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  public int getTotalBytesRead() {
1049d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return totalBytesRetired + bufferPos;
1050d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
1051fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1052a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private interface RefillCallback {
1053a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    void onRefill();
1054a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
1055a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1056a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private RefillCallback refillCallback = null;
1057a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1058a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
1059a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Ensures that at least {@code n} bytes are available in the buffer, reading
1060a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * more bytes from the input if necessary to make it so.  Caller must ensure
1061a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * that the requested space is less than BUFFER_SIZE.
1062a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
1063a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws InvalidProtocolBufferException The end of the stream or the current
1064a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *                                        limit was reached.
1065a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
1066a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private void ensureAvailable(int n) throws IOException {
1067a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (bufferSize - bufferPos < n) {
1068a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      refillBuffer(n);
1069a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
1070a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
1071a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1072a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
1073a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Reads more bytes from the input, making at least {@code n} bytes available
1074a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * in the buffer.  Caller must ensure that the requested space is not yet
1075a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * available, and that the requested space is less than BUFFER_SIZE.
1076a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
1077a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws InvalidProtocolBufferException The end of the stream or the current
1078a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *                                        limit was reached.
1079a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
1080a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private void refillBuffer(int n) throws IOException {
1081a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (!tryRefillBuffer(n)) {
1082a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throw InvalidProtocolBufferException.truncatedMessage();
1083a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
1084a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
1085a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1086fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
1087a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Tries to read more bytes from the input, making at least {@code n} bytes
1088a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * available in the buffer.  Caller must ensure that the requested space is
1089a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * not yet available, and that the requested space is less than BUFFER_SIZE.
1090a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
1091a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return {@code true} if the bytes could be made available; {@code false}
1092a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *         if the end of the stream or the current limit was reached.
1093fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
1094a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private boolean tryRefillBuffer(int n) throws IOException {
1095a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (bufferPos + n <= bufferSize) {
1096fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw new IllegalStateException(
1097a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          "refillBuffer() called when " + n +
1098a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          " bytes were already available in buffer");
1099fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1101a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (totalBytesRetired + bufferPos + n > currentLimit) {
1102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Oops, we hit a limit.
1103a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return false;
1104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1106a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (refillCallback != null) {
1107a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      refillCallback.onRefill();
1108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1109a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1110a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (input != null) {
1111a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int pos = bufferPos;
1112a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (pos > 0) {
1113a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        if (bufferSize > pos) {
1114a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          System.arraycopy(buffer, pos, buffer, 0, bufferSize - pos);
1115a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        }
1116a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        totalBytesRetired += pos;
1117a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        bufferSize -= pos;
1118a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        bufferPos = 0;
1119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
1120a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1121a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int bytesRead = input.read(buffer, bufferSize, buffer.length - bufferSize);
1122a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
1123a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        throw new IllegalStateException(
1124a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            "InputStream#read(byte[]) returned invalid result: " + bytesRead +
1125a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            "\nThe InputStream implementation is buggy.");
1126a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
1127a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (bytesRead > 0) {
1128a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        bufferSize += bytesRead;
1129a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // Integer-overflow-conscious check against sizeLimit
1130a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        if (totalBytesRetired + n - sizeLimit > 0) {
1131a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          throw InvalidProtocolBufferException.sizeLimitExceeded();
1132a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        }
1133a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        recomputeBufferSizeAfterLimit();
1134a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return (bufferSize >= n) ? true : tryRefillBuffer(n);
1135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
1136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1137a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1138a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return false;
1139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
1142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Read one byte from the input.
1143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
1144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @throws InvalidProtocolBufferException The end of the stream or the current
1145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *                                        limit was reached.
1146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
1147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public byte readRawByte() throws IOException {
1148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (bufferPos == bufferSize) {
1149a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      refillBuffer(1);
1150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return buffer[bufferPos++];
1152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
1155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Read a fixed size of bytes from the input.
1156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
1157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @throws InvalidProtocolBufferException The end of the stream or the current
1158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *                                        limit was reached.
1159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
1160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public byte[] readRawBytes(final int size) throws IOException {
1161a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    final int pos = bufferPos;
1162a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (size <= (bufferSize - pos) && size > 0) {
1163a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos = pos + size;
1164a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return Arrays.copyOfRange(buffer, pos, pos + size);
1165a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
1166a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return readRawBytesSlowPath(size);
1167a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
1168a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
1169a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1170a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
1171a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Exactly like readRawBytes, but caller must have already checked the fast
1172a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * path: (size <= (bufferSize - pos) && size > 0)
1173a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
1174a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private byte[] readRawBytesSlowPath(final int size) throws IOException {
1175a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (size <= 0) {
1176a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (size == 0) {
1177a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return Internal.EMPTY_BYTE_ARRAY;
1178a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else {
1179a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        throw InvalidProtocolBufferException.negativeSize();
1180a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
1181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (totalBytesRetired + bufferPos + size > currentLimit) {
1184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Read to the end of the stream anyway.
1185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
1186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Then fail.
1187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw InvalidProtocolBufferException.truncatedMessage();
1188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1190a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (size < BUFFER_SIZE) {
1191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Reading more bytes than are in the buffer, but not an excessive number
1192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // of bytes.  We can safely allocate the resulting array ahead of time.
1193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // First copy what we have.
1195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      final byte[] bytes = new byte[size];
1196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      int pos = bufferSize - bufferPos;
1197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      System.arraycopy(buffer, bufferPos, bytes, 0, pos);
1198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bufferPos = bufferSize;
1199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1200a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // We want to refill the buffer and then copy from the buffer into our
1201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // byte array rather than reading directly into our byte array because
1202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // the input may be unbuffered.
1203a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      ensureAvailable(size - pos);
1204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      System.arraycopy(buffer, 0, bytes, pos, size - pos);
1205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bufferPos = size - pos;
1206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return bytes;
1208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    } else {
1209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // The size is very large.  For security reasons, we can't allocate the
1210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // entire byte array yet.  The size comes directly from the input, so a
1211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // maliciously-crafted message could provide a bogus very large size in
1212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // order to trick the app into allocating a lot of memory.  We avoid this
1213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // by allocating and reading only a small chunk at a time, so that the
1214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // malicious message must actually *be* extremely large to cause
1215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // problems.  Meanwhile, we limit the allowed size of a message elsewhere.
1216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Remember the buffer markers since we'll have to copy the bytes out of
1218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // it later.
1219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      final int originalBufferPos = bufferPos;
1220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      final int originalBufferSize = bufferSize;
1221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Mark the current buffer consumed.
1223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      totalBytesRetired += bufferSize;
1224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bufferPos = 0;
1225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bufferSize = 0;
1226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Read all the rest of the bytes we need.
1228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      int sizeLeft = size - (originalBufferSize - originalBufferPos);
1229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      final List<byte[]> chunks = new ArrayList<byte[]>();
1230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      while (sizeLeft > 0) {
1232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
1233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        int pos = 0;
1234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        while (pos < chunk.length) {
1235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          final int n = (input == null) ? -1 :
1236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville            input.read(chunk, pos, chunk.length - pos);
1237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          if (n == -1) {
1238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville            throw InvalidProtocolBufferException.truncatedMessage();
1239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          }
1240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          totalBytesRetired += n;
1241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          pos += n;
1242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        }
1243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        sizeLeft -= chunk.length;
1244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        chunks.add(chunk);
1245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
1246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // OK, got everything.  Now concatenate it all into one buffer.
1248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      final byte[] bytes = new byte[size];
1249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Start by copying the leftover bytes from this.buffer.
1251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      int pos = originalBufferSize - originalBufferPos;
1252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
1253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // And now all the chunks.
1255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      for (final byte[] chunk : chunks) {
1256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        System.arraycopy(chunk, 0, bytes, pos, chunk.length);
1257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        pos += chunk.length;
1258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
1259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Done.
1261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return bytes;
1262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
1266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Reads and discards {@code size} bytes.
1267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
1268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @throws InvalidProtocolBufferException The end of the stream or the current
1269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *                                        limit was reached.
1270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
1271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public void skipRawBytes(final int size) throws IOException {
1272a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (size <= (bufferSize - bufferPos) && size >= 0) {
1273a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // We have all the bytes we need already.
1274a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos += size;
1275a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
1276a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      skipRawBytesSlowPath(size);
1277a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
1278a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
1279a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1280a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
1281a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Exactly like skipRawBytes, but caller must have already checked the fast
1282a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * path: (size <= (bufferSize - pos) && size >= 0)
1283a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
1284a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private void skipRawBytesSlowPath(final int size) throws IOException {
1285fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (size < 0) {
1286fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw InvalidProtocolBufferException.negativeSize();
1287fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1288fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1289fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (totalBytesRetired + bufferPos + size > currentLimit) {
1290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Read to the end of the stream anyway.
1291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
1292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Then fail.
1293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throw InvalidProtocolBufferException.truncatedMessage();
1294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1296a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // Skipping more bytes than are in the buffer.  First skip what we have.
1297a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    int pos = bufferSize - bufferPos;
1298a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    bufferPos = bufferSize;
1299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1300a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // Keep refilling the buffer until we get to the point we wanted to skip to.
1301a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // This has the side effect of ensuring the limits are updated correctly.
1302a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    refillBuffer(1);
1303a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    while (size - pos > bufferSize) {
1304a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      pos += bufferSize;
1305a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos = bufferSize;
1306a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      refillBuffer(1);
1307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1308a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1309a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    bufferPos = size - pos;
1310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1312