1e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Protocol Buffers - Google's data interchange format
2e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Copyright 2008 Google Inc.  All rights reserved.
3e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// http://code.google.com/p/protobuf/
4e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//
5e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Redistribution and use in source and binary forms, with or without
6e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// modification, are permitted provided that the following conditions are
7e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// met:
8e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//
9e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//     * Redistributions of source code must retain the above copyright
10e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// notice, this list of conditions and the following disclaimer.
11e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//     * Redistributions in binary form must reproduce the above
12e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// copyright notice, this list of conditions and the following disclaimer
13e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// in the documentation and/or other materials provided with the
14e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// distribution.
15e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//     * Neither the name of Google Inc. nor the names of its
16e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// contributors may be used to endorse or promote products derived from
17e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// this software without specific prior written permission.
18e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//
19e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
31e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillepackage com.google.protobuf.micro;
32e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
33e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleimport java.io.IOException;
34e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleimport java.io.InputStream;
35e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
36e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville/**
37e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville * Reads and decodes protocol message fields.
38e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville *
39e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville * This class contains two kinds of methods:  methods that read specific
40e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville * protocol message constructs and field types (e.g. {@link #readTag()} and
41e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville * {@link #readInt32()}) and methods that read low-level values (e.g.
42e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville * {@link #readRawVarint32()} and {@link #readRawBytes}).  If you are reading
43e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville * encoded protocol messages, you should use the former methods, but if you are
44e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville * reading some other format of your own design, use the latter.
45e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville *
46e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville * @author kenton@google.com Kenton Varda
47e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville */
48e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillepublic final class CodedInputStreamMicro {
49e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
50e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Create a new CodedInputStream wrapping the given InputStream.
51e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
52e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public static CodedInputStreamMicro newInstance(final InputStream input) {
53e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return new CodedInputStreamMicro(input);
54e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
55e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
56e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
57e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Create a new CodedInputStream wrapping the given byte array.
58e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
59e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public static CodedInputStreamMicro newInstance(final byte[] buf) {
60e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return newInstance(buf, 0, buf.length);
61e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
62e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
63e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
64e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Create a new CodedInputStream wrapping the given byte array slice.
65e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
66e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public static CodedInputStreamMicro newInstance(final byte[] buf, final int off,
67e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville                                             final int len) {
68e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return new CodedInputStreamMicro(buf, off, len);
69e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
70e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
71e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // -----------------------------------------------------------------
72e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
73e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
74e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Attempt to read a field tag, returning zero if we have reached EOF.
75e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Protocol message parsers use this to read tags, since a protocol message
76e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * may legally end wherever a tag occurs, and zero is not a valid tag number.
77e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
78e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int readTag() throws IOException {
79e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (isAtEnd()) {
80e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      lastTag = 0;
81e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return 0;
82e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
83e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
84e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    lastTag = readRawVarint32();
85e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (lastTag == 0) {
86e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // If we actually read zero, that's not a valid tag.
87e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw InvalidProtocolBufferMicroException.invalidTag();
88e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
89e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return lastTag;
90e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
91e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
92e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
93e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Verifies that the last call to readTag() returned the given tag value.
94e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * This is used to verify that a nested group ended with the correct
95e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * end tag.
96e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
97e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @throws InvalidProtocolBufferMicroException {@code value} does not match the
98e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *                                        last tag.
99e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
100e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public void checkLastTagWas(final int value)
101e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville                              throws InvalidProtocolBufferMicroException {
102e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (lastTag != value) {
103e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw InvalidProtocolBufferMicroException.invalidEndTag();
104e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
105e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
106e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
107e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
108e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Reads and discards a single field, given its tag value.
109e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
110e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @return {@code false} if the tag is an endgroup tag, in which case
111e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *         nothing is skipped.  Otherwise, returns {@code true}.
112e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
113e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public boolean skipField(final int tag) throws IOException {
114e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    switch (WireFormatMicro.getTagWireType(tag)) {
115e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      case WireFormatMicro.WIRETYPE_VARINT:
116e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        readInt32();
117e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return true;
118e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      case WireFormatMicro.WIRETYPE_FIXED64:
119e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        readRawLittleEndian64();
120e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return true;
121e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      case WireFormatMicro.WIRETYPE_LENGTH_DELIMITED:
122e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        skipRawBytes(readRawVarint32());
123e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return true;
124e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      case WireFormatMicro.WIRETYPE_START_GROUP:
125e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        skipMessage();
126e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        checkLastTagWas(
127e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          WireFormatMicro.makeTag(WireFormatMicro.getTagFieldNumber(tag),
128e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville                             WireFormatMicro.WIRETYPE_END_GROUP));
129e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return true;
130e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      case WireFormatMicro.WIRETYPE_END_GROUP:
131e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return false;
132e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      case WireFormatMicro.WIRETYPE_FIXED32:
133e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        readRawLittleEndian32();
134e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return true;
135e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      default:
136e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        throw InvalidProtocolBufferMicroException.invalidWireType();
137e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
138e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
139e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
140e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
141e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Reads and discards an entire message.  This will read either until EOF
142e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * or until an endgroup tag, whichever comes first.
143e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
144e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public void skipMessage() throws IOException {
145e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    while (true) {
146e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final int tag = readTag();
147e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (tag == 0 || !skipField(tag)) {
148e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return;
149e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
150e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
151e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
152e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
153e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // -----------------------------------------------------------------
154e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
155e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a {@code double} field value from the stream. */
156e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public double readDouble() throws IOException {
157e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return Double.longBitsToDouble(readRawLittleEndian64());
158e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
159e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
160e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a {@code float} field value from the stream. */
161e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public float readFloat() throws IOException {
162e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return Float.intBitsToFloat(readRawLittleEndian32());
163e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
164e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
165e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a {@code uint64} field value from the stream. */
166e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public long readUInt64() throws IOException {
167e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return readRawVarint64();
168e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
169e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
170e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read an {@code int64} field value from the stream. */
171e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public long readInt64() throws IOException {
172e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return readRawVarint64();
173e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
174e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
175e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read an {@code int32} field value from the stream. */
176e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int readInt32() throws IOException {
177e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return readRawVarint32();
178e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
179e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
180e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a {@code fixed64} field value from the stream. */
181e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public long readFixed64() throws IOException {
182e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return readRawLittleEndian64();
183e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
184e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
185e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a {@code fixed32} field value from the stream. */
186e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int readFixed32() throws IOException {
187e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return readRawLittleEndian32();
188e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
189e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
190e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a {@code bool} field value from the stream. */
191e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public boolean readBool() throws IOException {
192e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return readRawVarint32() != 0;
193e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
194e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
195e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a {@code string} field value from the stream. */
196e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public String readString() throws IOException {
197e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final int size = readRawVarint32();
198e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (size <= (bufferSize - bufferPos) && size > 0) {
199e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Fast path:  We already have the bytes in a contiguous buffer, so
200e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      //   just copy directly from it.
201e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final String result = new String(buffer, bufferPos, size, "UTF-8");
202e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferPos += size;
203e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return result;
204e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
205e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Slow path:  Build a byte array first then copy it.
206e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return new String(readRawBytes(size), "UTF-8");
207e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
208e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
209e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
210e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a {@code group} field value from the stream. */
211e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public void readGroup(final MessageMicro msg, final int fieldNumber)
212e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throws IOException {
213e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (recursionDepth >= recursionLimit) {
214e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw InvalidProtocolBufferMicroException.recursionLimitExceeded();
215e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
216e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    ++recursionDepth;
217e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    msg.mergeFrom(this);
218e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    checkLastTagWas(
219e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      WireFormatMicro.makeTag(fieldNumber, WireFormatMicro.WIRETYPE_END_GROUP));
220e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    --recursionDepth;
221e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
222e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
223e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public void readMessage(final MessageMicro msg)
224e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throws IOException {
225e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final int length = readRawVarint32();
226e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (recursionDepth >= recursionLimit) {
227e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw InvalidProtocolBufferMicroException.recursionLimitExceeded();
228e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
229e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final int oldLimit = pushLimit(length);
230e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    ++recursionDepth;
231e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    msg.mergeFrom(this);
232e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    checkLastTagWas(0);
233e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    --recursionDepth;
234e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    popLimit(oldLimit);
235e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
236e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
237e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a {@code bytes} field value from the stream. */
238e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public ByteStringMicro readBytes() throws IOException {
239e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final int size = readRawVarint32();
240e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (size <= (bufferSize - bufferPos) && size > 0) {
241e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Fast path:  We already have the bytes in a contiguous buffer, so
242e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      //   just copy directly from it.
243e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final ByteStringMicro result = ByteStringMicro.copyFrom(buffer, bufferPos, size);
244e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferPos += size;
245e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return result;
2464d8b123b8985b3f87a640be2d9a1b4b730b5fdcaAndre Eisenbach    } else if (size == 0) {
2474d8b123b8985b3f87a640be2d9a1b4b730b5fdcaAndre Eisenbach      return ByteStringMicro.EMPTY;
248e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
249e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Slow path:  Build a byte array first then copy it.
250e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return ByteStringMicro.copyFrom(readRawBytes(size));
251e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
252e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
253e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
254e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a {@code uint32} field value from the stream. */
255e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int readUInt32() throws IOException {
256e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return readRawVarint32();
257e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
258e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
259e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
260e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Read an enum field value from the stream.  Caller is responsible
261e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * for converting the numeric value to an actual enum.
262e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
263e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int readEnum() throws IOException {
264e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return readRawVarint32();
265e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
266e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
267e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read an {@code sfixed32} field value from the stream. */
268e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int readSFixed32() throws IOException {
269e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return readRawLittleEndian32();
270e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
271e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
272e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read an {@code sfixed64} field value from the stream. */
273e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public long readSFixed64() throws IOException {
274e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return readRawLittleEndian64();
275e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
276e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
277e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read an {@code sint32} field value from the stream. */
278e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int readSInt32() throws IOException {
279e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return decodeZigZag32(readRawVarint32());
280e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
281e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
282e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read an {@code sint64} field value from the stream. */
283e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public long readSInt64() throws IOException {
284e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return decodeZigZag64(readRawVarint64());
285e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
286e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
287e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // =================================================================
288e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
289e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
290e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Read a raw Varint from the stream.  If larger than 32 bits, discard the
291e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * upper bits.
292e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
293e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int readRawVarint32() throws IOException {
294e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    byte tmp = readRawByte();
295e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (tmp >= 0) {
296e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return tmp;
297e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
298e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    int result = tmp & 0x7f;
299e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if ((tmp = readRawByte()) >= 0) {
300e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      result |= tmp << 7;
301e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
302e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      result |= (tmp & 0x7f) << 7;
303e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if ((tmp = readRawByte()) >= 0) {
304e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        result |= tmp << 14;
305e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      } else {
306e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        result |= (tmp & 0x7f) << 14;
307e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        if ((tmp = readRawByte()) >= 0) {
308e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          result |= tmp << 21;
309e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        } else {
310e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          result |= (tmp & 0x7f) << 21;
311e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          result |= (tmp = readRawByte()) << 28;
312e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          if (tmp < 0) {
313e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            // Discard upper 32 bits.
314e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            for (int i = 0; i < 5; i++) {
315e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville              if (readRawByte() >= 0) {
316e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville                return result;
317e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville              }
318e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            }
319e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            throw InvalidProtocolBufferMicroException.malformedVarint();
320e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          }
321e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        }
322e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
323e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
324e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return result;
325e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
326e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
327e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
328e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Reads a varint from the input one byte at a time, so that it does not
329e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * read any bytes after the end of the varint.  If you simply wrapped the
330e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)}
331e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * then you would probably end up reading past the end of the varint since
332e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * CodedInputStream buffers its input.
333e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
334e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  static int readRawVarint32(final InputStream input) throws IOException {
335e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    int result = 0;
336e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    int offset = 0;
337e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    for (; offset < 32; offset += 7) {
338e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final int b = input.read();
339e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (b == -1) {
340e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        throw InvalidProtocolBufferMicroException.truncatedMessage();
341e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
342e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      result |= (b & 0x7f) << offset;
343e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if ((b & 0x80) == 0) {
344e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return result;
345e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
346e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
347e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // Keep reading up to 64 bits.
348e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    for (; offset < 64; offset += 7) {
349e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final int b = input.read();
350e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (b == -1) {
351e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        throw InvalidProtocolBufferMicroException.truncatedMessage();
352e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
353e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if ((b & 0x80) == 0) {
354e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return result;
355e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
356e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
357e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    throw InvalidProtocolBufferMicroException.malformedVarint();
358e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
359e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
360e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a raw Varint from the stream. */
361e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public long readRawVarint64() throws IOException {
362e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    int shift = 0;
363e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    long result = 0;
364e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    while (shift < 64) {
365e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final byte b = readRawByte();
366e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      result |= (long)(b & 0x7F) << shift;
367e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if ((b & 0x80) == 0) {
368e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return result;
369e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
370e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      shift += 7;
371e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
372e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    throw InvalidProtocolBufferMicroException.malformedVarint();
373e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
374e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
375e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a 32-bit little-endian integer from the stream. */
376e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int readRawLittleEndian32() throws IOException {
377e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b1 = readRawByte();
378e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b2 = readRawByte();
379e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b3 = readRawByte();
380e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b4 = readRawByte();
381e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return ((b1 & 0xff)      ) |
382e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville           ((b2 & 0xff) <<  8) |
383e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville           ((b3 & 0xff) << 16) |
384e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville           ((b4 & 0xff) << 24);
385e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
386e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
387e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** Read a 64-bit little-endian integer from the stream. */
388e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public long readRawLittleEndian64() throws IOException {
389e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b1 = readRawByte();
390e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b2 = readRawByte();
391e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b3 = readRawByte();
392e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b4 = readRawByte();
393e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b5 = readRawByte();
394e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b6 = readRawByte();
395e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b7 = readRawByte();
396e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final byte b8 = readRawByte();
397e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return (((long)b1 & 0xff)      ) |
398e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville           (((long)b2 & 0xff) <<  8) |
399e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville           (((long)b3 & 0xff) << 16) |
400e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville           (((long)b4 & 0xff) << 24) |
401e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville           (((long)b5 & 0xff) << 32) |
402e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville           (((long)b6 & 0xff) << 40) |
403e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville           (((long)b7 & 0xff) << 48) |
404e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville           (((long)b8 & 0xff) << 56);
405e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
406e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
407e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
408e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Decode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
409e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * into values that can be efficiently encoded with varint.  (Otherwise,
410e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * negative values must be sign-extended to 64 bits to be varint encoded,
411e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * thus always taking 10 bytes on the wire.)
412e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
413e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @param n An unsigned 32-bit integer, stored in a signed int because
414e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *          Java has no explicit unsigned support.
415e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @return A signed 32-bit integer.
416e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
417e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public static int decodeZigZag32(final int n) {
418e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return (n >>> 1) ^ -(n & 1);
419e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
420e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
421e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
422e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Decode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
423e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * into values that can be efficiently encoded with varint.  (Otherwise,
424e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * negative values must be sign-extended to 64 bits to be varint encoded,
425e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * thus always taking 10 bytes on the wire.)
426e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
427e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @param n An unsigned 64-bit integer, stored in a signed int because
428e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *          Java has no explicit unsigned support.
429e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @return A signed 64-bit integer.
430e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
431e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public static long decodeZigZag64(final long n) {
432e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return (n >>> 1) ^ -(n & 1);
433e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
434e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
435e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // -----------------------------------------------------------------
436e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
437e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private final byte[] buffer;
438e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private int bufferSize;
439e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private int bufferSizeAfterLimit;
440e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private int bufferPos;
441e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private final InputStream input;
442e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private int lastTag;
443e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
444e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
445e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * The total number of bytes read before the current buffer.  The total
446e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * bytes read up to the current position can be computed as
447e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * {@code totalBytesRetired + bufferPos}.
448e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
449e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private int totalBytesRetired;
450e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
451e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** The absolute position of the end of the current message. */
452e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private int currentLimit = Integer.MAX_VALUE;
453e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
454e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** See setRecursionLimit() */
455e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private int recursionDepth;
456e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private int recursionLimit = DEFAULT_RECURSION_LIMIT;
457e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
458e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /** See setSizeLimit() */
459e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private int sizeLimit = DEFAULT_SIZE_LIMIT;
460e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
461e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private static final int DEFAULT_RECURSION_LIMIT = 64;
462e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private static final int DEFAULT_SIZE_LIMIT = 64 << 20;  // 64MB
463e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private static final int BUFFER_SIZE = 4096;
464e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
465e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private CodedInputStreamMicro(final byte[] buffer, final int off, final int len) {
466e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    this.buffer = buffer;
467e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    bufferSize = off + len;
468e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    bufferPos = off;
469e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    input = null;
470e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
471e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
472e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private CodedInputStreamMicro(final InputStream input) {
473e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    buffer = new byte[BUFFER_SIZE];
474e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    bufferSize = 0;
475e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    bufferPos = 0;
476e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    this.input = input;
477e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
478e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
479e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
480e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Set the maximum message recursion depth.  In order to prevent malicious
481e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * messages from causing stack overflows, {@code CodedInputStream} limits
482e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * how deeply messages may be nested.  The default limit is 64.
483e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
484e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @return the old limit.
485e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
486e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int setRecursionLimit(final int limit) {
487e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (limit < 0) {
488e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw new IllegalArgumentException(
489e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        "Recursion limit cannot be negative: " + limit);
490e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
491e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final int oldLimit = recursionLimit;
492e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    recursionLimit = limit;
493e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return oldLimit;
494e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
495e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
496e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
497e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Set the maximum message size.  In order to prevent malicious
498e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * messages from exhausting memory or causing integer overflows,
499e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * {@code CodedInputStream} limits how large a message may be.
500e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * The default limit is 64MB.  You should set this limit as small
501e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * as you can without harming your app's functionality.  Note that
502e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * size limits only apply when reading from an {@code InputStream}, not
503e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * when constructed around a raw byte array (nor with
504e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * {@link ByteStringMicro#newCodedInput}).
505e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * <p>
506e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * If you want to read several messages from a single CodedInputStream, you
507e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * could call {@link #resetSizeCounter()} after each one to avoid hitting the
508e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * size limit.
509e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
510e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @return the old limit.
511e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
512e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int setSizeLimit(final int limit) {
513e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (limit < 0) {
514e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw new IllegalArgumentException(
515e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        "Size limit cannot be negative: " + limit);
516e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
517e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final int oldLimit = sizeLimit;
518e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    sizeLimit = limit;
519e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return oldLimit;
520e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
521e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
522e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
523e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
524e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
525e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public void resetSizeCounter() {
526e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    totalBytesRetired = 0;
527e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
528e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
529e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
530e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Sets {@code currentLimit} to (current position) + {@code byteLimit}.  This
531e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * is called when descending into a length-delimited embedded message.
532e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
533e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @return the old limit.
534e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
535e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int pushLimit(int byteLimit) throws InvalidProtocolBufferMicroException {
536e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (byteLimit < 0) {
537e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw InvalidProtocolBufferMicroException.negativeSize();
538e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
539e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    byteLimit += totalBytesRetired + bufferPos;
540e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final int oldLimit = currentLimit;
541e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (byteLimit > oldLimit) {
542e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw InvalidProtocolBufferMicroException.truncatedMessage();
543e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
544e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    currentLimit = byteLimit;
545e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
546e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    recomputeBufferSizeAfterLimit();
547e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
548e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return oldLimit;
549e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
550e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
551e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private void recomputeBufferSizeAfterLimit() {
552e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    bufferSize += bufferSizeAfterLimit;
553e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final int bufferEnd = totalBytesRetired + bufferSize;
554e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (bufferEnd > currentLimit) {
555e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Limit is in current buffer.
556e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferSizeAfterLimit = bufferEnd - currentLimit;
557e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferSize -= bufferSizeAfterLimit;
558e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
559e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferSizeAfterLimit = 0;
560e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
561e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
562e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
563e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
564e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Discards the current limit, returning to the previous limit.
565e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
566e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @param oldLimit The old limit, as returned by {@code pushLimit}.
567e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
568e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public void popLimit(final int oldLimit) {
569e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    currentLimit = oldLimit;
570e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    recomputeBufferSizeAfterLimit();
571e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
572e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
573e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
574e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Returns the number of bytes to be read before the current limit.
575e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * If no limit is set, returns -1.
576e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
577e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public int getBytesUntilLimit() {
578e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (currentLimit == Integer.MAX_VALUE) {
579e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return -1;
580e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
581e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
582e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    final int currentAbsolutePosition = totalBytesRetired + bufferPos;
583e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return currentLimit - currentAbsolutePosition;
584e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
585e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
586e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
587e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Returns true if the stream has reached the end of the input.  This is the
588e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * case if either the end of the underlying input source has been reached or
589e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * if the stream has reached a limit created using {@link #pushLimit(int)}.
590e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
591e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public boolean isAtEnd() throws IOException {
592e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return bufferPos == bufferSize && !refillBuffer(false);
593e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
594e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
595e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
596e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Called with {@code this.buffer} is empty to read more bytes from the
597e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * input.  If {@code mustSucceed} is true, refillBuffer() gurantees that
598e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * either there will be at least one byte in the buffer when it returns
599e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * or it will throw an exception.  If {@code mustSucceed} is false,
600e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * refillBuffer() returns false if no more bytes were available.
601e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
602e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  private boolean refillBuffer(final boolean mustSucceed) throws IOException {
603e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (bufferPos < bufferSize) {
604e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw new IllegalStateException(
605e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        "refillBuffer() called when buffer wasn't empty.");
606e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
607e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
608e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (totalBytesRetired + bufferSize == currentLimit) {
609e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Oops, we hit a limit.
610e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (mustSucceed) {
611e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        throw InvalidProtocolBufferMicroException.truncatedMessage();
612e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      } else {
613e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return false;
614e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
615e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
616e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
617e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    totalBytesRetired += bufferSize;
618e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
619e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    bufferPos = 0;
620e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    bufferSize = (input == null) ? -1 : input.read(buffer);
621e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (bufferSize == 0 || bufferSize < -1) {
622e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw new IllegalStateException(
623e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          "InputStream#read(byte[]) returned invalid result: " + bufferSize +
624e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          "\nThe InputStream implementation is buggy.");
625e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
626e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (bufferSize == -1) {
627e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferSize = 0;
628e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (mustSucceed) {
629e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        throw InvalidProtocolBufferMicroException.truncatedMessage();
630e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      } else {
631e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        return false;
632e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
633e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
634e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      recomputeBufferSizeAfterLimit();
635e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final int totalBytesRead =
636e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        totalBytesRetired + bufferSize + bufferSizeAfterLimit;
637e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
638e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        throw InvalidProtocolBufferMicroException.sizeLimitExceeded();
639e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
640e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return true;
641e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
642e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
643e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
644e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
645e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Read one byte from the input.
646e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
647e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @throws InvalidProtocolBufferMicroException The end of the stream or the current
648e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *                                        limit was reached.
649e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
650e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public byte readRawByte() throws IOException {
651e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (bufferPos == bufferSize) {
652e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      refillBuffer(true);
653e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
654e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return buffer[bufferPos++];
655e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
656e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
657e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
658e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Read a fixed size of bytes from the input.
659e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
660e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @throws InvalidProtocolBufferMicroException The end of the stream or the current
661e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *                                        limit was reached.
662e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
663e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public byte[] readRawBytes(final int size) throws IOException {
664e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (size < 0) {
665e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw InvalidProtocolBufferMicroException.negativeSize();
666e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
667e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
668e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (totalBytesRetired + bufferPos + size > currentLimit) {
669e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Read to the end of the stream anyway.
670e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
671e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Then fail.
672e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw InvalidProtocolBufferMicroException.truncatedMessage();
673e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
674e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
675e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (size <= bufferSize - bufferPos) {
676e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // We have all the bytes we need already.
677e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final byte[] bytes = new byte[size];
678e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      System.arraycopy(buffer, bufferPos, bytes, 0, size);
679e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferPos += size;
680e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return bytes;
681e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else if (size < BUFFER_SIZE) {
682e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Reading more bytes than are in the buffer, but not an excessive number
683e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // of bytes.  We can safely allocate the resulting array ahead of time.
684e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
685e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // First copy what we have.
686e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final byte[] bytes = new byte[size];
687e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      int pos = bufferSize - bufferPos;
688e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      System.arraycopy(buffer, bufferPos, bytes, 0, pos);
689e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferPos = bufferSize;
690e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
691e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // We want to use refillBuffer() and then copy from the buffer into our
692e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // byte array rather than reading directly into our byte array because
693e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // the input may be unbuffered.
694e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      refillBuffer(true);
695e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
696e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      while (size - pos > bufferSize) {
697e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        System.arraycopy(buffer, 0, bytes, pos, bufferSize);
698e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        pos += bufferSize;
699e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        bufferPos = bufferSize;
700e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        refillBuffer(true);
701e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
702e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
703e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      System.arraycopy(buffer, 0, bytes, pos, size - pos);
704e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferPos = size - pos;
705e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
706e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return bytes;
707e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
708e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // The size is very large.  For security reasons, we can't allocate the
709e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // entire byte array yet.  The size comes directly from the input, so a
710e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // maliciously-crafted message could provide a bogus very large size in
711e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // order to trick the app into allocating a lot of memory.  We avoid this
712e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // by allocating and reading only a small chunk at a time, so that the
713e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // malicious message must actually *be* extremely large to cause
714e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // problems.  Meanwhile, we limit the allowed size of a message elsewhere.
715e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
716e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Remember the buffer markers since we'll have to copy the bytes out of
717e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // it later.
718e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final int originalBufferPos = bufferPos;
719e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final int originalBufferSize = bufferSize;
720e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
721e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Mark the current buffer consumed.
722e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      totalBytesRetired += bufferSize;
723e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferPos = 0;
724e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferSize = 0;
725e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
726e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Read all the rest of the bytes we need.
727e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      int sizeLeft = size - (originalBufferSize - originalBufferPos);
728e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
729e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // For compatibility with Java 1.3 use Vector
730e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final java.util.Vector chunks = new java.util.Vector();
731e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
732e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      while (sizeLeft > 0) {
733e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
734e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        int pos = 0;
735e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        while (pos < chunk.length) {
736e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          final int n = (input == null) ? -1 :
737e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            input.read(chunk, pos, chunk.length - pos);
738e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          if (n == -1) {
739e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            throw InvalidProtocolBufferMicroException.truncatedMessage();
740e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          }
741e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          totalBytesRetired += n;
742e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          pos += n;
743e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        }
744e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        sizeLeft -= chunk.length;
745e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        chunks.addElement(chunk);
746e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
747e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
748e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // OK, got everything.  Now concatenate it all into one buffer.
749e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      final byte[] bytes = new byte[size];
750e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
751e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Start by copying the leftover bytes from this.buffer.
752e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      int pos = originalBufferSize - originalBufferPos;
753e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
754e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
755e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // And now all the chunks.
756e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      for (int i = 0; i < chunks.size(); i++) {
757e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        byte [] chunk = (byte [])chunks.elementAt(i);
758e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        System.arraycopy(chunk, 0, bytes, pos, chunk.length);
759e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        pos += chunk.length;
760e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
761e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
762e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Done.
763e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return bytes;
764e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
765e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
766e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
767e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  /**
768e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * Reads and discards {@code size} bytes.
769e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *
770e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   * @throws InvalidProtocolBufferMicroException The end of the stream or the current
771e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   *                                        limit was reached.
772e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville   */
773e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  public void skipRawBytes(final int size) throws IOException {
774e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (size < 0) {
775e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw InvalidProtocolBufferMicroException.negativeSize();
776e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
777e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
778e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (totalBytesRetired + bufferPos + size > currentLimit) {
779e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Read to the end of the stream anyway.
780e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
781e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Then fail.
782e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      throw InvalidProtocolBufferMicroException.truncatedMessage();
783e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
784e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
785e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (size <= bufferSize - bufferPos) {
786e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // We have all the bytes we need already.
787e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferPos += size;
788e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
789e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Skipping more bytes than are in the buffer.  First skip what we have.
790e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      int pos = bufferSize - bufferPos;
7918a2f7578bb6289415f1d0a01c9cc96d283730480Wink Saville      totalBytesRetired += bufferSize;
792e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferPos = 0;
793e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      bufferSize = 0;
794e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
795e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Then skip directly from the InputStream for the rest.
796e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      while (pos < size) {
797e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        final int n = (input == null) ? -1 : (int) input.skip(size - pos);
798e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        if (n <= 0) {
799e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          throw InvalidProtocolBufferMicroException.truncatedMessage();
800e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        }
801e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        pos += n;
802e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        totalBytesRetired += n;
803e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
804e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
805e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
806e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
807