1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 package com.google.protobuf;
33 import static com.google.protobuf.Internal.EMPTY_BYTE_ARRAY;
34 import static com.google.protobuf.Internal.EMPTY_BYTE_BUFFER;
35 import static com.google.protobuf.Internal.UTF_8;
36 import static com.google.protobuf.Internal.checkNotNull;
37 import static com.google.protobuf.WireFormat.FIXED32_SIZE;
38 import static com.google.protobuf.WireFormat.FIXED64_SIZE;
39 import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
41 import java.io.ByteArrayOutputStream;
42 import java.io.IOException;
43 import java.io.InputStream;
44 import java.nio.ByteBuffer;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Iterator;
48 import java.util.List;
51 * Reads and decodes protocol message fields.
53 * <p>This class contains two kinds of methods: methods that read specific protocol message
54 * constructs and field types (e.g. {@link #readTag()} and {@link #readInt32()}) and methods that
55 * read low-level values (e.g. {@link #readRawVarint32()} and {@link #readRawBytes}). If you are
56 * reading encoded protocol messages, you should use the former methods, but if you are reading some
57 * other format of your own design, use the latter.
59 * @author kenton@google.com Kenton Varda
61 public abstract class CodedInputStream {
62 private static final int DEFAULT_BUFFER_SIZE = 4096;
63 private static final int DEFAULT_RECURSION_LIMIT = 100;
64 // Integer.MAX_VALUE == 0x7FFFFFF == INT_MAX from limits.h
65 private static final int DEFAULT_SIZE_LIMIT = Integer.MAX_VALUE;
67 /** Visible for subclasses. See setRecursionLimit() */
70 int recursionLimit = DEFAULT_RECURSION_LIMIT;
72 /** Visible for subclasses. See setSizeLimit() */
73 int sizeLimit = DEFAULT_SIZE_LIMIT;
75 /** Used to adapt to the experimental {@link Reader} interface. */
76 CodedInputStreamReader wrapper;
78 /** Create a new CodedInputStream wrapping the given InputStream. */
79 public static CodedInputStream newInstance(final InputStream input) {
80 return newInstance(input, DEFAULT_BUFFER_SIZE);
83 /** Create a new CodedInputStream wrapping the given InputStream, with a specified buffer size. */
84 public static CodedInputStream newInstance(final InputStream input, int bufferSize) {
85 if (bufferSize <= 0) {
86 throw new IllegalArgumentException("bufferSize must be > 0");
89 // TODO(nathanmittler): Ideally we should throw here. This is done for backward compatibility.
90 return newInstance(EMPTY_BYTE_ARRAY);
92 return new StreamDecoder(input, bufferSize);
95 /** Create a new CodedInputStream wrapping the given {@code Iterable <ByteBuffer>}. */
96 public static CodedInputStream newInstance(final Iterable<ByteBuffer> input) {
97 if (!UnsafeDirectNioDecoder.isSupported()) {
98 return newInstance(new IterableByteBufferInputStream(input));
100 return newInstance(input, false);
103 /** Create a new CodedInputStream wrapping the given {@code Iterable <ByteBuffer>}. */
104 static CodedInputStream newInstance(
105 final Iterable<ByteBuffer> bufs, final boolean bufferIsImmutable) {
106 // flag is to check the type of input's ByteBuffers.
107 // flag equals 1: all ByteBuffers have array.
108 // flag equals 2: all ByteBuffers are direct ByteBuffers.
109 // flag equals 3: some ByteBuffers are direct and some have array.
110 // flag greater than 3: other cases.
112 // Total size of the input
114 for (ByteBuffer buf : bufs) {
115 totalSize += buf.remaining();
116 if (buf.hasArray()) {
118 } else if (buf.isDirect()) {
125 return new IterableDirectByteBufferDecoder(bufs, totalSize, bufferIsImmutable);
127 // TODO(yilunchong): add another decoders to deal case 1 and 3.
128 return newInstance(new IterableByteBufferInputStream(bufs));
132 /** Create a new CodedInputStream wrapping the given byte array. */
133 public static CodedInputStream newInstance(final byte[] buf) {
134 return newInstance(buf, 0, buf.length);
137 /** Create a new CodedInputStream wrapping the given byte array slice. */
138 public static CodedInputStream newInstance(final byte[] buf, final int off, final int len) {
139 return newInstance(buf, off, len, /* bufferIsImmutable= */ false);
142 /** Create a new CodedInputStream wrapping the given byte array slice. */
143 static CodedInputStream newInstance(
144 final byte[] buf, final int off, final int len, final boolean bufferIsImmutable) {
145 ArrayDecoder result = new ArrayDecoder(buf, off, len, bufferIsImmutable);
147 // Some uses of CodedInputStream can be more efficient if they know
148 // exactly how many bytes are available. By pushing the end point of the
149 // buffer as a limit, we allow them to get this information via
150 // getBytesUntilLimit(). Pushing a limit that we know is at the end of
151 // the stream can never hurt, since we can never past that point anyway.
152 result.pushLimit(len);
153 } catch (InvalidProtocolBufferException ex) {
154 // The only reason pushLimit() might throw an exception here is if len
155 // is negative. Normally pushLimit()'s parameter comes directly off the
156 // wire, so it's important to catch exceptions in case of corrupt or
157 // malicious data. However, in this case, we expect that len is not a
158 // user-supplied value, so we can assume that it being negative indicates
159 // a programming error. Therefore, throwing an unchecked exception is
161 throw new IllegalArgumentException(ex);
167 * Create a new CodedInputStream wrapping the given ByteBuffer. The data starting from the
168 * ByteBuffer's current position to its limit will be read. The returned CodedInputStream may or
169 * may not share the underlying data in the ByteBuffer, therefore the ByteBuffer cannot be changed
170 * while the CodedInputStream is in use. Note that the ByteBuffer's position won't be changed by
171 * this function. Concurrent calls with the same ByteBuffer object are safe if no other thread is
172 * trying to alter the ByteBuffer's status.
174 public static CodedInputStream newInstance(ByteBuffer buf) {
175 return newInstance(buf, /* bufferIsImmutable= */ false);
178 /** Create a new CodedInputStream wrapping the given buffer. */
179 static CodedInputStream newInstance(ByteBuffer buf, boolean bufferIsImmutable) {
180 if (buf.hasArray()) {
182 buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), bufferIsImmutable);
185 if (buf.isDirect() && UnsafeDirectNioDecoder.isSupported()) {
186 return new UnsafeDirectNioDecoder(buf, bufferIsImmutable);
189 // The buffer is non-direct and does not expose the underlying array. Using the ByteBuffer API
190 // to access individual bytes is very slow, so just copy the buffer to an array.
191 // TODO(nathanmittler): Re-evaluate with Java 9
192 byte[] buffer = new byte[buf.remaining()];
193 buf.duplicate().get(buffer);
194 return newInstance(buffer, 0, buffer.length, true);
197 /** Disable construction/inheritance outside of this class. */
198 private CodedInputStream() {}
200 // -----------------------------------------------------------------
203 * Attempt to read a field tag, returning zero if we have reached EOF. Protocol message parsers
204 * use this to read tags, since a protocol message may legally end wherever a tag occurs, and zero
205 * is not a valid tag number.
207 public abstract int readTag() throws IOException;
210 * Verifies that the last call to readTag() returned the given tag value. This is used to verify
211 * that a nested group ended with the correct end tag.
213 * @throws InvalidProtocolBufferException {@code value} does not match the last tag.
215 public abstract void checkLastTagWas(final int value) throws InvalidProtocolBufferException;
217 public abstract int getLastTag();
220 * Reads and discards a single field, given its tag value.
222 * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped.
223 * Otherwise, returns {@code true}.
225 public abstract boolean skipField(final int tag) throws IOException;
228 * Reads a single field and writes it to output in wire format, given its tag value.
230 * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped.
231 * Otherwise, returns {@code true}.
232 * @deprecated use {@code UnknownFieldSet} or {@code UnknownFieldSetLite} to skip to an output
236 public abstract boolean skipField(final int tag, final CodedOutputStream output)
240 * Reads and discards an entire message. This will read either until EOF or until an endgroup tag,
241 * whichever comes first.
243 public abstract void skipMessage() throws IOException;
246 * Reads an entire message and writes it to output in wire format. This will read either until EOF
247 * or until an endgroup tag, whichever comes first.
249 public abstract void skipMessage(CodedOutputStream output) throws IOException;
252 // -----------------------------------------------------------------
254 /** Read a {@code double} field value from the stream. */
255 public abstract double readDouble() throws IOException;
257 /** Read a {@code float} field value from the stream. */
258 public abstract float readFloat() throws IOException;
260 /** Read a {@code uint64} field value from the stream. */
261 public abstract long readUInt64() throws IOException;
263 /** Read an {@code int64} field value from the stream. */
264 public abstract long readInt64() throws IOException;
266 /** Read an {@code int32} field value from the stream. */
267 public abstract int readInt32() throws IOException;
269 /** Read a {@code fixed64} field value from the stream. */
270 public abstract long readFixed64() throws IOException;
272 /** Read a {@code fixed32} field value from the stream. */
273 public abstract int readFixed32() throws IOException;
275 /** Read a {@code bool} field value from the stream. */
276 public abstract boolean readBool() throws IOException;
279 * Read a {@code string} field value from the stream. If the stream contains malformed UTF-8,
280 * replace the offending bytes with the standard UTF-8 replacement character.
282 public abstract String readString() throws IOException;
285 * Read a {@code string} field value from the stream. If the stream contains malformed UTF-8,
286 * throw exception {@link InvalidProtocolBufferException}.
288 public abstract String readStringRequireUtf8() throws IOException;
290 /** Read a {@code group} field value from the stream. */
291 public abstract void readGroup(
292 final int fieldNumber,
293 final MessageLite.Builder builder,
294 final ExtensionRegistryLite extensionRegistry)
298 /** Read a {@code group} field value from the stream. */
299 public abstract <T extends MessageLite> T readGroup(
300 final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)
304 * Reads a {@code group} field value from the stream and merges it into the given {@link
307 * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so you can just call
308 * {@link #readGroup}.
311 public abstract void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
314 /** Read an embedded message field value from the stream. */
315 public abstract void readMessage(
316 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
320 /** Read an embedded message field value from the stream. */
321 public abstract <T extends MessageLite> T readMessage(
322 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException;
324 /** Read a {@code bytes} field value from the stream. */
325 public abstract ByteString readBytes() throws IOException;
327 /** Read a {@code bytes} field value from the stream. */
328 public abstract byte[] readByteArray() throws IOException;
330 /** Read a {@code bytes} field value from the stream. */
331 public abstract ByteBuffer readByteBuffer() throws IOException;
333 /** Read a {@code uint32} field value from the stream. */
334 public abstract int readUInt32() throws IOException;
337 * Read an enum field value from the stream. Caller is responsible for converting the numeric
338 * value to an actual enum.
340 public abstract int readEnum() throws IOException;
342 /** Read an {@code sfixed32} field value from the stream. */
343 public abstract int readSFixed32() throws IOException;
345 /** Read an {@code sfixed64} field value from the stream. */
346 public abstract long readSFixed64() throws IOException;
348 /** Read an {@code sint32} field value from the stream. */
349 public abstract int readSInt32() throws IOException;
351 /** Read an {@code sint64} field value from the stream. */
352 public abstract long readSInt64() throws IOException;
354 // =================================================================
356 /** Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits. */
357 public abstract int readRawVarint32() throws IOException;
359 /** Read a raw Varint from the stream. */
360 public abstract long readRawVarint64() throws IOException;
362 /** Variant of readRawVarint64 for when uncomfortably close to the limit. */
363 /* Visible for testing */
364 abstract long readRawVarint64SlowPath() throws IOException;
366 /** Read a 32-bit little-endian integer from the stream. */
367 public abstract int readRawLittleEndian32() throws IOException;
369 /** Read a 64-bit little-endian integer from the stream. */
370 public abstract long readRawLittleEndian64() throws IOException;
372 // -----------------------------------------------------------------
375 * Enables {@link ByteString} aliasing of the underlying buffer, trading off on buffer pinning for
376 * data copies. Only valid for buffer-backed streams.
378 public abstract void enableAliasing(boolean enabled);
381 * Set the maximum message recursion depth. In order to prevent malicious messages from causing
382 * stack overflows, {@code CodedInputStream} limits how deeply messages may be nested. The default
385 * @return the old limit.
387 public final int setRecursionLimit(final int limit) {
389 throw new IllegalArgumentException("Recursion limit cannot be negative: " + limit);
391 final int oldLimit = recursionLimit;
392 recursionLimit = limit;
397 * Only valid for {@link InputStream}-backed streams.
399 * <p>Set the maximum message size. In order to prevent malicious messages from exhausting memory
400 * or causing integer overflows, {@code CodedInputStream} limits how large a message may be. The
401 * default limit is {@code Integer.MAX_INT}. You should set this limit as small as you can without
402 * harming your app's functionality. Note that size limits only apply when reading from an {@code
403 * InputStream}, not when constructed around a raw byte array.
405 * <p>If you want to read several messages from a single CodedInputStream, you could call {@link
406 * #resetSizeCounter()} after each one to avoid hitting the size limit.
408 * @return the old limit.
410 public final int setSizeLimit(final int limit) {
412 throw new IllegalArgumentException("Size limit cannot be negative: " + limit);
414 final int oldLimit = sizeLimit;
419 private boolean shouldDiscardUnknownFields = false;
422 * Sets this {@code CodedInputStream} to discard unknown fields. Only applies to full runtime
423 * messages; lite messages will always preserve unknowns.
425 * <p>Note calling this function alone will have NO immediate effect on the underlying input data.
426 * The unknown fields will be discarded during parsing. This affects both Proto2 and Proto3 full
429 final void discardUnknownFields() {
430 shouldDiscardUnknownFields = true;
434 * Reverts the unknown fields preservation behavior for Proto2 and Proto3 full runtime to their
437 final void unsetDiscardUnknownFields() {
438 shouldDiscardUnknownFields = false;
442 * Whether unknown fields in this input stream should be discarded during parsing into full
445 final boolean shouldDiscardUnknownFields() {
446 return shouldDiscardUnknownFields;
450 * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). Only valid for {@link
451 * InputStream}-backed streams.
453 public abstract void resetSizeCounter();
456 * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This is called when
457 * descending into a length-delimited embedded message.
459 * <p>Note that {@code pushLimit()} does NOT affect how many bytes the {@code CodedInputStream}
460 * reads from an underlying {@code InputStream} when refreshing its buffer. If you need to prevent
461 * reading past a certain point in the underlying {@code InputStream} (e.g. because you expect it
462 * to contain more data after the end of the message which you need to handle differently) then
463 * you must place a wrapper around your {@code InputStream} which limits the amount of data that
464 * can be read from it.
466 * @return the old limit.
468 public abstract int pushLimit(int byteLimit) throws InvalidProtocolBufferException;
471 * Discards the current limit, returning to the previous limit.
473 * @param oldLimit The old limit, as returned by {@code pushLimit}.
475 public abstract void popLimit(final int oldLimit);
478 * Returns the number of bytes to be read before the current limit. If no limit is set, returns
481 public abstract int getBytesUntilLimit();
484 * Returns true if the stream has reached the end of the input. This is the case if either the end
485 * of the underlying input source has been reached or if the stream has reached a limit created
486 * using {@link #pushLimit(int)}.
488 public abstract boolean isAtEnd() throws IOException;
491 * The total bytes read up to the current position. Calling {@link #resetSizeCounter()} resets
492 * this value to zero.
494 public abstract int getTotalBytesRead();
497 * Read one byte from the input.
499 * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
501 public abstract byte readRawByte() throws IOException;
504 * Read a fixed size of bytes from the input.
506 * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
508 public abstract byte[] readRawBytes(final int size) throws IOException;
511 * Reads and discards {@code size} bytes.
513 * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
515 public abstract void skipRawBytes(final int size) throws IOException;
518 * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers into values that can be
519 * efficiently encoded with varint. (Otherwise, negative values must be sign-extended to 64 bits
520 * to be varint encoded, thus always taking 10 bytes on the wire.)
522 * @param n An unsigned 32-bit integer, stored in a signed int because Java has no explicit
524 * @return A signed 32-bit integer.
526 public static int decodeZigZag32(final int n) {
527 return (n >>> 1) ^ -(n & 1);
531 * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers into values that can be
532 * efficiently encoded with varint. (Otherwise, negative values must be sign-extended to 64 bits
533 * to be varint encoded, thus always taking 10 bytes on the wire.)
535 * @param n An unsigned 64-bit integer, stored in a signed int because Java has no explicit
537 * @return A signed 64-bit integer.
539 public static long decodeZigZag64(final long n) {
540 return (n >>> 1) ^ -(n & 1);
544 * Like {@link #readRawVarint32(InputStream)}, but expects that the caller has already read one
545 * byte. This allows the caller to determine if EOF has been reached before attempting to read.
547 public static int readRawVarint32(final int firstByte, final InputStream input)
549 if ((firstByte & 0x80) == 0) {
553 int result = firstByte & 0x7f;
555 for (; offset < 32; offset += 7) {
556 final int b = input.read();
558 throw InvalidProtocolBufferException.truncatedMessage();
560 result |= (b & 0x7f) << offset;
561 if ((b & 0x80) == 0) {
565 // Keep reading up to 64 bits.
566 for (; offset < 64; offset += 7) {
567 final int b = input.read();
569 throw InvalidProtocolBufferException.truncatedMessage();
571 if ((b & 0x80) == 0) {
575 throw InvalidProtocolBufferException.malformedVarint();
579 * Reads a varint from the input one byte at a time, so that it does not read any bytes after the
580 * end of the varint. If you simply wrapped the stream in a CodedInputStream and used {@link
581 * #readRawVarint32(InputStream)} then you would probably end up reading past the end of the
582 * varint since CodedInputStream buffers its input.
584 static int readRawVarint32(final InputStream input) throws IOException {
585 final int firstByte = input.read();
586 if (firstByte == -1) {
587 throw InvalidProtocolBufferException.truncatedMessage();
589 return readRawVarint32(firstByte, input);
592 /** A {@link CodedInputStream} implementation that uses a backing array as the input. */
593 private static final class ArrayDecoder extends CodedInputStream {
594 private final byte[] buffer;
595 private final boolean immutable;
597 private int bufferSizeAfterLimit;
599 private int startPos;
601 private boolean enableAliasing;
603 /** The absolute position of the end of the current message. */
604 private int currentLimit = Integer.MAX_VALUE;
606 private ArrayDecoder(final byte[] buffer, final int offset, final int len, boolean immutable) {
607 this.buffer = buffer;
608 limit = offset + len;
611 this.immutable = immutable;
615 public int readTag() throws IOException {
621 lastTag = readRawVarint32();
622 if (WireFormat.getTagFieldNumber(lastTag) == 0) {
623 // If we actually read zero (or any tag number corresponding to field
624 // number zero), that's not a valid tag.
625 throw InvalidProtocolBufferException.invalidTag();
631 public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
632 if (lastTag != value) {
633 throw InvalidProtocolBufferException.invalidEndTag();
638 public int getLastTag() {
643 public boolean skipField(final int tag) throws IOException {
644 switch (WireFormat.getTagWireType(tag)) {
645 case WireFormat.WIRETYPE_VARINT:
648 case WireFormat.WIRETYPE_FIXED64:
649 skipRawBytes(FIXED64_SIZE);
651 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
652 skipRawBytes(readRawVarint32());
654 case WireFormat.WIRETYPE_START_GROUP:
657 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
659 case WireFormat.WIRETYPE_END_GROUP:
661 case WireFormat.WIRETYPE_FIXED32:
662 skipRawBytes(FIXED32_SIZE);
665 throw InvalidProtocolBufferException.invalidWireType();
670 public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
671 switch (WireFormat.getTagWireType(tag)) {
672 case WireFormat.WIRETYPE_VARINT:
674 long value = readInt64();
675 output.writeRawVarint32(tag);
676 output.writeUInt64NoTag(value);
679 case WireFormat.WIRETYPE_FIXED64:
681 long value = readRawLittleEndian64();
682 output.writeRawVarint32(tag);
683 output.writeFixed64NoTag(value);
686 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
688 ByteString value = readBytes();
689 output.writeRawVarint32(tag);
690 output.writeBytesNoTag(value);
693 case WireFormat.WIRETYPE_START_GROUP:
695 output.writeRawVarint32(tag);
699 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
700 checkLastTagWas(endtag);
701 output.writeRawVarint32(endtag);
704 case WireFormat.WIRETYPE_END_GROUP:
708 case WireFormat.WIRETYPE_FIXED32:
710 int value = readRawLittleEndian32();
711 output.writeRawVarint32(tag);
712 output.writeFixed32NoTag(value);
716 throw InvalidProtocolBufferException.invalidWireType();
721 public void skipMessage() throws IOException {
723 final int tag = readTag();
724 if (tag == 0 || !skipField(tag)) {
731 public void skipMessage(CodedOutputStream output) throws IOException {
733 final int tag = readTag();
734 if (tag == 0 || !skipField(tag, output)) {
741 // -----------------------------------------------------------------
744 public double readDouble() throws IOException {
745 return Double.longBitsToDouble(readRawLittleEndian64());
749 public float readFloat() throws IOException {
750 return Float.intBitsToFloat(readRawLittleEndian32());
754 public long readUInt64() throws IOException {
755 return readRawVarint64();
759 public long readInt64() throws IOException {
760 return readRawVarint64();
764 public int readInt32() throws IOException {
765 return readRawVarint32();
769 public long readFixed64() throws IOException {
770 return readRawLittleEndian64();
774 public int readFixed32() throws IOException {
775 return readRawLittleEndian32();
779 public boolean readBool() throws IOException {
780 return readRawVarint64() != 0;
784 public String readString() throws IOException {
785 final int size = readRawVarint32();
786 if (size > 0 && size <= (limit - pos)) {
787 // Fast path: We already have the bytes in a contiguous buffer, so
788 // just copy directly from it.
789 final String result = new String(buffer, pos, size, UTF_8);
798 throw InvalidProtocolBufferException.negativeSize();
800 throw InvalidProtocolBufferException.truncatedMessage();
804 public String readStringRequireUtf8() throws IOException {
805 final int size = readRawVarint32();
806 if (size > 0 && size <= (limit - pos)) {
807 String result = Utf8.decodeUtf8(buffer, pos, size);
816 throw InvalidProtocolBufferException.negativeSize();
818 throw InvalidProtocolBufferException.truncatedMessage();
822 public void readGroup(
823 final int fieldNumber,
824 final MessageLite.Builder builder,
825 final ExtensionRegistryLite extensionRegistry)
827 if (recursionDepth >= recursionLimit) {
828 throw InvalidProtocolBufferException.recursionLimitExceeded();
831 builder.mergeFrom(this, extensionRegistry);
832 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
838 public <T extends MessageLite> T readGroup(
839 final int fieldNumber,
840 final Parser<T> parser,
841 final ExtensionRegistryLite extensionRegistry)
843 if (recursionDepth >= recursionLimit) {
844 throw InvalidProtocolBufferException.recursionLimitExceeded();
847 T result = parser.parsePartialFrom(this, extensionRegistry);
848 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
855 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
857 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
861 public void readMessage(
862 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
864 final int length = readRawVarint32();
865 if (recursionDepth >= recursionLimit) {
866 throw InvalidProtocolBufferException.recursionLimitExceeded();
868 final int oldLimit = pushLimit(length);
870 builder.mergeFrom(this, extensionRegistry);
878 public <T extends MessageLite> T readMessage(
879 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
880 int length = readRawVarint32();
881 if (recursionDepth >= recursionLimit) {
882 throw InvalidProtocolBufferException.recursionLimitExceeded();
884 final int oldLimit = pushLimit(length);
886 T result = parser.parsePartialFrom(this, extensionRegistry);
894 public ByteString readBytes() throws IOException {
895 final int size = readRawVarint32();
896 if (size > 0 && size <= (limit - pos)) {
897 // Fast path: We already have the bytes in a contiguous buffer, so
898 // just copy directly from it.
899 final ByteString result =
900 immutable && enableAliasing
901 ? ByteString.wrap(buffer, pos, size)
902 : ByteString.copyFrom(buffer, pos, size);
907 return ByteString.EMPTY;
909 // Slow path: Build a byte array first then copy it.
910 return ByteString.wrap(readRawBytes(size));
914 public byte[] readByteArray() throws IOException {
915 final int size = readRawVarint32();
916 return readRawBytes(size);
920 public ByteBuffer readByteBuffer() throws IOException {
921 final int size = readRawVarint32();
922 if (size > 0 && size <= (limit - pos)) {
923 // Fast path: We already have the bytes in a contiguous buffer.
924 // When aliasing is enabled, we can return a ByteBuffer pointing directly
925 // into the underlying byte array without copy if the CodedInputStream is
926 // constructed from a byte array. If aliasing is disabled or the input is
927 // from an InputStream or ByteString, we have to make a copy of the bytes.
929 !immutable && enableAliasing
930 ? ByteBuffer.wrap(buffer, pos, size).slice()
931 : ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size));
933 // TODO(nathanmittler): Investigate making the ByteBuffer be made read-only
938 return EMPTY_BYTE_BUFFER;
941 throw InvalidProtocolBufferException.negativeSize();
943 throw InvalidProtocolBufferException.truncatedMessage();
947 public int readUInt32() throws IOException {
948 return readRawVarint32();
952 public int readEnum() throws IOException {
953 return readRawVarint32();
957 public int readSFixed32() throws IOException {
958 return readRawLittleEndian32();
962 public long readSFixed64() throws IOException {
963 return readRawLittleEndian64();
967 public int readSInt32() throws IOException {
968 return decodeZigZag32(readRawVarint32());
972 public long readSInt64() throws IOException {
973 return decodeZigZag64(readRawVarint64());
976 // =================================================================
979 public int readRawVarint32() throws IOException {
980 // See implementation notes for readRawVarint64
985 if (limit == tempPos) {
989 final byte[] buffer = this.buffer;
991 if ((x = buffer[tempPos++]) >= 0) {
994 } else if (limit - tempPos < 9) {
996 } else if ((x ^= (buffer[tempPos++] << 7)) < 0) {
998 } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) {
999 x ^= (~0 << 7) ^ (~0 << 14);
1000 } else if ((x ^= (buffer[tempPos++] << 21)) < 0) {
1001 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
1003 int y = buffer[tempPos++];
1005 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
1007 && buffer[tempPos++] < 0
1008 && buffer[tempPos++] < 0
1009 && buffer[tempPos++] < 0
1010 && buffer[tempPos++] < 0
1011 && buffer[tempPos++] < 0) {
1012 break fastpath; // Will throw malformedVarint()
1018 return (int) readRawVarint64SlowPath();
1021 private void skipRawVarint() throws IOException {
1022 if (limit - pos >= MAX_VARINT_SIZE) {
1023 skipRawVarintFastPath();
1025 skipRawVarintSlowPath();
1029 private void skipRawVarintFastPath() throws IOException {
1030 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
1031 if (buffer[pos++] >= 0) {
1035 throw InvalidProtocolBufferException.malformedVarint();
1038 private void skipRawVarintSlowPath() throws IOException {
1039 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
1040 if (readRawByte() >= 0) {
1044 throw InvalidProtocolBufferException.malformedVarint();
1048 public long readRawVarint64() throws IOException {
1049 // Implementation notes:
1051 // Optimized for one-byte values, expected to be common.
1052 // The particular code below was selected from various candidates
1053 // empirically, by winning VarintBenchmark.
1055 // Sign extension of (signed) Java bytes is usually a nuisance, but
1056 // we exploit it here to more easily obtain the sign of bytes read.
1057 // Instead of cleaning up the sign extension bits by masking eagerly,
1058 // we delay until we find the final (positive) byte, when we clear all
1059 // accumulated bits with one xor. We depend on javac to constant fold.
1064 if (limit == tempPos) {
1068 final byte[] buffer = this.buffer;
1071 if ((y = buffer[tempPos++]) >= 0) {
1074 } else if (limit - tempPos < 9) {
1076 } else if ((y ^= (buffer[tempPos++] << 7)) < 0) {
1078 } else if ((y ^= (buffer[tempPos++] << 14)) >= 0) {
1079 x = y ^ ((~0 << 7) ^ (~0 << 14));
1080 } else if ((y ^= (buffer[tempPos++] << 21)) < 0) {
1081 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
1082 } else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) {
1083 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
1084 } else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) {
1085 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
1086 } else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) {
1087 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
1088 } else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) {
1098 x ^= ((long) buffer[tempPos++] << 56);
1109 if (buffer[tempPos++] < 0L) {
1110 break fastpath; // Will throw malformedVarint()
1117 return readRawVarint64SlowPath();
1121 long readRawVarint64SlowPath() throws IOException {
1123 for (int shift = 0; shift < 64; shift += 7) {
1124 final byte b = readRawByte();
1125 result |= (long) (b & 0x7F) << shift;
1126 if ((b & 0x80) == 0) {
1130 throw InvalidProtocolBufferException.malformedVarint();
1134 public int readRawLittleEndian32() throws IOException {
1137 if (limit - tempPos < FIXED32_SIZE) {
1138 throw InvalidProtocolBufferException.truncatedMessage();
1141 final byte[] buffer = this.buffer;
1142 pos = tempPos + FIXED32_SIZE;
1143 return (((buffer[tempPos] & 0xff))
1144 | ((buffer[tempPos + 1] & 0xff) << 8)
1145 | ((buffer[tempPos + 2] & 0xff) << 16)
1146 | ((buffer[tempPos + 3] & 0xff) << 24));
1150 public long readRawLittleEndian64() throws IOException {
1153 if (limit - tempPos < FIXED64_SIZE) {
1154 throw InvalidProtocolBufferException.truncatedMessage();
1157 final byte[] buffer = this.buffer;
1158 pos = tempPos + FIXED64_SIZE;
1159 return (((buffer[tempPos] & 0xffL))
1160 | ((buffer[tempPos + 1] & 0xffL) << 8)
1161 | ((buffer[tempPos + 2] & 0xffL) << 16)
1162 | ((buffer[tempPos + 3] & 0xffL) << 24)
1163 | ((buffer[tempPos + 4] & 0xffL) << 32)
1164 | ((buffer[tempPos + 5] & 0xffL) << 40)
1165 | ((buffer[tempPos + 6] & 0xffL) << 48)
1166 | ((buffer[tempPos + 7] & 0xffL) << 56));
1170 public void enableAliasing(boolean enabled) {
1171 this.enableAliasing = enabled;
1175 public void resetSizeCounter() {
1180 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
1181 if (byteLimit < 0) {
1182 throw InvalidProtocolBufferException.negativeSize();
1184 byteLimit += getTotalBytesRead();
1185 final int oldLimit = currentLimit;
1186 if (byteLimit > oldLimit) {
1187 throw InvalidProtocolBufferException.truncatedMessage();
1189 currentLimit = byteLimit;
1191 recomputeBufferSizeAfterLimit();
1196 private void recomputeBufferSizeAfterLimit() {
1197 limit += bufferSizeAfterLimit;
1198 final int bufferEnd = limit - startPos;
1199 if (bufferEnd > currentLimit) {
1200 // Limit is in current buffer.
1201 bufferSizeAfterLimit = bufferEnd - currentLimit;
1202 limit -= bufferSizeAfterLimit;
1204 bufferSizeAfterLimit = 0;
1209 public void popLimit(final int oldLimit) {
1210 currentLimit = oldLimit;
1211 recomputeBufferSizeAfterLimit();
1215 public int getBytesUntilLimit() {
1216 if (currentLimit == Integer.MAX_VALUE) {
1220 return currentLimit - getTotalBytesRead();
1224 public boolean isAtEnd() throws IOException {
1225 return pos == limit;
1229 public int getTotalBytesRead() {
1230 return pos - startPos;
1234 public byte readRawByte() throws IOException {
1236 throw InvalidProtocolBufferException.truncatedMessage();
1238 return buffer[pos++];
1242 public byte[] readRawBytes(final int length) throws IOException {
1243 if (length > 0 && length <= (limit - pos)) {
1244 final int tempPos = pos;
1246 return Arrays.copyOfRange(buffer, tempPos, pos);
1251 return Internal.EMPTY_BYTE_ARRAY;
1253 throw InvalidProtocolBufferException.negativeSize();
1256 throw InvalidProtocolBufferException.truncatedMessage();
1260 public void skipRawBytes(final int length) throws IOException {
1261 if (length >= 0 && length <= (limit - pos)) {
1262 // We have all the bytes we need already.
1268 throw InvalidProtocolBufferException.negativeSize();
1270 throw InvalidProtocolBufferException.truncatedMessage();
1275 * A {@link CodedInputStream} implementation that uses a backing direct ByteBuffer as the input.
1276 * Requires the use of {@code sun.misc.Unsafe} to perform fast reads on the buffer.
1278 private static final class UnsafeDirectNioDecoder extends CodedInputStream {
1279 /** The direct buffer that is backing this stream. */
1280 private final ByteBuffer buffer;
1283 * If {@code true}, indicates that the buffer is backing a {@link ByteString} and is therefore
1284 * considered to be an immutable input source.
1286 private final boolean immutable;
1288 /** The unsafe address of the content of {@link #buffer}. */
1289 private final long address;
1291 /** The unsafe address of the current read limit of the buffer. */
1294 /** The unsafe address of the current read position of the buffer. */
1297 /** The unsafe address of the starting read position. */
1298 private long startPos;
1300 /** The amount of available data in the buffer beyond {@link #limit}. */
1301 private int bufferSizeAfterLimit;
1303 /** The last tag that was read from this stream. */
1304 private int lastTag;
1307 * If {@code true}, indicates that calls to read {@link ByteString} or {@code byte[]}
1308 * <strong>may</strong> return slices of the underlying buffer, rather than copies.
1310 private boolean enableAliasing;
1312 /** The absolute position of the end of the current message. */
1313 private int currentLimit = Integer.MAX_VALUE;
1315 static boolean isSupported() {
1316 return UnsafeUtil.hasUnsafeByteBufferOperations();
1319 private UnsafeDirectNioDecoder(ByteBuffer buffer, boolean immutable) {
1320 this.buffer = buffer;
1321 address = UnsafeUtil.addressOffset(buffer);
1322 limit = address + buffer.limit();
1323 pos = address + buffer.position();
1325 this.immutable = immutable;
1329 public int readTag() throws IOException {
1335 lastTag = readRawVarint32();
1336 if (WireFormat.getTagFieldNumber(lastTag) == 0) {
1337 // If we actually read zero (or any tag number corresponding to field
1338 // number zero), that's not a valid tag.
1339 throw InvalidProtocolBufferException.invalidTag();
1345 public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
1346 if (lastTag != value) {
1347 throw InvalidProtocolBufferException.invalidEndTag();
1352 public int getLastTag() {
1357 public boolean skipField(final int tag) throws IOException {
1358 switch (WireFormat.getTagWireType(tag)) {
1359 case WireFormat.WIRETYPE_VARINT:
1362 case WireFormat.WIRETYPE_FIXED64:
1363 skipRawBytes(FIXED64_SIZE);
1365 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
1366 skipRawBytes(readRawVarint32());
1368 case WireFormat.WIRETYPE_START_GROUP:
1371 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
1373 case WireFormat.WIRETYPE_END_GROUP:
1375 case WireFormat.WIRETYPE_FIXED32:
1376 skipRawBytes(FIXED32_SIZE);
1379 throw InvalidProtocolBufferException.invalidWireType();
1384 public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
1385 switch (WireFormat.getTagWireType(tag)) {
1386 case WireFormat.WIRETYPE_VARINT:
1388 long value = readInt64();
1389 output.writeRawVarint32(tag);
1390 output.writeUInt64NoTag(value);
1393 case WireFormat.WIRETYPE_FIXED64:
1395 long value = readRawLittleEndian64();
1396 output.writeRawVarint32(tag);
1397 output.writeFixed64NoTag(value);
1400 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
1402 ByteString value = readBytes();
1403 output.writeRawVarint32(tag);
1404 output.writeBytesNoTag(value);
1407 case WireFormat.WIRETYPE_START_GROUP:
1409 output.writeRawVarint32(tag);
1410 skipMessage(output);
1413 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
1414 checkLastTagWas(endtag);
1415 output.writeRawVarint32(endtag);
1418 case WireFormat.WIRETYPE_END_GROUP:
1422 case WireFormat.WIRETYPE_FIXED32:
1424 int value = readRawLittleEndian32();
1425 output.writeRawVarint32(tag);
1426 output.writeFixed32NoTag(value);
1430 throw InvalidProtocolBufferException.invalidWireType();
1435 public void skipMessage() throws IOException {
1437 final int tag = readTag();
1438 if (tag == 0 || !skipField(tag)) {
1445 public void skipMessage(CodedOutputStream output) throws IOException {
1447 final int tag = readTag();
1448 if (tag == 0 || !skipField(tag, output)) {
1455 // -----------------------------------------------------------------
1458 public double readDouble() throws IOException {
1459 return Double.longBitsToDouble(readRawLittleEndian64());
1463 public float readFloat() throws IOException {
1464 return Float.intBitsToFloat(readRawLittleEndian32());
1468 public long readUInt64() throws IOException {
1469 return readRawVarint64();
1473 public long readInt64() throws IOException {
1474 return readRawVarint64();
1478 public int readInt32() throws IOException {
1479 return readRawVarint32();
1483 public long readFixed64() throws IOException {
1484 return readRawLittleEndian64();
1488 public int readFixed32() throws IOException {
1489 return readRawLittleEndian32();
1493 public boolean readBool() throws IOException {
1494 return readRawVarint64() != 0;
1498 public String readString() throws IOException {
1499 final int size = readRawVarint32();
1500 if (size > 0 && size <= remaining()) {
1501 // TODO(nathanmittler): Is there a way to avoid this copy?
1502 // TODO(anuraaga): It might be possible to share the optimized loop with
1503 // readStringRequireUtf8 by implementing Java replacement logic there.
1504 // The same as readBytes' logic
1505 byte[] bytes = new byte[size];
1506 UnsafeUtil.copyMemory(pos, bytes, 0, size);
1507 String result = new String(bytes, UTF_8);
1516 throw InvalidProtocolBufferException.negativeSize();
1518 throw InvalidProtocolBufferException.truncatedMessage();
1522 public String readStringRequireUtf8() throws IOException {
1523 final int size = readRawVarint32();
1524 if (size > 0 && size <= remaining()) {
1525 final int bufferPos = bufferPos(pos);
1526 String result = Utf8.decodeUtf8(buffer, bufferPos, size);
1535 throw InvalidProtocolBufferException.negativeSize();
1537 throw InvalidProtocolBufferException.truncatedMessage();
1541 public void readGroup(
1542 final int fieldNumber,
1543 final MessageLite.Builder builder,
1544 final ExtensionRegistryLite extensionRegistry)
1545 throws IOException {
1546 if (recursionDepth >= recursionLimit) {
1547 throw InvalidProtocolBufferException.recursionLimitExceeded();
1550 builder.mergeFrom(this, extensionRegistry);
1551 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
1557 public <T extends MessageLite> T readGroup(
1558 final int fieldNumber,
1559 final Parser<T> parser,
1560 final ExtensionRegistryLite extensionRegistry)
1561 throws IOException {
1562 if (recursionDepth >= recursionLimit) {
1563 throw InvalidProtocolBufferException.recursionLimitExceeded();
1566 T result = parser.parsePartialFrom(this, extensionRegistry);
1567 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
1574 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
1575 throws IOException {
1576 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
1580 public void readMessage(
1581 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
1582 throws IOException {
1583 final int length = readRawVarint32();
1584 if (recursionDepth >= recursionLimit) {
1585 throw InvalidProtocolBufferException.recursionLimitExceeded();
1587 final int oldLimit = pushLimit(length);
1589 builder.mergeFrom(this, extensionRegistry);
1597 public <T extends MessageLite> T readMessage(
1598 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
1599 int length = readRawVarint32();
1600 if (recursionDepth >= recursionLimit) {
1601 throw InvalidProtocolBufferException.recursionLimitExceeded();
1603 final int oldLimit = pushLimit(length);
1605 T result = parser.parsePartialFrom(this, extensionRegistry);
1613 public ByteString readBytes() throws IOException {
1614 final int size = readRawVarint32();
1615 if (size > 0 && size <= remaining()) {
1616 if (immutable && enableAliasing) {
1617 final ByteBuffer result = slice(pos, pos + size);
1619 return ByteString.wrap(result);
1621 // Use UnsafeUtil to copy the memory to bytes instead of using ByteBuffer ways.
1622 byte[] bytes = new byte[size];
1623 UnsafeUtil.copyMemory(pos, bytes, 0, size);
1625 return ByteString.wrap(bytes);
1630 return ByteString.EMPTY;
1633 throw InvalidProtocolBufferException.negativeSize();
1635 throw InvalidProtocolBufferException.truncatedMessage();
1639 public byte[] readByteArray() throws IOException {
1640 return readRawBytes(readRawVarint32());
1644 public ByteBuffer readByteBuffer() throws IOException {
1645 final int size = readRawVarint32();
1646 if (size > 0 && size <= remaining()) {
1647 // "Immutable" implies that buffer is backing a ByteString.
1648 // Disallow slicing in this case to prevent the caller from modifying the contents
1649 // of the ByteString.
1650 if (!immutable && enableAliasing) {
1651 final ByteBuffer result = slice(pos, pos + size);
1655 // The same as readBytes' logic
1656 byte[] bytes = new byte[size];
1657 UnsafeUtil.copyMemory(pos, bytes, 0, size);
1659 return ByteBuffer.wrap(bytes);
1661 // TODO(nathanmittler): Investigate making the ByteBuffer be made read-only
1665 return EMPTY_BYTE_BUFFER;
1668 throw InvalidProtocolBufferException.negativeSize();
1670 throw InvalidProtocolBufferException.truncatedMessage();
1674 public int readUInt32() throws IOException {
1675 return readRawVarint32();
1679 public int readEnum() throws IOException {
1680 return readRawVarint32();
1684 public int readSFixed32() throws IOException {
1685 return readRawLittleEndian32();
1689 public long readSFixed64() throws IOException {
1690 return readRawLittleEndian64();
1694 public int readSInt32() throws IOException {
1695 return decodeZigZag32(readRawVarint32());
1699 public long readSInt64() throws IOException {
1700 return decodeZigZag64(readRawVarint64());
1703 // =================================================================
1706 public int readRawVarint32() throws IOException {
1707 // See implementation notes for readRawVarint64
1712 if (limit == tempPos) {
1717 if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) {
1720 } else if (limit - tempPos < 9) {
1722 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
1724 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
1725 x ^= (~0 << 7) ^ (~0 << 14);
1726 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
1727 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
1729 int y = UnsafeUtil.getByte(tempPos++);
1731 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
1733 && UnsafeUtil.getByte(tempPos++) < 0
1734 && UnsafeUtil.getByte(tempPos++) < 0
1735 && UnsafeUtil.getByte(tempPos++) < 0
1736 && UnsafeUtil.getByte(tempPos++) < 0
1737 && UnsafeUtil.getByte(tempPos++) < 0) {
1738 break fastpath; // Will throw malformedVarint()
1744 return (int) readRawVarint64SlowPath();
1747 private void skipRawVarint() throws IOException {
1748 if (remaining() >= MAX_VARINT_SIZE) {
1749 skipRawVarintFastPath();
1751 skipRawVarintSlowPath();
1755 private void skipRawVarintFastPath() throws IOException {
1756 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
1757 if (UnsafeUtil.getByte(pos++) >= 0) {
1761 throw InvalidProtocolBufferException.malformedVarint();
1764 private void skipRawVarintSlowPath() throws IOException {
1765 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
1766 if (readRawByte() >= 0) {
1770 throw InvalidProtocolBufferException.malformedVarint();
1774 public long readRawVarint64() throws IOException {
1775 // Implementation notes:
1777 // Optimized for one-byte values, expected to be common.
1778 // The particular code below was selected from various candidates
1779 // empirically, by winning VarintBenchmark.
1781 // Sign extension of (signed) Java bytes is usually a nuisance, but
1782 // we exploit it here to more easily obtain the sign of bytes read.
1783 // Instead of cleaning up the sign extension bits by masking eagerly,
1784 // we delay until we find the final (positive) byte, when we clear all
1785 // accumulated bits with one xor. We depend on javac to constant fold.
1790 if (limit == tempPos) {
1796 if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) {
1799 } else if (limit - tempPos < 9) {
1801 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
1803 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
1804 x = y ^ ((~0 << 7) ^ (~0 << 14));
1805 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
1806 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
1807 } else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) {
1808 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
1809 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) {
1810 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
1811 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) {
1812 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
1813 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) {
1823 x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56);
1834 if (UnsafeUtil.getByte(tempPos++) < 0L) {
1835 break fastpath; // Will throw malformedVarint()
1842 return readRawVarint64SlowPath();
1846 long readRawVarint64SlowPath() throws IOException {
1848 for (int shift = 0; shift < 64; shift += 7) {
1849 final byte b = readRawByte();
1850 result |= (long) (b & 0x7F) << shift;
1851 if ((b & 0x80) == 0) {
1855 throw InvalidProtocolBufferException.malformedVarint();
1859 public int readRawLittleEndian32() throws IOException {
1862 if (limit - tempPos < FIXED32_SIZE) {
1863 throw InvalidProtocolBufferException.truncatedMessage();
1866 pos = tempPos + FIXED32_SIZE;
1867 return (((UnsafeUtil.getByte(tempPos) & 0xff))
1868 | ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8)
1869 | ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16)
1870 | ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24));
1874 public long readRawLittleEndian64() throws IOException {
1877 if (limit - tempPos < FIXED64_SIZE) {
1878 throw InvalidProtocolBufferException.truncatedMessage();
1881 pos = tempPos + FIXED64_SIZE;
1882 return (((UnsafeUtil.getByte(tempPos) & 0xffL))
1883 | ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8)
1884 | ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16)
1885 | ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24)
1886 | ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32)
1887 | ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40)
1888 | ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48)
1889 | ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56));
1893 public void enableAliasing(boolean enabled) {
1894 this.enableAliasing = enabled;
1898 public void resetSizeCounter() {
1903 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
1904 if (byteLimit < 0) {
1905 throw InvalidProtocolBufferException.negativeSize();
1907 byteLimit += getTotalBytesRead();
1908 final int oldLimit = currentLimit;
1909 if (byteLimit > oldLimit) {
1910 throw InvalidProtocolBufferException.truncatedMessage();
1912 currentLimit = byteLimit;
1914 recomputeBufferSizeAfterLimit();
1920 public void popLimit(final int oldLimit) {
1921 currentLimit = oldLimit;
1922 recomputeBufferSizeAfterLimit();
1926 public int getBytesUntilLimit() {
1927 if (currentLimit == Integer.MAX_VALUE) {
1931 return currentLimit - getTotalBytesRead();
1935 public boolean isAtEnd() throws IOException {
1936 return pos == limit;
1940 public int getTotalBytesRead() {
1941 return (int) (pos - startPos);
1945 public byte readRawByte() throws IOException {
1947 throw InvalidProtocolBufferException.truncatedMessage();
1949 return UnsafeUtil.getByte(pos++);
1953 public byte[] readRawBytes(final int length) throws IOException {
1954 if (length >= 0 && length <= remaining()) {
1955 byte[] bytes = new byte[length];
1956 slice(pos, pos + length).get(bytes);
1963 return EMPTY_BYTE_ARRAY;
1965 throw InvalidProtocolBufferException.negativeSize();
1969 throw InvalidProtocolBufferException.truncatedMessage();
1973 public void skipRawBytes(final int length) throws IOException {
1974 if (length >= 0 && length <= remaining()) {
1975 // We have all the bytes we need already.
1981 throw InvalidProtocolBufferException.negativeSize();
1983 throw InvalidProtocolBufferException.truncatedMessage();
1986 private void recomputeBufferSizeAfterLimit() {
1987 limit += bufferSizeAfterLimit;
1988 final int bufferEnd = (int) (limit - startPos);
1989 if (bufferEnd > currentLimit) {
1990 // Limit is in current buffer.
1991 bufferSizeAfterLimit = bufferEnd - currentLimit;
1992 limit -= bufferSizeAfterLimit;
1994 bufferSizeAfterLimit = 0;
1998 private int remaining() {
1999 return (int) (limit - pos);
2002 private int bufferPos(long pos) {
2003 return (int) (pos - address);
2006 private ByteBuffer slice(long begin, long end) throws IOException {
2007 int prevPos = buffer.position();
2008 int prevLimit = buffer.limit();
2010 buffer.position(bufferPos(begin));
2011 buffer.limit(bufferPos(end));
2012 return buffer.slice();
2013 } catch (IllegalArgumentException e) {
2014 throw InvalidProtocolBufferException.truncatedMessage();
2016 buffer.position(prevPos);
2017 buffer.limit(prevLimit);
2023 * Implementation of {@link CodedInputStream} that uses an {@link InputStream} as the data source.
2025 private static final class StreamDecoder extends CodedInputStream {
2026 private final InputStream input;
2027 private final byte[] buffer;
2028 /** bufferSize represents how many bytes are currently filled in the buffer */
2029 private int bufferSize;
2031 private int bufferSizeAfterLimit;
2033 private int lastTag;
2036 * The total number of bytes read before the current buffer. The total bytes read up to the
2037 * current position can be computed as {@code totalBytesRetired + pos}. This value may be
2038 * negative if reading started in the middle of the current buffer (e.g. if the constructor that
2039 * takes a byte array and an offset was used).
2041 private int totalBytesRetired;
2043 /** The absolute position of the end of the current message. */
2044 private int currentLimit = Integer.MAX_VALUE;
2046 private StreamDecoder(final InputStream input, int bufferSize) {
2047 checkNotNull(input, "input");
2049 this.buffer = new byte[bufferSize];
2050 this.bufferSize = 0;
2052 totalBytesRetired = 0;
2056 public int readTag() throws IOException {
2062 lastTag = readRawVarint32();
2063 if (WireFormat.getTagFieldNumber(lastTag) == 0) {
2064 // If we actually read zero (or any tag number corresponding to field
2065 // number zero), that's not a valid tag.
2066 throw InvalidProtocolBufferException.invalidTag();
2072 public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
2073 if (lastTag != value) {
2074 throw InvalidProtocolBufferException.invalidEndTag();
2079 public int getLastTag() {
2084 public boolean skipField(final int tag) throws IOException {
2085 switch (WireFormat.getTagWireType(tag)) {
2086 case WireFormat.WIRETYPE_VARINT:
2089 case WireFormat.WIRETYPE_FIXED64:
2090 skipRawBytes(FIXED64_SIZE);
2092 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
2093 skipRawBytes(readRawVarint32());
2095 case WireFormat.WIRETYPE_START_GROUP:
2098 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
2100 case WireFormat.WIRETYPE_END_GROUP:
2102 case WireFormat.WIRETYPE_FIXED32:
2103 skipRawBytes(FIXED32_SIZE);
2106 throw InvalidProtocolBufferException.invalidWireType();
2111 public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
2112 switch (WireFormat.getTagWireType(tag)) {
2113 case WireFormat.WIRETYPE_VARINT:
2115 long value = readInt64();
2116 output.writeRawVarint32(tag);
2117 output.writeUInt64NoTag(value);
2120 case WireFormat.WIRETYPE_FIXED64:
2122 long value = readRawLittleEndian64();
2123 output.writeRawVarint32(tag);
2124 output.writeFixed64NoTag(value);
2127 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
2129 ByteString value = readBytes();
2130 output.writeRawVarint32(tag);
2131 output.writeBytesNoTag(value);
2134 case WireFormat.WIRETYPE_START_GROUP:
2136 output.writeRawVarint32(tag);
2137 skipMessage(output);
2140 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
2141 checkLastTagWas(endtag);
2142 output.writeRawVarint32(endtag);
2145 case WireFormat.WIRETYPE_END_GROUP:
2149 case WireFormat.WIRETYPE_FIXED32:
2151 int value = readRawLittleEndian32();
2152 output.writeRawVarint32(tag);
2153 output.writeFixed32NoTag(value);
2157 throw InvalidProtocolBufferException.invalidWireType();
2162 public void skipMessage() throws IOException {
2164 final int tag = readTag();
2165 if (tag == 0 || !skipField(tag)) {
2172 public void skipMessage(CodedOutputStream output) throws IOException {
2174 final int tag = readTag();
2175 if (tag == 0 || !skipField(tag, output)) {
2181 /** Collects the bytes skipped and returns the data in a ByteBuffer. */
2182 private class SkippedDataSink implements RefillCallback {
2183 private int lastPos = pos;
2184 private ByteArrayOutputStream byteArrayStream;
2187 public void onRefill() {
2188 if (byteArrayStream == null) {
2189 byteArrayStream = new ByteArrayOutputStream();
2191 byteArrayStream.write(buffer, lastPos, pos - lastPos);
2195 /** Gets skipped data in a ByteBuffer. This method should only be called once. */
2196 ByteBuffer getSkippedData() {
2197 if (byteArrayStream == null) {
2198 return ByteBuffer.wrap(buffer, lastPos, pos - lastPos);
2200 byteArrayStream.write(buffer, lastPos, pos);
2201 return ByteBuffer.wrap(byteArrayStream.toByteArray());
2207 // -----------------------------------------------------------------
2210 public double readDouble() throws IOException {
2211 return Double.longBitsToDouble(readRawLittleEndian64());
2215 public float readFloat() throws IOException {
2216 return Float.intBitsToFloat(readRawLittleEndian32());
2220 public long readUInt64() throws IOException {
2221 return readRawVarint64();
2225 public long readInt64() throws IOException {
2226 return readRawVarint64();
2230 public int readInt32() throws IOException {
2231 return readRawVarint32();
2235 public long readFixed64() throws IOException {
2236 return readRawLittleEndian64();
2240 public int readFixed32() throws IOException {
2241 return readRawLittleEndian32();
2245 public boolean readBool() throws IOException {
2246 return readRawVarint64() != 0;
2250 public String readString() throws IOException {
2251 final int size = readRawVarint32();
2252 if (size > 0 && size <= (bufferSize - pos)) {
2253 // Fast path: We already have the bytes in a contiguous buffer, so
2254 // just copy directly from it.
2255 final String result = new String(buffer, pos, size, UTF_8);
2262 if (size <= bufferSize) {
2264 String result = new String(buffer, pos, size, UTF_8);
2268 // Slow path: Build a byte array first then copy it.
2269 return new String(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false), UTF_8);
2273 public String readStringRequireUtf8() throws IOException {
2274 final int size = readRawVarint32();
2276 final int oldPos = pos;
2278 if (size <= (bufferSize - oldPos) && size > 0) {
2279 // Fast path: We already have the bytes in a contiguous buffer, so
2280 // just copy directly from it.
2282 pos = oldPos + size;
2284 } else if (size == 0) {
2286 } else if (size <= bufferSize) {
2290 pos = tempPos + size;
2292 // Slow path: Build a byte array first then copy it.
2293 bytes = readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false);
2296 return Utf8.decodeUtf8(bytes, tempPos, size);
2300 public void readGroup(
2301 final int fieldNumber,
2302 final MessageLite.Builder builder,
2303 final ExtensionRegistryLite extensionRegistry)
2304 throws IOException {
2305 if (recursionDepth >= recursionLimit) {
2306 throw InvalidProtocolBufferException.recursionLimitExceeded();
2309 builder.mergeFrom(this, extensionRegistry);
2310 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
2316 public <T extends MessageLite> T readGroup(
2317 final int fieldNumber,
2318 final Parser<T> parser,
2319 final ExtensionRegistryLite extensionRegistry)
2320 throws IOException {
2321 if (recursionDepth >= recursionLimit) {
2322 throw InvalidProtocolBufferException.recursionLimitExceeded();
2325 T result = parser.parsePartialFrom(this, extensionRegistry);
2326 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
2333 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
2334 throws IOException {
2335 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
2339 public void readMessage(
2340 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
2341 throws IOException {
2342 final int length = readRawVarint32();
2343 if (recursionDepth >= recursionLimit) {
2344 throw InvalidProtocolBufferException.recursionLimitExceeded();
2346 final int oldLimit = pushLimit(length);
2348 builder.mergeFrom(this, extensionRegistry);
2356 public <T extends MessageLite> T readMessage(
2357 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
2358 int length = readRawVarint32();
2359 if (recursionDepth >= recursionLimit) {
2360 throw InvalidProtocolBufferException.recursionLimitExceeded();
2362 final int oldLimit = pushLimit(length);
2364 T result = parser.parsePartialFrom(this, extensionRegistry);
2372 public ByteString readBytes() throws IOException {
2373 final int size = readRawVarint32();
2374 if (size <= (bufferSize - pos) && size > 0) {
2375 // Fast path: We already have the bytes in a contiguous buffer, so
2376 // just copy directly from it.
2377 final ByteString result = ByteString.copyFrom(buffer, pos, size);
2382 return ByteString.EMPTY;
2384 return readBytesSlowPath(size);
2388 public byte[] readByteArray() throws IOException {
2389 final int size = readRawVarint32();
2390 if (size <= (bufferSize - pos) && size > 0) {
2391 // Fast path: We already have the bytes in a contiguous buffer, so
2392 // just copy directly from it.
2393 final byte[] result = Arrays.copyOfRange(buffer, pos, pos + size);
2397 // Slow path: Build a byte array first then copy it.
2398 // TODO(dweis): Do we want to protect from malicious input streams here?
2399 return readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false);
2404 public ByteBuffer readByteBuffer() throws IOException {
2405 final int size = readRawVarint32();
2406 if (size <= (bufferSize - pos) && size > 0) {
2407 // Fast path: We already have the bytes in a contiguous buffer.
2408 ByteBuffer result = ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size));
2413 return Internal.EMPTY_BYTE_BUFFER;
2415 // Slow path: Build a byte array first then copy it.
2417 // We must copy as the byte array was handed off to the InputStream and a malicious
2418 // implementation could retain a reference.
2419 return ByteBuffer.wrap(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ true));
2423 public int readUInt32() throws IOException {
2424 return readRawVarint32();
2428 public int readEnum() throws IOException {
2429 return readRawVarint32();
2433 public int readSFixed32() throws IOException {
2434 return readRawLittleEndian32();
2438 public long readSFixed64() throws IOException {
2439 return readRawLittleEndian64();
2443 public int readSInt32() throws IOException {
2444 return decodeZigZag32(readRawVarint32());
2448 public long readSInt64() throws IOException {
2449 return decodeZigZag64(readRawVarint64());
2452 // =================================================================
2455 public int readRawVarint32() throws IOException {
2456 // See implementation notes for readRawVarint64
2461 if (bufferSize == tempPos) {
2465 final byte[] buffer = this.buffer;
2467 if ((x = buffer[tempPos++]) >= 0) {
2470 } else if (bufferSize - tempPos < 9) {
2472 } else if ((x ^= (buffer[tempPos++] << 7)) < 0) {
2474 } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) {
2475 x ^= (~0 << 7) ^ (~0 << 14);
2476 } else if ((x ^= (buffer[tempPos++] << 21)) < 0) {
2477 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
2479 int y = buffer[tempPos++];
2481 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
2483 && buffer[tempPos++] < 0
2484 && buffer[tempPos++] < 0
2485 && buffer[tempPos++] < 0
2486 && buffer[tempPos++] < 0
2487 && buffer[tempPos++] < 0) {
2488 break fastpath; // Will throw malformedVarint()
2494 return (int) readRawVarint64SlowPath();
2497 private void skipRawVarint() throws IOException {
2498 if (bufferSize - pos >= MAX_VARINT_SIZE) {
2499 skipRawVarintFastPath();
2501 skipRawVarintSlowPath();
2505 private void skipRawVarintFastPath() throws IOException {
2506 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
2507 if (buffer[pos++] >= 0) {
2511 throw InvalidProtocolBufferException.malformedVarint();
2514 private void skipRawVarintSlowPath() throws IOException {
2515 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
2516 if (readRawByte() >= 0) {
2520 throw InvalidProtocolBufferException.malformedVarint();
2524 public long readRawVarint64() throws IOException {
2525 // Implementation notes:
2527 // Optimized for one-byte values, expected to be common.
2528 // The particular code below was selected from various candidates
2529 // empirically, by winning VarintBenchmark.
2531 // Sign extension of (signed) Java bytes is usually a nuisance, but
2532 // we exploit it here to more easily obtain the sign of bytes read.
2533 // Instead of cleaning up the sign extension bits by masking eagerly,
2534 // we delay until we find the final (positive) byte, when we clear all
2535 // accumulated bits with one xor. We depend on javac to constant fold.
2540 if (bufferSize == tempPos) {
2544 final byte[] buffer = this.buffer;
2547 if ((y = buffer[tempPos++]) >= 0) {
2550 } else if (bufferSize - tempPos < 9) {
2552 } else if ((y ^= (buffer[tempPos++] << 7)) < 0) {
2554 } else if ((y ^= (buffer[tempPos++] << 14)) >= 0) {
2555 x = y ^ ((~0 << 7) ^ (~0 << 14));
2556 } else if ((y ^= (buffer[tempPos++] << 21)) < 0) {
2557 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
2558 } else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) {
2559 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
2560 } else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) {
2561 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
2562 } else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) {
2563 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
2564 } else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) {
2574 x ^= ((long) buffer[tempPos++] << 56);
2585 if (buffer[tempPos++] < 0L) {
2586 break fastpath; // Will throw malformedVarint()
2593 return readRawVarint64SlowPath();
2597 long readRawVarint64SlowPath() throws IOException {
2599 for (int shift = 0; shift < 64; shift += 7) {
2600 final byte b = readRawByte();
2601 result |= (long) (b & 0x7F) << shift;
2602 if ((b & 0x80) == 0) {
2606 throw InvalidProtocolBufferException.malformedVarint();
2610 public int readRawLittleEndian32() throws IOException {
2613 if (bufferSize - tempPos < FIXED32_SIZE) {
2614 refillBuffer(FIXED32_SIZE);
2618 final byte[] buffer = this.buffer;
2619 pos = tempPos + FIXED32_SIZE;
2620 return (((buffer[tempPos] & 0xff))
2621 | ((buffer[tempPos + 1] & 0xff) << 8)
2622 | ((buffer[tempPos + 2] & 0xff) << 16)
2623 | ((buffer[tempPos + 3] & 0xff) << 24));
2627 public long readRawLittleEndian64() throws IOException {
2630 if (bufferSize - tempPos < FIXED64_SIZE) {
2631 refillBuffer(FIXED64_SIZE);
2635 final byte[] buffer = this.buffer;
2636 pos = tempPos + FIXED64_SIZE;
2637 return (((buffer[tempPos] & 0xffL))
2638 | ((buffer[tempPos + 1] & 0xffL) << 8)
2639 | ((buffer[tempPos + 2] & 0xffL) << 16)
2640 | ((buffer[tempPos + 3] & 0xffL) << 24)
2641 | ((buffer[tempPos + 4] & 0xffL) << 32)
2642 | ((buffer[tempPos + 5] & 0xffL) << 40)
2643 | ((buffer[tempPos + 6] & 0xffL) << 48)
2644 | ((buffer[tempPos + 7] & 0xffL) << 56));
2647 // -----------------------------------------------------------------
2650 public void enableAliasing(boolean enabled) {
2651 // TODO(nathanmittler): Ideally we should throw here. Do nothing for backward compatibility.
2655 public void resetSizeCounter() {
2656 totalBytesRetired = -pos;
2660 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
2661 if (byteLimit < 0) {
2662 throw InvalidProtocolBufferException.negativeSize();
2664 byteLimit += totalBytesRetired + pos;
2665 final int oldLimit = currentLimit;
2666 if (byteLimit > oldLimit) {
2667 throw InvalidProtocolBufferException.truncatedMessage();
2669 currentLimit = byteLimit;
2671 recomputeBufferSizeAfterLimit();
2676 private void recomputeBufferSizeAfterLimit() {
2677 bufferSize += bufferSizeAfterLimit;
2678 final int bufferEnd = totalBytesRetired + bufferSize;
2679 if (bufferEnd > currentLimit) {
2680 // Limit is in current buffer.
2681 bufferSizeAfterLimit = bufferEnd - currentLimit;
2682 bufferSize -= bufferSizeAfterLimit;
2684 bufferSizeAfterLimit = 0;
2689 public void popLimit(final int oldLimit) {
2690 currentLimit = oldLimit;
2691 recomputeBufferSizeAfterLimit();
2695 public int getBytesUntilLimit() {
2696 if (currentLimit == Integer.MAX_VALUE) {
2700 final int currentAbsolutePosition = totalBytesRetired + pos;
2701 return currentLimit - currentAbsolutePosition;
2705 public boolean isAtEnd() throws IOException {
2706 return pos == bufferSize && !tryRefillBuffer(1);
2710 public int getTotalBytesRead() {
2711 return totalBytesRetired + pos;
2714 private interface RefillCallback {
2718 private RefillCallback refillCallback = null;
2721 * Reads more bytes from the input, making at least {@code n} bytes available in the buffer.
2722 * Caller must ensure that the requested space is not yet available, and that the requested
2723 * space is less than BUFFER_SIZE.
2725 * @throws InvalidProtocolBufferException The end of the stream or the current limit was
2728 private void refillBuffer(int n) throws IOException {
2729 if (!tryRefillBuffer(n)) {
2730 // We have to distinguish the exception between sizeLimitExceeded and truncatedMessage. So
2731 // we just throw an sizeLimitExceeded exception here if it exceeds the sizeLimit
2732 if (n > sizeLimit - totalBytesRetired - pos) {
2733 throw InvalidProtocolBufferException.sizeLimitExceeded();
2735 throw InvalidProtocolBufferException.truncatedMessage();
2741 * Tries to read more bytes from the input, making at least {@code n} bytes available in the
2742 * buffer. Caller must ensure that the requested space is not yet available, and that the
2743 * requested space is less than BUFFER_SIZE.
2745 * @return {@code true} If the bytes could be made available; {@code false} 1. Current at the
2746 * end of the stream 2. The current limit was reached 3. The total size limit was reached
2748 private boolean tryRefillBuffer(int n) throws IOException {
2749 if (pos + n <= bufferSize) {
2750 throw new IllegalStateException(
2751 "refillBuffer() called when " + n + " bytes were already available in buffer");
2754 // Check whether the size of total message needs to read is bigger than the size limit.
2755 // We shouldn't throw an exception here as isAtEnd() function needs to get this function's
2756 // return as the result.
2757 if (n > sizeLimit - totalBytesRetired - pos) {
2761 // Shouldn't throw the exception here either.
2762 if (totalBytesRetired + pos + n > currentLimit) {
2763 // Oops, we hit a limit.
2767 if (refillCallback != null) {
2768 refillCallback.onRefill();
2773 if (bufferSize > tempPos) {
2774 System.arraycopy(buffer, tempPos, buffer, 0, bufferSize - tempPos);
2776 totalBytesRetired += tempPos;
2777 bufferSize -= tempPos;
2781 // Here we should refill the buffer as many bytes as possible.
2787 // the size of allocated but unused bytes in the buffer
2788 buffer.length - bufferSize,
2789 // do not exceed the total bytes limit
2790 sizeLimit - totalBytesRetired - bufferSize));
2791 if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
2792 throw new IllegalStateException(
2794 + "#read(byte[]) returned invalid result: "
2796 + "\nThe InputStream implementation is buggy.");
2798 if (bytesRead > 0) {
2799 bufferSize += bytesRead;
2800 recomputeBufferSizeAfterLimit();
2801 return (bufferSize >= n) ? true : tryRefillBuffer(n);
2808 public byte readRawByte() throws IOException {
2809 if (pos == bufferSize) {
2812 return buffer[pos++];
2816 public byte[] readRawBytes(final int size) throws IOException {
2817 final int tempPos = pos;
2818 if (size <= (bufferSize - tempPos) && size > 0) {
2819 pos = tempPos + size;
2820 return Arrays.copyOfRange(buffer, tempPos, tempPos + size);
2822 // TODO(dweis): Do we want to protect from malicious input streams here?
2823 return readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false);
2828 * Exactly like readRawBytes, but caller must have already checked the fast path: (size <=
2829 * (bufferSize - pos) && size > 0)
2831 * If ensureNoLeakedReferences is true, the value is guaranteed to have not escaped to
2834 private byte[] readRawBytesSlowPath(
2835 final int size, boolean ensureNoLeakedReferences) throws IOException {
2836 // Attempt to read the data in one byte array when it's safe to do.
2837 byte[] result = readRawBytesSlowPathOneChunk(size);
2838 if (result != null) {
2839 return ensureNoLeakedReferences ? result.clone() : result;
2842 final int originalBufferPos = pos;
2843 final int bufferedBytes = bufferSize - pos;
2845 // Mark the current buffer consumed.
2846 totalBytesRetired += bufferSize;
2850 // Determine the number of bytes we need to read from the input stream.
2851 int sizeLeft = size - bufferedBytes;
2853 // The size is very large. For security reasons we read them in small
2855 List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
2857 // OK, got everything. Now concatenate it all into one buffer.
2858 final byte[] bytes = new byte[size];
2860 // Start by copying the leftover bytes from this.buffer.
2861 System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
2863 // And now all the chunks.
2864 int tempPos = bufferedBytes;
2865 for (final byte[] chunk : chunks) {
2866 System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
2867 tempPos += chunk.length;
2875 * Attempts to read the data in one byte array when it's safe to do. Returns null if the size to
2876 * read is too large and needs to be allocated in smaller chunks for security reasons.
2878 * Returns a byte[] that may have escaped to user code via InputStream APIs.
2880 private byte[] readRawBytesSlowPathOneChunk(final int size) throws IOException {
2882 return Internal.EMPTY_BYTE_ARRAY;
2885 throw InvalidProtocolBufferException.negativeSize();
2888 // Integer-overflow-conscious check that the message size so far has not exceeded sizeLimit.
2889 int currentMessageSize = totalBytesRetired + pos + size;
2890 if (currentMessageSize - sizeLimit > 0) {
2891 throw InvalidProtocolBufferException.sizeLimitExceeded();
2894 // Verify that the message size so far has not exceeded currentLimit.
2895 if (currentMessageSize > currentLimit) {
2896 // Read to the end of the stream anyway.
2897 skipRawBytes(currentLimit - totalBytesRetired - pos);
2898 throw InvalidProtocolBufferException.truncatedMessage();
2901 final int bufferedBytes = bufferSize - pos;
2902 // Determine the number of bytes we need to read from the input stream.
2903 int sizeLeft = size - bufferedBytes;
2904 // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_SIZE.
2905 if (sizeLeft < DEFAULT_BUFFER_SIZE || sizeLeft <= input.available()) {
2906 // Either the bytes we need are known to be available, or the required buffer is
2907 // within an allowed threshold - go ahead and allocate the buffer now.
2908 final byte[] bytes = new byte[size];
2910 // Copy all of the buffered bytes to the result buffer.
2911 System.arraycopy(buffer, pos, bytes, 0, bufferedBytes);
2912 totalBytesRetired += bufferSize;
2916 // Fill the remaining bytes from the input stream.
2917 int tempPos = bufferedBytes;
2918 while (tempPos < bytes.length) {
2919 int n = input.read(bytes, tempPos, size - tempPos);
2921 throw InvalidProtocolBufferException.truncatedMessage();
2923 totalBytesRetired += n;
2934 * Reads the remaining data in small chunks from the input stream.
2936 * Returns a byte[] that may have escaped to user code via InputStream APIs.
2938 private List<byte[]> readRawBytesSlowPathRemainingChunks(int sizeLeft) throws IOException {
2939 // The size is very large. For security reasons, we can't allocate the
2940 // entire byte array yet. The size comes directly from the input, so a
2941 // maliciously-crafted message could provide a bogus very large size in
2942 // order to trick the app into allocating a lot of memory. We avoid this
2943 // by allocating and reading only a small chunk at a time, so that the
2944 // malicious message must actually *be* extremely large to cause
2945 // problems. Meanwhile, we limit the allowed size of a message elsewhere.
2946 final List<byte[]> chunks = new ArrayList<byte[]>();
2948 while (sizeLeft > 0) {
2949 // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_SIZE.
2950 final byte[] chunk = new byte[Math.min(sizeLeft, DEFAULT_BUFFER_SIZE)];
2952 while (tempPos < chunk.length) {
2953 final int n = input.read(chunk, tempPos, chunk.length - tempPos);
2955 throw InvalidProtocolBufferException.truncatedMessage();
2957 totalBytesRetired += n;
2960 sizeLeft -= chunk.length;
2968 * Like readBytes, but caller must have already checked the fast path: (size <= (bufferSize -
2969 * pos) && size > 0 || size == 0)
2971 private ByteString readBytesSlowPath(final int size) throws IOException {
2972 final byte[] result = readRawBytesSlowPathOneChunk(size);
2973 if (result != null) {
2974 // We must copy as the byte array was handed off to the InputStream and a malicious
2975 // implementation could retain a reference.
2976 return ByteString.copyFrom(result);
2979 final int originalBufferPos = pos;
2980 final int bufferedBytes = bufferSize - pos;
2982 // Mark the current buffer consumed.
2983 totalBytesRetired += bufferSize;
2987 // Determine the number of bytes we need to read from the input stream.
2988 int sizeLeft = size - bufferedBytes;
2990 // The size is very large. For security reasons we read them in small
2992 List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
2994 // OK, got everything. Now concatenate it all into one buffer.
2995 final byte[] bytes = new byte[size];
2997 // Start by copying the leftover bytes from this.buffer.
2998 System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
3000 // And now all the chunks.
3001 int tempPos = bufferedBytes;
3002 for (final byte[] chunk : chunks) {
3003 System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
3004 tempPos += chunk.length;
3007 return ByteString.wrap(bytes);
3011 public void skipRawBytes(final int size) throws IOException {
3012 if (size <= (bufferSize - pos) && size >= 0) {
3013 // We have all the bytes we need already.
3016 skipRawBytesSlowPath(size);
3021 * Exactly like skipRawBytes, but caller must have already checked the fast path: (size <=
3022 * (bufferSize - pos) && size >= 0)
3024 private void skipRawBytesSlowPath(final int size) throws IOException {
3026 throw InvalidProtocolBufferException.negativeSize();
3029 if (totalBytesRetired + pos + size > currentLimit) {
3030 // Read to the end of the stream anyway.
3031 skipRawBytes(currentLimit - totalBytesRetired - pos);
3033 throw InvalidProtocolBufferException.truncatedMessage();
3036 int totalSkipped = 0;
3037 if (refillCallback == null) {
3038 // Skipping more bytes than are in the buffer. First skip what we have.
3039 totalBytesRetired += pos;
3040 totalSkipped = bufferSize - pos;
3045 while (totalSkipped < size) {
3046 int toSkip = size - totalSkipped;
3047 long skipped = input.skip(toSkip);
3048 if (skipped < 0 || skipped > toSkip) {
3049 throw new IllegalStateException(
3051 + "#skip returned invalid result: "
3053 + "\nThe InputStream implementation is buggy.");
3054 } else if (skipped == 0) {
3055 // The API contract of skip() permits an inputstream to skip zero bytes for any reason
3056 // it wants. In particular, ByteArrayInputStream will just return zero over and over
3057 // when it's at the end of its input. In order to actually confirm that we've hit the
3058 // end of input, we need to issue a read call via the other path.
3061 totalSkipped += (int) skipped;
3064 totalBytesRetired += totalSkipped;
3065 recomputeBufferSizeAfterLimit();
3068 if (totalSkipped < size) {
3069 // Skipping more bytes than are in the buffer. First skip what we have.
3070 int tempPos = bufferSize - pos;
3073 // Keep refilling the buffer until we get to the point we wanted to skip to.
3074 // This has the side effect of ensuring the limits are updated correctly.
3076 while (size - tempPos > bufferSize) {
3077 tempPos += bufferSize;
3082 pos = size - tempPos;
3088 * Implementation of {@link CodedInputStream} that uses an {@link Iterable <ByteBuffer>} as the
3089 * data source. Requires the use of {@code sun.misc.Unsafe} to perform fast reads on the buffer.
3091 private static final class IterableDirectByteBufferDecoder extends CodedInputStream {
3092 /** The object that need to decode. */
3093 private Iterable<ByteBuffer> input;
3094 /** The {@link Iterator} with type {@link ByteBuffer} of {@code input} */
3095 private Iterator<ByteBuffer> iterator;
3096 /** The current ByteBuffer; */
3097 private ByteBuffer currentByteBuffer;
3099 * If {@code true}, indicates that all the buffer are backing a {@link ByteString} and are
3100 * therefore considered to be an immutable input source.
3102 private boolean immutable;
3104 * If {@code true}, indicates that calls to read {@link ByteString} or {@code byte[]}
3105 * <strong>may</strong> return slices of the underlying buffer, rather than copies.
3107 private boolean enableAliasing;
3108 /** The global total message length limit */
3109 private int totalBufferSize;
3110 /** The amount of available data in the input beyond {@link #currentLimit}. */
3111 private int bufferSizeAfterCurrentLimit;
3112 /** The absolute position of the end of the current message. */
3113 private int currentLimit = Integer.MAX_VALUE;
3114 /** The last tag that was read from this stream. */
3115 private int lastTag;
3116 /** Total Bytes have been Read from the {@link Iterable} {@link ByteBuffer} */
3117 private int totalBytesRead;
3118 /** The start position offset of the whole message, used as to reset the totalBytesRead */
3119 private int startOffset;
3120 /** The current position for current ByteBuffer */
3121 private long currentByteBufferPos;
3123 private long currentByteBufferStartPos;
3125 * If the current ByteBuffer is unsafe-direct based, currentAddress is the start address of this
3126 * ByteBuffer; otherwise should be zero.
3128 private long currentAddress;
3129 /** The limit position for current ByteBuffer */
3130 private long currentByteBufferLimit;
3133 * The constructor of {@code Iterable<ByteBuffer>} decoder.
3135 * @param inputBufs The input data.
3136 * @param size The total size of the input data.
3137 * @param immutableFlag whether the input data is immutable.
3139 private IterableDirectByteBufferDecoder(
3140 Iterable<ByteBuffer> inputBufs, int size, boolean immutableFlag) {
3141 totalBufferSize = size;
3143 iterator = input.iterator();
3144 immutable = immutableFlag;
3145 startOffset = totalBytesRead = 0;
3147 currentByteBuffer = EMPTY_BYTE_BUFFER;
3148 currentByteBufferPos = 0;
3149 currentByteBufferStartPos = 0;
3150 currentByteBufferLimit = 0;
3153 tryGetNextByteBuffer();
3157 /** To get the next ByteBuffer from {@code input}, and then update the parameters */
3158 private void getNextByteBuffer() throws InvalidProtocolBufferException {
3159 if (!iterator.hasNext()) {
3160 throw InvalidProtocolBufferException.truncatedMessage();
3162 tryGetNextByteBuffer();
3165 private void tryGetNextByteBuffer() {
3166 currentByteBuffer = iterator.next();
3167 totalBytesRead += (int) (currentByteBufferPos - currentByteBufferStartPos);
3168 currentByteBufferPos = currentByteBuffer.position();
3169 currentByteBufferStartPos = currentByteBufferPos;
3170 currentByteBufferLimit = currentByteBuffer.limit();
3171 currentAddress = UnsafeUtil.addressOffset(currentByteBuffer);
3172 currentByteBufferPos += currentAddress;
3173 currentByteBufferStartPos += currentAddress;
3174 currentByteBufferLimit += currentAddress;
3178 public int readTag() throws IOException {
3184 lastTag = readRawVarint32();
3185 if (WireFormat.getTagFieldNumber(lastTag) == 0) {
3186 // If we actually read zero (or any tag number corresponding to field
3187 // number zero), that's not a valid tag.
3188 throw InvalidProtocolBufferException.invalidTag();
3194 public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
3195 if (lastTag != value) {
3196 throw InvalidProtocolBufferException.invalidEndTag();
3201 public int getLastTag() {
3206 public boolean skipField(final int tag) throws IOException {
3207 switch (WireFormat.getTagWireType(tag)) {
3208 case WireFormat.WIRETYPE_VARINT:
3211 case WireFormat.WIRETYPE_FIXED64:
3212 skipRawBytes(FIXED64_SIZE);
3214 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
3215 skipRawBytes(readRawVarint32());
3217 case WireFormat.WIRETYPE_START_GROUP:
3220 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
3222 case WireFormat.WIRETYPE_END_GROUP:
3224 case WireFormat.WIRETYPE_FIXED32:
3225 skipRawBytes(FIXED32_SIZE);
3228 throw InvalidProtocolBufferException.invalidWireType();
3233 public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
3234 switch (WireFormat.getTagWireType(tag)) {
3235 case WireFormat.WIRETYPE_VARINT:
3237 long value = readInt64();
3238 output.writeRawVarint32(tag);
3239 output.writeUInt64NoTag(value);
3242 case WireFormat.WIRETYPE_FIXED64:
3244 long value = readRawLittleEndian64();
3245 output.writeRawVarint32(tag);
3246 output.writeFixed64NoTag(value);
3249 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
3251 ByteString value = readBytes();
3252 output.writeRawVarint32(tag);
3253 output.writeBytesNoTag(value);
3256 case WireFormat.WIRETYPE_START_GROUP:
3258 output.writeRawVarint32(tag);
3259 skipMessage(output);
3262 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
3263 checkLastTagWas(endtag);
3264 output.writeRawVarint32(endtag);
3267 case WireFormat.WIRETYPE_END_GROUP:
3271 case WireFormat.WIRETYPE_FIXED32:
3273 int value = readRawLittleEndian32();
3274 output.writeRawVarint32(tag);
3275 output.writeFixed32NoTag(value);
3279 throw InvalidProtocolBufferException.invalidWireType();
3284 public void skipMessage() throws IOException {
3286 final int tag = readTag();
3287 if (tag == 0 || !skipField(tag)) {
3294 public void skipMessage(CodedOutputStream output) throws IOException {
3296 final int tag = readTag();
3297 if (tag == 0 || !skipField(tag, output)) {
3303 // -----------------------------------------------------------------
3306 public double readDouble() throws IOException {
3307 return Double.longBitsToDouble(readRawLittleEndian64());
3311 public float readFloat() throws IOException {
3312 return Float.intBitsToFloat(readRawLittleEndian32());
3316 public long readUInt64() throws IOException {
3317 return readRawVarint64();
3321 public long readInt64() throws IOException {
3322 return readRawVarint64();
3326 public int readInt32() throws IOException {
3327 return readRawVarint32();
3331 public long readFixed64() throws IOException {
3332 return readRawLittleEndian64();
3336 public int readFixed32() throws IOException {
3337 return readRawLittleEndian32();
3341 public boolean readBool() throws IOException {
3342 return readRawVarint64() != 0;
3346 public String readString() throws IOException {
3347 final int size = readRawVarint32();
3348 if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) {
3349 byte[] bytes = new byte[size];
3350 UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size);
3351 String result = new String(bytes, UTF_8);
3352 currentByteBufferPos += size;
3354 } else if (size > 0 && size <= remaining()) {
3355 // TODO(yilunchong): To use an underlying bytes[] instead of allocating a new bytes[]
3356 byte[] bytes = new byte[size];
3357 readRawBytesTo(bytes, 0, size);
3358 String result = new String(bytes, UTF_8);
3366 throw InvalidProtocolBufferException.negativeSize();
3368 throw InvalidProtocolBufferException.truncatedMessage();
3372 public String readStringRequireUtf8() throws IOException {
3373 final int size = readRawVarint32();
3374 if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) {
3375 final int bufferPos = (int) (currentByteBufferPos - currentByteBufferStartPos);
3376 String result = Utf8.decodeUtf8(currentByteBuffer, bufferPos, size);
3377 currentByteBufferPos += size;
3380 if (size >= 0 && size <= remaining()) {
3381 byte[] bytes = new byte[size];
3382 readRawBytesTo(bytes, 0, size);
3383 return Utf8.decodeUtf8(bytes, 0, size);
3390 throw InvalidProtocolBufferException.negativeSize();
3392 throw InvalidProtocolBufferException.truncatedMessage();
3396 public void readGroup(
3397 final int fieldNumber,
3398 final MessageLite.Builder builder,
3399 final ExtensionRegistryLite extensionRegistry)
3400 throws IOException {
3401 if (recursionDepth >= recursionLimit) {
3402 throw InvalidProtocolBufferException.recursionLimitExceeded();
3405 builder.mergeFrom(this, extensionRegistry);
3406 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
3412 public <T extends MessageLite> T readGroup(
3413 final int fieldNumber,
3414 final Parser<T> parser,
3415 final ExtensionRegistryLite extensionRegistry)
3416 throws IOException {
3417 if (recursionDepth >= recursionLimit) {
3418 throw InvalidProtocolBufferException.recursionLimitExceeded();
3421 T result = parser.parsePartialFrom(this, extensionRegistry);
3422 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
3429 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
3430 throws IOException {
3431 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
3435 public void readMessage(
3436 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
3437 throws IOException {
3438 final int length = readRawVarint32();
3439 if (recursionDepth >= recursionLimit) {
3440 throw InvalidProtocolBufferException.recursionLimitExceeded();
3442 final int oldLimit = pushLimit(length);
3444 builder.mergeFrom(this, extensionRegistry);
3452 public <T extends MessageLite> T readMessage(
3453 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
3454 int length = readRawVarint32();
3455 if (recursionDepth >= recursionLimit) {
3456 throw InvalidProtocolBufferException.recursionLimitExceeded();
3458 final int oldLimit = pushLimit(length);
3460 T result = parser.parsePartialFrom(this, extensionRegistry);
3468 public ByteString readBytes() throws IOException {
3469 final int size = readRawVarint32();
3470 if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) {
3471 if (immutable && enableAliasing) {
3472 final int idx = (int) (currentByteBufferPos - currentAddress);
3473 final ByteString result = ByteString.wrap(slice(idx, idx + size));
3474 currentByteBufferPos += size;
3478 bytes = new byte[size];
3479 UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size);
3480 currentByteBufferPos += size;
3481 return ByteString.wrap(bytes);
3483 } else if (size > 0 && size <= remaining()) {
3484 byte[] temp = new byte[size];
3485 readRawBytesTo(temp, 0, size);
3486 return ByteString.wrap(temp);
3490 return ByteString.EMPTY;
3493 throw InvalidProtocolBufferException.negativeSize();
3495 throw InvalidProtocolBufferException.truncatedMessage();
3499 public byte[] readByteArray() throws IOException {
3500 return readRawBytes(readRawVarint32());
3504 public ByteBuffer readByteBuffer() throws IOException {
3505 final int size = readRawVarint32();
3506 if (size > 0 && size <= currentRemaining()) {
3507 if (!immutable && enableAliasing) {
3508 currentByteBufferPos += size;
3510 (int) (currentByteBufferPos - currentAddress - size),
3511 (int) (currentByteBufferPos - currentAddress));
3513 byte[] bytes = new byte[size];
3514 UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size);
3515 currentByteBufferPos += size;
3516 return ByteBuffer.wrap(bytes);
3518 } else if (size > 0 && size <= remaining()) {
3519 byte[] temp = new byte[size];
3520 readRawBytesTo(temp, 0, size);
3521 return ByteBuffer.wrap(temp);
3525 return EMPTY_BYTE_BUFFER;
3528 throw InvalidProtocolBufferException.negativeSize();
3530 throw InvalidProtocolBufferException.truncatedMessage();
3534 public int readUInt32() throws IOException {
3535 return readRawVarint32();
3539 public int readEnum() throws IOException {
3540 return readRawVarint32();
3544 public int readSFixed32() throws IOException {
3545 return readRawLittleEndian32();
3549 public long readSFixed64() throws IOException {
3550 return readRawLittleEndian64();
3554 public int readSInt32() throws IOException {
3555 return decodeZigZag32(readRawVarint32());
3559 public long readSInt64() throws IOException {
3560 return decodeZigZag64(readRawVarint64());
3564 public int readRawVarint32() throws IOException {
3567 long tempPos = currentByteBufferPos;
3569 if (currentByteBufferLimit == currentByteBufferPos) {
3574 if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) {
3575 currentByteBufferPos++;
3577 } else if (currentByteBufferLimit - currentByteBufferPos < 10) {
3579 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
3581 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
3582 x ^= (~0 << 7) ^ (~0 << 14);
3583 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
3584 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
3586 int y = UnsafeUtil.getByte(tempPos++);
3588 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
3590 && UnsafeUtil.getByte(tempPos++) < 0
3591 && UnsafeUtil.getByte(tempPos++) < 0
3592 && UnsafeUtil.getByte(tempPos++) < 0
3593 && UnsafeUtil.getByte(tempPos++) < 0
3594 && UnsafeUtil.getByte(tempPos++) < 0) {
3595 break fastpath; // Will throw malformedVarint()
3598 currentByteBufferPos = tempPos;
3601 return (int) readRawVarint64SlowPath();
3605 public long readRawVarint64() throws IOException {
3608 long tempPos = currentByteBufferPos;
3610 if (currentByteBufferLimit == currentByteBufferPos) {
3616 if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) {
3617 currentByteBufferPos++;
3619 } else if (currentByteBufferLimit - currentByteBufferPos < 10) {
3621 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
3623 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
3624 x = y ^ ((~0 << 7) ^ (~0 << 14));
3625 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
3626 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
3627 } else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) {
3628 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
3629 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) {
3630 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
3631 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) {
3632 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
3633 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) {
3643 x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56);
3654 if (UnsafeUtil.getByte(tempPos++) < 0L) {
3655 break fastpath; // Will throw malformedVarint()
3659 currentByteBufferPos = tempPos;
3662 return readRawVarint64SlowPath();
3666 long readRawVarint64SlowPath() throws IOException {
3668 for (int shift = 0; shift < 64; shift += 7) {
3669 final byte b = readRawByte();
3670 result |= (long) (b & 0x7F) << shift;
3671 if ((b & 0x80) == 0) {
3675 throw InvalidProtocolBufferException.malformedVarint();
3679 public int readRawLittleEndian32() throws IOException {
3680 if (currentRemaining() >= FIXED32_SIZE) {
3681 long tempPos = currentByteBufferPos;
3682 currentByteBufferPos += FIXED32_SIZE;
3683 return (((UnsafeUtil.getByte(tempPos) & 0xff))
3684 | ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8)
3685 | ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16)
3686 | ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24));
3688 return ((readRawByte() & 0xff)
3689 | ((readRawByte() & 0xff) << 8)
3690 | ((readRawByte() & 0xff) << 16)
3691 | ((readRawByte() & 0xff) << 24));
3695 public long readRawLittleEndian64() throws IOException {
3696 if (currentRemaining() >= FIXED64_SIZE) {
3697 long tempPos = currentByteBufferPos;
3698 currentByteBufferPos += FIXED64_SIZE;
3699 return (((UnsafeUtil.getByte(tempPos) & 0xffL))
3700 | ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8)
3701 | ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16)
3702 | ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24)
3703 | ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32)
3704 | ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40)
3705 | ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48)
3706 | ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56));
3708 return ((readRawByte() & 0xffL)
3709 | ((readRawByte() & 0xffL) << 8)
3710 | ((readRawByte() & 0xffL) << 16)
3711 | ((readRawByte() & 0xffL) << 24)
3712 | ((readRawByte() & 0xffL) << 32)
3713 | ((readRawByte() & 0xffL) << 40)
3714 | ((readRawByte() & 0xffL) << 48)
3715 | ((readRawByte() & 0xffL) << 56));
3719 public void enableAliasing(boolean enabled) {
3720 this.enableAliasing = enabled;
3724 public void resetSizeCounter() {
3725 startOffset = (int) (totalBytesRead + currentByteBufferPos - currentByteBufferStartPos);
3729 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
3730 if (byteLimit < 0) {
3731 throw InvalidProtocolBufferException.negativeSize();
3733 byteLimit += getTotalBytesRead();
3734 final int oldLimit = currentLimit;
3735 if (byteLimit > oldLimit) {
3736 throw InvalidProtocolBufferException.truncatedMessage();
3738 currentLimit = byteLimit;
3740 recomputeBufferSizeAfterLimit();
3745 private void recomputeBufferSizeAfterLimit() {
3746 totalBufferSize += bufferSizeAfterCurrentLimit;
3747 final int bufferEnd = totalBufferSize - startOffset;
3748 if (bufferEnd > currentLimit) {
3749 // Limit is in current buffer.
3750 bufferSizeAfterCurrentLimit = bufferEnd - currentLimit;
3751 totalBufferSize -= bufferSizeAfterCurrentLimit;
3753 bufferSizeAfterCurrentLimit = 0;
3758 public void popLimit(final int oldLimit) {
3759 currentLimit = oldLimit;
3760 recomputeBufferSizeAfterLimit();
3764 public int getBytesUntilLimit() {
3765 if (currentLimit == Integer.MAX_VALUE) {
3769 return currentLimit - getTotalBytesRead();
3773 public boolean isAtEnd() throws IOException {
3774 return totalBytesRead + currentByteBufferPos - currentByteBufferStartPos == totalBufferSize;
3778 public int getTotalBytesRead() {
3780 (totalBytesRead - startOffset + currentByteBufferPos - currentByteBufferStartPos);
3784 public byte readRawByte() throws IOException {
3785 if (currentRemaining() == 0) {
3786 getNextByteBuffer();
3788 return UnsafeUtil.getByte(currentByteBufferPos++);
3792 public byte[] readRawBytes(final int length) throws IOException {
3793 if (length >= 0 && length <= currentRemaining()) {
3794 byte[] bytes = new byte[length];
3795 UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, length);
3796 currentByteBufferPos += length;
3799 if (length >= 0 && length <= remaining()) {
3800 byte[] bytes = new byte[length];
3801 readRawBytesTo(bytes, 0, length);
3807 return EMPTY_BYTE_ARRAY;
3809 throw InvalidProtocolBufferException.negativeSize();
3813 throw InvalidProtocolBufferException.truncatedMessage();
3817 * Try to get raw bytes from {@code input} with the size of {@code length} and copy to {@code
3818 * bytes} array. If the size is bigger than the number of remaining bytes in the input, then
3819 * throw {@code truncatedMessage} exception.
3824 * @throws IOException
3826 private void readRawBytesTo(byte[] bytes, int offset, final int length) throws IOException {
3827 if (length >= 0 && length <= remaining()) {
3830 if (currentRemaining() == 0) {
3831 getNextByteBuffer();
3833 int bytesToCopy = Math.min(l, (int) currentRemaining());
3834 UnsafeUtil.copyMemory(currentByteBufferPos, bytes, length - l + offset, bytesToCopy);
3836 currentByteBufferPos += bytesToCopy;
3845 throw InvalidProtocolBufferException.negativeSize();
3848 throw InvalidProtocolBufferException.truncatedMessage();
3852 public void skipRawBytes(final int length) throws IOException {
3857 - currentByteBufferPos
3858 + currentByteBufferStartPos)) {
3859 // We have all the bytes we need already.
3862 if (currentRemaining() == 0) {
3863 getNextByteBuffer();
3865 int rl = Math.min(l, (int) currentRemaining());
3867 currentByteBufferPos += rl;
3873 throw InvalidProtocolBufferException.negativeSize();
3875 throw InvalidProtocolBufferException.truncatedMessage();
3878 // TODO: optimize to fastpath
3879 private void skipRawVarint() throws IOException {
3880 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
3881 if (readRawByte() >= 0) {
3885 throw InvalidProtocolBufferException.malformedVarint();
3889 * Try to get the number of remaining bytes in {@code input}.
3891 * @return the number of remaining bytes in {@code input}.
3893 private int remaining() {
3895 (totalBufferSize - totalBytesRead - currentByteBufferPos + currentByteBufferStartPos);
3899 * Try to get the number of remaining bytes in {@code currentByteBuffer}.
3901 * @return the number of remaining bytes in {@code currentByteBuffer}
3903 private long currentRemaining() {
3904 return (currentByteBufferLimit - currentByteBufferPos);
3907 private ByteBuffer slice(int begin, int end) throws IOException {
3908 int prevPos = currentByteBuffer.position();
3909 int prevLimit = currentByteBuffer.limit();
3911 currentByteBuffer.position(begin);
3912 currentByteBuffer.limit(end);
3913 return currentByteBuffer.slice();
3914 } catch (IllegalArgumentException e) {
3915 throw InvalidProtocolBufferException.truncatedMessage();
3917 currentByteBuffer.position(prevPos);
3918 currentByteBuffer.limit(prevLimit);