• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
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
14 // distribution.
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.
18 //
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.
30 
31 package com.google.protobuf;
32 
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;
40 
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;
49 
50 /**
51  * Reads and decodes protocol message fields.
52  *
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.
58  *
59  * @author kenton@google.com Kenton Varda
60  */
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;
66 
67   /** Visible for subclasses. See setRecursionLimit() */
68   int recursionDepth;
69 
70   int recursionLimit = DEFAULT_RECURSION_LIMIT;
71 
72   /** Visible for subclasses. See setSizeLimit() */
73   int sizeLimit = DEFAULT_SIZE_LIMIT;
74 
75   /** Used to adapt to the experimental {@link Reader} interface. */
76   CodedInputStreamReader wrapper;
77 
78   /** Create a new CodedInputStream wrapping the given InputStream. */
newInstance(final InputStream input)79   public static CodedInputStream newInstance(final InputStream input) {
80     return newInstance(input, DEFAULT_BUFFER_SIZE);
81   }
82 
83   /** Create a new CodedInputStream wrapping the given InputStream, with a specified buffer size. */
newInstance(final InputStream input, int bufferSize)84   public static CodedInputStream newInstance(final InputStream input, int bufferSize) {
85     if (bufferSize <= 0) {
86       throw new IllegalArgumentException("bufferSize must be > 0");
87     }
88     if (input == null) {
89       // TODO(nathanmittler): Ideally we should throw here. This is done for backward compatibility.
90       return newInstance(EMPTY_BYTE_ARRAY);
91     }
92     return new StreamDecoder(input, bufferSize);
93   }
94 
95   /** Create a new CodedInputStream wrapping the given {@code Iterable <ByteBuffer>}. */
newInstance(final Iterable<ByteBuffer> input)96   public static CodedInputStream newInstance(final Iterable<ByteBuffer> input) {
97     if (!UnsafeDirectNioDecoder.isSupported()) {
98       return newInstance(new IterableByteBufferInputStream(input));
99     }
100     return newInstance(input, false);
101   }
102 
103   /** Create a new CodedInputStream wrapping the given {@code Iterable <ByteBuffer>}. */
newInstance( final Iterable<ByteBuffer> bufs, final boolean bufferIsImmutable)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.
111     int flag = 0;
112     // Total size of the input
113     int totalSize = 0;
114     for (ByteBuffer buf : bufs) {
115       totalSize += buf.remaining();
116       if (buf.hasArray()) {
117         flag |= 1;
118       } else if (buf.isDirect()) {
119         flag |= 2;
120       } else {
121         flag |= 4;
122       }
123     }
124     if (flag == 2) {
125       return new IterableDirectByteBufferDecoder(bufs, totalSize, bufferIsImmutable);
126     } else {
127       // TODO(yilunchong): add another decoders to deal case 1 and 3.
128       return newInstance(new IterableByteBufferInputStream(bufs));
129     }
130   }
131 
132   /** Create a new CodedInputStream wrapping the given byte array. */
newInstance(final byte[] buf)133   public static CodedInputStream newInstance(final byte[] buf) {
134     return newInstance(buf, 0, buf.length);
135   }
136 
137   /** Create a new CodedInputStream wrapping the given byte array slice. */
newInstance(final byte[] buf, final int off, final int len)138   public static CodedInputStream newInstance(final byte[] buf, final int off, final int len) {
139     return newInstance(buf, off, len, /* bufferIsImmutable= */ false);
140   }
141 
142   /** Create a new CodedInputStream wrapping the given byte array slice. */
newInstance( final byte[] buf, final int off, final int len, final boolean bufferIsImmutable)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);
146     try {
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
160       // appropriate.
161       throw new IllegalArgumentException(ex);
162     }
163     return result;
164   }
165 
166   /**
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.
173    */
newInstance(ByteBuffer buf)174   public static CodedInputStream newInstance(ByteBuffer buf) {
175     return newInstance(buf, /* bufferIsImmutable= */ false);
176   }
177 
178   /** Create a new CodedInputStream wrapping the given buffer. */
newInstance(ByteBuffer buf, boolean bufferIsImmutable)179   static CodedInputStream newInstance(ByteBuffer buf, boolean bufferIsImmutable) {
180     if (buf.hasArray()) {
181       return newInstance(
182           buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), bufferIsImmutable);
183     }
184 
185     if (buf.isDirect() && UnsafeDirectNioDecoder.isSupported()) {
186       return new UnsafeDirectNioDecoder(buf, bufferIsImmutable);
187     }
188 
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);
195   }
196 
197   /** Disable construction/inheritance outside of this class. */
CodedInputStream()198   private CodedInputStream() {}
199 
200   // -----------------------------------------------------------------
201 
202   /**
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.
206    */
readTag()207   public abstract int readTag() throws IOException;
208 
209   /**
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.
212    *
213    * @throws InvalidProtocolBufferException {@code value} does not match the last tag.
214    */
checkLastTagWas(final int value)215   public abstract void checkLastTagWas(final int value) throws InvalidProtocolBufferException;
216 
getLastTag()217   public abstract int getLastTag();
218 
219   /**
220    * Reads and discards a single field, given its tag value.
221    *
222    * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped.
223    *     Otherwise, returns {@code true}.
224    */
skipField(final int tag)225   public abstract boolean skipField(final int tag) throws IOException;
226 
227   /**
228    * Reads a single field and writes it to output in wire format, given its tag value.
229    *
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
233    *     stream.
234    */
235   @Deprecated
skipField(final int tag, final CodedOutputStream output)236   public abstract boolean skipField(final int tag, final CodedOutputStream output)
237       throws IOException;
238 
239   /**
240    * Reads and discards an entire message. This will read either until EOF or until an endgroup tag,
241    * whichever comes first.
242    */
skipMessage()243   public abstract void skipMessage() throws IOException;
244 
245   /**
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.
248    */
skipMessage(CodedOutputStream output)249   public abstract void skipMessage(CodedOutputStream output) throws IOException;
250 
251 
252   // -----------------------------------------------------------------
253 
254   /** Read a {@code double} field value from the stream. */
readDouble()255   public abstract double readDouble() throws IOException;
256 
257   /** Read a {@code float} field value from the stream. */
readFloat()258   public abstract float readFloat() throws IOException;
259 
260   /** Read a {@code uint64} field value from the stream. */
readUInt64()261   public abstract long readUInt64() throws IOException;
262 
263   /** Read an {@code int64} field value from the stream. */
readInt64()264   public abstract long readInt64() throws IOException;
265 
266   /** Read an {@code int32} field value from the stream. */
readInt32()267   public abstract int readInt32() throws IOException;
268 
269   /** Read a {@code fixed64} field value from the stream. */
readFixed64()270   public abstract long readFixed64() throws IOException;
271 
272   /** Read a {@code fixed32} field value from the stream. */
readFixed32()273   public abstract int readFixed32() throws IOException;
274 
275   /** Read a {@code bool} field value from the stream. */
readBool()276   public abstract boolean readBool() throws IOException;
277 
278   /**
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.
281    */
readString()282   public abstract String readString() throws IOException;
283 
284   /**
285    * Read a {@code string} field value from the stream. If the stream contains malformed UTF-8,
286    * throw exception {@link InvalidProtocolBufferException}.
287    */
readStringRequireUtf8()288   public abstract String readStringRequireUtf8() throws IOException;
289 
290   /** Read a {@code group} field value from the stream. */
readGroup( final int fieldNumber, final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)291   public abstract void readGroup(
292       final int fieldNumber,
293       final MessageLite.Builder builder,
294       final ExtensionRegistryLite extensionRegistry)
295       throws IOException;
296 
297 
298   /** Read a {@code group} field value from the stream. */
readGroup( final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)299   public abstract <T extends MessageLite> T readGroup(
300       final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)
301       throws IOException;
302 
303   /**
304    * Reads a {@code group} field value from the stream and merges it into the given {@link
305    * UnknownFieldSet}.
306    *
307    * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so you can just call
308    *     {@link #readGroup}.
309    */
310   @Deprecated
readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)311   public abstract void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
312       throws IOException;
313 
314   /** Read an embedded message field value from the stream. */
readMessage( final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)315   public abstract void readMessage(
316       final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
317       throws IOException;
318 
319 
320   /** Read an embedded message field value from the stream. */
readMessage( final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)321   public abstract <T extends MessageLite> T readMessage(
322       final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException;
323 
324   /** Read a {@code bytes} field value from the stream. */
readBytes()325   public abstract ByteString readBytes() throws IOException;
326 
327   /** Read a {@code bytes} field value from the stream. */
readByteArray()328   public abstract byte[] readByteArray() throws IOException;
329 
330   /** Read a {@code bytes} field value from the stream. */
readByteBuffer()331   public abstract ByteBuffer readByteBuffer() throws IOException;
332 
333   /** Read a {@code uint32} field value from the stream. */
readUInt32()334   public abstract int readUInt32() throws IOException;
335 
336   /**
337    * Read an enum field value from the stream. Caller is responsible for converting the numeric
338    * value to an actual enum.
339    */
readEnum()340   public abstract int readEnum() throws IOException;
341 
342   /** Read an {@code sfixed32} field value from the stream. */
readSFixed32()343   public abstract int readSFixed32() throws IOException;
344 
345   /** Read an {@code sfixed64} field value from the stream. */
readSFixed64()346   public abstract long readSFixed64() throws IOException;
347 
348   /** Read an {@code sint32} field value from the stream. */
readSInt32()349   public abstract int readSInt32() throws IOException;
350 
351   /** Read an {@code sint64} field value from the stream. */
readSInt64()352   public abstract long readSInt64() throws IOException;
353 
354   // =================================================================
355 
356   /** Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits. */
readRawVarint32()357   public abstract int readRawVarint32() throws IOException;
358 
359   /** Read a raw Varint from the stream. */
readRawVarint64()360   public abstract long readRawVarint64() throws IOException;
361 
362   /** Variant of readRawVarint64 for when uncomfortably close to the limit. */
363   /* Visible for testing */
readRawVarint64SlowPath()364   abstract long readRawVarint64SlowPath() throws IOException;
365 
366   /** Read a 32-bit little-endian integer from the stream. */
readRawLittleEndian32()367   public abstract int readRawLittleEndian32() throws IOException;
368 
369   /** Read a 64-bit little-endian integer from the stream. */
readRawLittleEndian64()370   public abstract long readRawLittleEndian64() throws IOException;
371 
372   // -----------------------------------------------------------------
373 
374   /**
375    * Enables {@link ByteString} aliasing of the underlying buffer, trading off on buffer pinning for
376    * data copies. Only valid for buffer-backed streams.
377    */
enableAliasing(boolean enabled)378   public abstract void enableAliasing(boolean enabled);
379 
380   /**
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
383    * limit is 100.
384    *
385    * @return the old limit.
386    */
setRecursionLimit(final int limit)387   public final int setRecursionLimit(final int limit) {
388     if (limit < 0) {
389       throw new IllegalArgumentException("Recursion limit cannot be negative: " + limit);
390     }
391     final int oldLimit = recursionLimit;
392     recursionLimit = limit;
393     return oldLimit;
394   }
395 
396   /**
397    * Only valid for {@link InputStream}-backed streams.
398    *
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.
404    *
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.
407    *
408    * @return the old limit.
409    */
setSizeLimit(final int limit)410   public final int setSizeLimit(final int limit) {
411     if (limit < 0) {
412       throw new IllegalArgumentException("Size limit cannot be negative: " + limit);
413     }
414     final int oldLimit = sizeLimit;
415     sizeLimit = limit;
416     return oldLimit;
417   }
418 
419   private boolean shouldDiscardUnknownFields = false;
420 
421   /**
422    * Sets this {@code CodedInputStream} to discard unknown fields. Only applies to full runtime
423    * messages; lite messages will always preserve unknowns.
424    *
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
427    * runtime.
428    */
discardUnknownFields()429   final void discardUnknownFields() {
430     shouldDiscardUnknownFields = true;
431   }
432 
433   /**
434    * Reverts the unknown fields preservation behavior for Proto2 and Proto3 full runtime to their
435    * default.
436    */
unsetDiscardUnknownFields()437   final void unsetDiscardUnknownFields() {
438     shouldDiscardUnknownFields = false;
439   }
440 
441   /**
442    * Whether unknown fields in this input stream should be discarded during parsing into full
443    * runtime messages.
444    */
shouldDiscardUnknownFields()445   final boolean shouldDiscardUnknownFields() {
446     return shouldDiscardUnknownFields;
447   }
448 
449   /**
450    * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). Only valid for {@link
451    * InputStream}-backed streams.
452    */
resetSizeCounter()453   public abstract void resetSizeCounter();
454 
455   /**
456    * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This is called when
457    * descending into a length-delimited embedded message.
458    *
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.
465    *
466    * @return the old limit.
467    */
pushLimit(int byteLimit)468   public abstract int pushLimit(int byteLimit) throws InvalidProtocolBufferException;
469 
470   /**
471    * Discards the current limit, returning to the previous limit.
472    *
473    * @param oldLimit The old limit, as returned by {@code pushLimit}.
474    */
popLimit(final int oldLimit)475   public abstract void popLimit(final int oldLimit);
476 
477   /**
478    * Returns the number of bytes to be read before the current limit. If no limit is set, returns
479    * -1.
480    */
getBytesUntilLimit()481   public abstract int getBytesUntilLimit();
482 
483   /**
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)}. This function may get blocked when using StreamDecoder as it
487    * invokes {@link StreamDecoder#tryRefillBuffer(int)} in this function which will try to read
488    * bytes from input.
489    */
isAtEnd()490   public abstract boolean isAtEnd() throws IOException;
491 
492   /**
493    * The total bytes read up to the current position. Calling {@link #resetSizeCounter()} resets
494    * this value to zero.
495    */
getTotalBytesRead()496   public abstract int getTotalBytesRead();
497 
498   /**
499    * Read one byte from the input.
500    *
501    * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
502    */
readRawByte()503   public abstract byte readRawByte() throws IOException;
504 
505   /**
506    * Read a fixed size of bytes from the input.
507    *
508    * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
509    */
readRawBytes(final int size)510   public abstract byte[] readRawBytes(final int size) throws IOException;
511 
512   /**
513    * Reads and discards {@code size} bytes.
514    *
515    * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
516    */
skipRawBytes(final int size)517   public abstract void skipRawBytes(final int size) throws IOException;
518 
519   /**
520    * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers into values that can be
521    * efficiently encoded with varint. (Otherwise, negative values must be sign-extended to 64 bits
522    * to be varint encoded, thus always taking 10 bytes on the wire.)
523    *
524    * @param n An unsigned 32-bit integer, stored in a signed int because Java has no explicit
525    *     unsigned support.
526    * @return A signed 32-bit integer.
527    */
decodeZigZag32(final int n)528   public static int decodeZigZag32(final int n) {
529     return (n >>> 1) ^ -(n & 1);
530   }
531 
532   /**
533    * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers into values that can be
534    * efficiently encoded with varint. (Otherwise, negative values must be sign-extended to 64 bits
535    * to be varint encoded, thus always taking 10 bytes on the wire.)
536    *
537    * @param n An unsigned 64-bit integer, stored in a signed int because Java has no explicit
538    *     unsigned support.
539    * @return A signed 64-bit integer.
540    */
decodeZigZag64(final long n)541   public static long decodeZigZag64(final long n) {
542     return (n >>> 1) ^ -(n & 1);
543   }
544 
545   /**
546    * Like {@link #readRawVarint32(InputStream)}, but expects that the caller has already read one
547    * byte. This allows the caller to determine if EOF has been reached before attempting to read.
548    */
readRawVarint32(final int firstByte, final InputStream input)549   public static int readRawVarint32(final int firstByte, final InputStream input)
550       throws IOException {
551     if ((firstByte & 0x80) == 0) {
552       return firstByte;
553     }
554 
555     int result = firstByte & 0x7f;
556     int offset = 7;
557     for (; offset < 32; offset += 7) {
558       final int b = input.read();
559       if (b == -1) {
560         throw InvalidProtocolBufferException.truncatedMessage();
561       }
562       result |= (b & 0x7f) << offset;
563       if ((b & 0x80) == 0) {
564         return result;
565       }
566     }
567     // Keep reading up to 64 bits.
568     for (; offset < 64; offset += 7) {
569       final int b = input.read();
570       if (b == -1) {
571         throw InvalidProtocolBufferException.truncatedMessage();
572       }
573       if ((b & 0x80) == 0) {
574         return result;
575       }
576     }
577     throw InvalidProtocolBufferException.malformedVarint();
578   }
579 
580   /**
581    * Reads a varint from the input one byte at a time, so that it does not read any bytes after the
582    * end of the varint. If you simply wrapped the stream in a CodedInputStream and used {@link
583    * #readRawVarint32(InputStream)} then you would probably end up reading past the end of the
584    * varint since CodedInputStream buffers its input.
585    */
readRawVarint32(final InputStream input)586   static int readRawVarint32(final InputStream input) throws IOException {
587     final int firstByte = input.read();
588     if (firstByte == -1) {
589       throw InvalidProtocolBufferException.truncatedMessage();
590     }
591     return readRawVarint32(firstByte, input);
592   }
593 
594   /** A {@link CodedInputStream} implementation that uses a backing array as the input. */
595   private static final class ArrayDecoder extends CodedInputStream {
596     private final byte[] buffer;
597     private final boolean immutable;
598     private int limit;
599     private int bufferSizeAfterLimit;
600     private int pos;
601     private int startPos;
602     private int lastTag;
603     private boolean enableAliasing;
604 
605     /** The absolute position of the end of the current message. */
606     private int currentLimit = Integer.MAX_VALUE;
607 
ArrayDecoder(final byte[] buffer, final int offset, final int len, boolean immutable)608     private ArrayDecoder(final byte[] buffer, final int offset, final int len, boolean immutable) {
609       this.buffer = buffer;
610       limit = offset + len;
611       pos = offset;
612       startPos = pos;
613       this.immutable = immutable;
614     }
615 
616     @Override
readTag()617     public int readTag() throws IOException {
618       if (isAtEnd()) {
619         lastTag = 0;
620         return 0;
621       }
622 
623       lastTag = readRawVarint32();
624       if (WireFormat.getTagFieldNumber(lastTag) == 0) {
625         // If we actually read zero (or any tag number corresponding to field
626         // number zero), that's not a valid tag.
627         throw InvalidProtocolBufferException.invalidTag();
628       }
629       return lastTag;
630     }
631 
632     @Override
checkLastTagWas(final int value)633     public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
634       if (lastTag != value) {
635         throw InvalidProtocolBufferException.invalidEndTag();
636       }
637     }
638 
639     @Override
getLastTag()640     public int getLastTag() {
641       return lastTag;
642     }
643 
644     @Override
skipField(final int tag)645     public boolean skipField(final int tag) throws IOException {
646       switch (WireFormat.getTagWireType(tag)) {
647         case WireFormat.WIRETYPE_VARINT:
648           skipRawVarint();
649           return true;
650         case WireFormat.WIRETYPE_FIXED64:
651           skipRawBytes(FIXED64_SIZE);
652           return true;
653         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
654           skipRawBytes(readRawVarint32());
655           return true;
656         case WireFormat.WIRETYPE_START_GROUP:
657           skipMessage();
658           checkLastTagWas(
659               WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
660           return true;
661         case WireFormat.WIRETYPE_END_GROUP:
662           return false;
663         case WireFormat.WIRETYPE_FIXED32:
664           skipRawBytes(FIXED32_SIZE);
665           return true;
666         default:
667           throw InvalidProtocolBufferException.invalidWireType();
668       }
669     }
670 
671     @Override
skipField(final int tag, final CodedOutputStream output)672     public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
673       switch (WireFormat.getTagWireType(tag)) {
674         case WireFormat.WIRETYPE_VARINT:
675           {
676             long value = readInt64();
677             output.writeRawVarint32(tag);
678             output.writeUInt64NoTag(value);
679             return true;
680           }
681         case WireFormat.WIRETYPE_FIXED64:
682           {
683             long value = readRawLittleEndian64();
684             output.writeRawVarint32(tag);
685             output.writeFixed64NoTag(value);
686             return true;
687           }
688         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
689           {
690             ByteString value = readBytes();
691             output.writeRawVarint32(tag);
692             output.writeBytesNoTag(value);
693             return true;
694           }
695         case WireFormat.WIRETYPE_START_GROUP:
696           {
697             output.writeRawVarint32(tag);
698             skipMessage(output);
699             int endtag =
700                 WireFormat.makeTag(
701                     WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
702             checkLastTagWas(endtag);
703             output.writeRawVarint32(endtag);
704             return true;
705           }
706         case WireFormat.WIRETYPE_END_GROUP:
707           {
708             return false;
709           }
710         case WireFormat.WIRETYPE_FIXED32:
711           {
712             int value = readRawLittleEndian32();
713             output.writeRawVarint32(tag);
714             output.writeFixed32NoTag(value);
715             return true;
716           }
717         default:
718           throw InvalidProtocolBufferException.invalidWireType();
719       }
720     }
721 
722     @Override
skipMessage()723     public void skipMessage() throws IOException {
724       while (true) {
725         final int tag = readTag();
726         if (tag == 0 || !skipField(tag)) {
727           return;
728         }
729       }
730     }
731 
732     @Override
skipMessage(CodedOutputStream output)733     public void skipMessage(CodedOutputStream output) throws IOException {
734       while (true) {
735         final int tag = readTag();
736         if (tag == 0 || !skipField(tag, output)) {
737           return;
738         }
739       }
740     }
741 
742 
743     // -----------------------------------------------------------------
744 
745     @Override
readDouble()746     public double readDouble() throws IOException {
747       return Double.longBitsToDouble(readRawLittleEndian64());
748     }
749 
750     @Override
readFloat()751     public float readFloat() throws IOException {
752       return Float.intBitsToFloat(readRawLittleEndian32());
753     }
754 
755     @Override
readUInt64()756     public long readUInt64() throws IOException {
757       return readRawVarint64();
758     }
759 
760     @Override
readInt64()761     public long readInt64() throws IOException {
762       return readRawVarint64();
763     }
764 
765     @Override
readInt32()766     public int readInt32() throws IOException {
767       return readRawVarint32();
768     }
769 
770     @Override
readFixed64()771     public long readFixed64() throws IOException {
772       return readRawLittleEndian64();
773     }
774 
775     @Override
readFixed32()776     public int readFixed32() throws IOException {
777       return readRawLittleEndian32();
778     }
779 
780     @Override
readBool()781     public boolean readBool() throws IOException {
782       return readRawVarint64() != 0;
783     }
784 
785     @Override
readString()786     public String readString() throws IOException {
787       final int size = readRawVarint32();
788       if (size > 0 && size <= (limit - pos)) {
789         // Fast path:  We already have the bytes in a contiguous buffer, so
790         //   just copy directly from it.
791         final String result = new String(buffer, pos, size, UTF_8);
792         pos += size;
793         return result;
794       }
795 
796       if (size == 0) {
797         return "";
798       }
799       if (size < 0) {
800         throw InvalidProtocolBufferException.negativeSize();
801       }
802       throw InvalidProtocolBufferException.truncatedMessage();
803     }
804 
805     @Override
readStringRequireUtf8()806     public String readStringRequireUtf8() throws IOException {
807       final int size = readRawVarint32();
808       if (size > 0 && size <= (limit - pos)) {
809         String result = Utf8.decodeUtf8(buffer, pos, size);
810         pos += size;
811         return result;
812       }
813 
814       if (size == 0) {
815         return "";
816       }
817       if (size <= 0) {
818         throw InvalidProtocolBufferException.negativeSize();
819       }
820       throw InvalidProtocolBufferException.truncatedMessage();
821     }
822 
823     @Override
readGroup( final int fieldNumber, final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)824     public void readGroup(
825         final int fieldNumber,
826         final MessageLite.Builder builder,
827         final ExtensionRegistryLite extensionRegistry)
828         throws IOException {
829       if (recursionDepth >= recursionLimit) {
830         throw InvalidProtocolBufferException.recursionLimitExceeded();
831       }
832       ++recursionDepth;
833       builder.mergeFrom(this, extensionRegistry);
834       checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
835       --recursionDepth;
836     }
837 
838 
839     @Override
readGroup( final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)840     public <T extends MessageLite> T readGroup(
841         final int fieldNumber,
842         final Parser<T> parser,
843         final ExtensionRegistryLite extensionRegistry)
844         throws IOException {
845       if (recursionDepth >= recursionLimit) {
846         throw InvalidProtocolBufferException.recursionLimitExceeded();
847       }
848       ++recursionDepth;
849       T result = parser.parsePartialFrom(this, extensionRegistry);
850       checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
851       --recursionDepth;
852       return result;
853     }
854 
855     @Deprecated
856     @Override
readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)857     public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
858         throws IOException {
859       readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
860     }
861 
862     @Override
readMessage( final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)863     public void readMessage(
864         final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
865         throws IOException {
866       final int length = readRawVarint32();
867       if (recursionDepth >= recursionLimit) {
868         throw InvalidProtocolBufferException.recursionLimitExceeded();
869       }
870       final int oldLimit = pushLimit(length);
871       ++recursionDepth;
872       builder.mergeFrom(this, extensionRegistry);
873       checkLastTagWas(0);
874       --recursionDepth;
875       popLimit(oldLimit);
876     }
877 
878 
879     @Override
readMessage( final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)880     public <T extends MessageLite> T readMessage(
881         final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
882       int length = readRawVarint32();
883       if (recursionDepth >= recursionLimit) {
884         throw InvalidProtocolBufferException.recursionLimitExceeded();
885       }
886       final int oldLimit = pushLimit(length);
887       ++recursionDepth;
888       T result = parser.parsePartialFrom(this, extensionRegistry);
889       checkLastTagWas(0);
890       --recursionDepth;
891       popLimit(oldLimit);
892       return result;
893     }
894 
895     @Override
readBytes()896     public ByteString readBytes() throws IOException {
897       final int size = readRawVarint32();
898       if (size > 0 && size <= (limit - pos)) {
899         // Fast path:  We already have the bytes in a contiguous buffer, so
900         //   just copy directly from it.
901         final ByteString result =
902             immutable && enableAliasing
903                 ? ByteString.wrap(buffer, pos, size)
904                 : ByteString.copyFrom(buffer, pos, size);
905         pos += size;
906         return result;
907       }
908       if (size == 0) {
909         return ByteString.EMPTY;
910       }
911       // Slow path:  Build a byte array first then copy it.
912       return ByteString.wrap(readRawBytes(size));
913     }
914 
915     @Override
readByteArray()916     public byte[] readByteArray() throws IOException {
917       final int size = readRawVarint32();
918       return readRawBytes(size);
919     }
920 
921     @Override
readByteBuffer()922     public ByteBuffer readByteBuffer() throws IOException {
923       final int size = readRawVarint32();
924       if (size > 0 && size <= (limit - pos)) {
925         // Fast path: We already have the bytes in a contiguous buffer.
926         // When aliasing is enabled, we can return a ByteBuffer pointing directly
927         // into the underlying byte array without copy if the CodedInputStream is
928         // constructed from a byte array. If aliasing is disabled or the input is
929         // from an InputStream or ByteString, we have to make a copy of the bytes.
930         ByteBuffer result =
931             !immutable && enableAliasing
932                 ? ByteBuffer.wrap(buffer, pos, size).slice()
933                 : ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size));
934         pos += size;
935         // TODO(nathanmittler): Investigate making the ByteBuffer be made read-only
936         return result;
937       }
938 
939       if (size == 0) {
940         return EMPTY_BYTE_BUFFER;
941       }
942       if (size < 0) {
943         throw InvalidProtocolBufferException.negativeSize();
944       }
945       throw InvalidProtocolBufferException.truncatedMessage();
946     }
947 
948     @Override
readUInt32()949     public int readUInt32() throws IOException {
950       return readRawVarint32();
951     }
952 
953     @Override
readEnum()954     public int readEnum() throws IOException {
955       return readRawVarint32();
956     }
957 
958     @Override
readSFixed32()959     public int readSFixed32() throws IOException {
960       return readRawLittleEndian32();
961     }
962 
963     @Override
readSFixed64()964     public long readSFixed64() throws IOException {
965       return readRawLittleEndian64();
966     }
967 
968     @Override
readSInt32()969     public int readSInt32() throws IOException {
970       return decodeZigZag32(readRawVarint32());
971     }
972 
973     @Override
readSInt64()974     public long readSInt64() throws IOException {
975       return decodeZigZag64(readRawVarint64());
976     }
977 
978     // =================================================================
979 
980     @Override
readRawVarint32()981     public int readRawVarint32() throws IOException {
982       // See implementation notes for readRawVarint64
983       fastpath:
984       {
985         int tempPos = pos;
986 
987         if (limit == tempPos) {
988           break fastpath;
989         }
990 
991         final byte[] buffer = this.buffer;
992         int x;
993         if ((x = buffer[tempPos++]) >= 0) {
994           pos = tempPos;
995           return x;
996         } else if (limit - tempPos < 9) {
997           break fastpath;
998         } else if ((x ^= (buffer[tempPos++] << 7)) < 0) {
999           x ^= (~0 << 7);
1000         } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) {
1001           x ^= (~0 << 7) ^ (~0 << 14);
1002         } else if ((x ^= (buffer[tempPos++] << 21)) < 0) {
1003           x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
1004         } else {
1005           int y = buffer[tempPos++];
1006           x ^= y << 28;
1007           x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
1008           if (y < 0
1009               && buffer[tempPos++] < 0
1010               && buffer[tempPos++] < 0
1011               && buffer[tempPos++] < 0
1012               && buffer[tempPos++] < 0
1013               && buffer[tempPos++] < 0) {
1014             break fastpath; // Will throw malformedVarint()
1015           }
1016         }
1017         pos = tempPos;
1018         return x;
1019       }
1020       return (int) readRawVarint64SlowPath();
1021     }
1022 
skipRawVarint()1023     private void skipRawVarint() throws IOException {
1024       if (limit - pos >= MAX_VARINT_SIZE) {
1025         skipRawVarintFastPath();
1026       } else {
1027         skipRawVarintSlowPath();
1028       }
1029     }
1030 
skipRawVarintFastPath()1031     private void skipRawVarintFastPath() throws IOException {
1032       for (int i = 0; i < MAX_VARINT_SIZE; i++) {
1033         if (buffer[pos++] >= 0) {
1034           return;
1035         }
1036       }
1037       throw InvalidProtocolBufferException.malformedVarint();
1038     }
1039 
skipRawVarintSlowPath()1040     private void skipRawVarintSlowPath() throws IOException {
1041       for (int i = 0; i < MAX_VARINT_SIZE; i++) {
1042         if (readRawByte() >= 0) {
1043           return;
1044         }
1045       }
1046       throw InvalidProtocolBufferException.malformedVarint();
1047     }
1048 
1049     @Override
readRawVarint64()1050     public long readRawVarint64() throws IOException {
1051       // Implementation notes:
1052       //
1053       // Optimized for one-byte values, expected to be common.
1054       // The particular code below was selected from various candidates
1055       // empirically, by winning VarintBenchmark.
1056       //
1057       // Sign extension of (signed) Java bytes is usually a nuisance, but
1058       // we exploit it here to more easily obtain the sign of bytes read.
1059       // Instead of cleaning up the sign extension bits by masking eagerly,
1060       // we delay until we find the final (positive) byte, when we clear all
1061       // accumulated bits with one xor.  We depend on javac to constant fold.
1062       fastpath:
1063       {
1064         int tempPos = pos;
1065 
1066         if (limit == tempPos) {
1067           break fastpath;
1068         }
1069 
1070         final byte[] buffer = this.buffer;
1071         long x;
1072         int y;
1073         if ((y = buffer[tempPos++]) >= 0) {
1074           pos = tempPos;
1075           return y;
1076         } else if (limit - tempPos < 9) {
1077           break fastpath;
1078         } else if ((y ^= (buffer[tempPos++] << 7)) < 0) {
1079           x = y ^ (~0 << 7);
1080         } else if ((y ^= (buffer[tempPos++] << 14)) >= 0) {
1081           x = y ^ ((~0 << 7) ^ (~0 << 14));
1082         } else if ((y ^= (buffer[tempPos++] << 21)) < 0) {
1083           x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
1084         } else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) {
1085           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
1086         } else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) {
1087           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
1088         } else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) {
1089           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
1090         } else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) {
1091           x ^=
1092               (~0L << 7)
1093                   ^ (~0L << 14)
1094                   ^ (~0L << 21)
1095                   ^ (~0L << 28)
1096                   ^ (~0L << 35)
1097                   ^ (~0L << 42)
1098                   ^ (~0L << 49);
1099         } else {
1100           x ^= ((long) buffer[tempPos++] << 56);
1101           x ^=
1102               (~0L << 7)
1103                   ^ (~0L << 14)
1104                   ^ (~0L << 21)
1105                   ^ (~0L << 28)
1106                   ^ (~0L << 35)
1107                   ^ (~0L << 42)
1108                   ^ (~0L << 49)
1109                   ^ (~0L << 56);
1110           if (x < 0L) {
1111             if (buffer[tempPos++] < 0L) {
1112               break fastpath; // Will throw malformedVarint()
1113             }
1114           }
1115         }
1116         pos = tempPos;
1117         return x;
1118       }
1119       return readRawVarint64SlowPath();
1120     }
1121 
1122     @Override
readRawVarint64SlowPath()1123     long readRawVarint64SlowPath() throws IOException {
1124       long result = 0;
1125       for (int shift = 0; shift < 64; shift += 7) {
1126         final byte b = readRawByte();
1127         result |= (long) (b & 0x7F) << shift;
1128         if ((b & 0x80) == 0) {
1129           return result;
1130         }
1131       }
1132       throw InvalidProtocolBufferException.malformedVarint();
1133     }
1134 
1135     @Override
readRawLittleEndian32()1136     public int readRawLittleEndian32() throws IOException {
1137       int tempPos = pos;
1138 
1139       if (limit - tempPos < FIXED32_SIZE) {
1140         throw InvalidProtocolBufferException.truncatedMessage();
1141       }
1142 
1143       final byte[] buffer = this.buffer;
1144       pos = tempPos + FIXED32_SIZE;
1145       return (((buffer[tempPos] & 0xff))
1146           | ((buffer[tempPos + 1] & 0xff) << 8)
1147           | ((buffer[tempPos + 2] & 0xff) << 16)
1148           | ((buffer[tempPos + 3] & 0xff) << 24));
1149     }
1150 
1151     @Override
readRawLittleEndian64()1152     public long readRawLittleEndian64() throws IOException {
1153       int tempPos = pos;
1154 
1155       if (limit - tempPos < FIXED64_SIZE) {
1156         throw InvalidProtocolBufferException.truncatedMessage();
1157       }
1158 
1159       final byte[] buffer = this.buffer;
1160       pos = tempPos + FIXED64_SIZE;
1161       return (((buffer[tempPos] & 0xffL))
1162           | ((buffer[tempPos + 1] & 0xffL) << 8)
1163           | ((buffer[tempPos + 2] & 0xffL) << 16)
1164           | ((buffer[tempPos + 3] & 0xffL) << 24)
1165           | ((buffer[tempPos + 4] & 0xffL) << 32)
1166           | ((buffer[tempPos + 5] & 0xffL) << 40)
1167           | ((buffer[tempPos + 6] & 0xffL) << 48)
1168           | ((buffer[tempPos + 7] & 0xffL) << 56));
1169     }
1170 
1171     @Override
enableAliasing(boolean enabled)1172     public void enableAliasing(boolean enabled) {
1173       this.enableAliasing = enabled;
1174     }
1175 
1176     @Override
resetSizeCounter()1177     public void resetSizeCounter() {
1178       startPos = pos;
1179     }
1180 
1181     @Override
pushLimit(int byteLimit)1182     public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
1183       if (byteLimit < 0) {
1184         throw InvalidProtocolBufferException.negativeSize();
1185       }
1186       byteLimit += getTotalBytesRead();
1187       final int oldLimit = currentLimit;
1188       if (byteLimit > oldLimit) {
1189         throw InvalidProtocolBufferException.truncatedMessage();
1190       }
1191       currentLimit = byteLimit;
1192 
1193       recomputeBufferSizeAfterLimit();
1194 
1195       return oldLimit;
1196     }
1197 
recomputeBufferSizeAfterLimit()1198     private void recomputeBufferSizeAfterLimit() {
1199       limit += bufferSizeAfterLimit;
1200       final int bufferEnd = limit - startPos;
1201       if (bufferEnd > currentLimit) {
1202         // Limit is in current buffer.
1203         bufferSizeAfterLimit = bufferEnd - currentLimit;
1204         limit -= bufferSizeAfterLimit;
1205       } else {
1206         bufferSizeAfterLimit = 0;
1207       }
1208     }
1209 
1210     @Override
popLimit(final int oldLimit)1211     public void popLimit(final int oldLimit) {
1212       currentLimit = oldLimit;
1213       recomputeBufferSizeAfterLimit();
1214     }
1215 
1216     @Override
getBytesUntilLimit()1217     public int getBytesUntilLimit() {
1218       if (currentLimit == Integer.MAX_VALUE) {
1219         return -1;
1220       }
1221 
1222       return currentLimit - getTotalBytesRead();
1223     }
1224 
1225     @Override
isAtEnd()1226     public boolean isAtEnd() throws IOException {
1227       return pos == limit;
1228     }
1229 
1230     @Override
getTotalBytesRead()1231     public int getTotalBytesRead() {
1232       return pos - startPos;
1233     }
1234 
1235     @Override
readRawByte()1236     public byte readRawByte() throws IOException {
1237       if (pos == limit) {
1238         throw InvalidProtocolBufferException.truncatedMessage();
1239       }
1240       return buffer[pos++];
1241     }
1242 
1243     @Override
readRawBytes(final int length)1244     public byte[] readRawBytes(final int length) throws IOException {
1245       if (length > 0 && length <= (limit - pos)) {
1246         final int tempPos = pos;
1247         pos += length;
1248         return Arrays.copyOfRange(buffer, tempPos, pos);
1249       }
1250 
1251       if (length <= 0) {
1252         if (length == 0) {
1253           return Internal.EMPTY_BYTE_ARRAY;
1254         } else {
1255           throw InvalidProtocolBufferException.negativeSize();
1256         }
1257       }
1258       throw InvalidProtocolBufferException.truncatedMessage();
1259     }
1260 
1261     @Override
skipRawBytes(final int length)1262     public void skipRawBytes(final int length) throws IOException {
1263       if (length >= 0 && length <= (limit - pos)) {
1264         // We have all the bytes we need already.
1265         pos += length;
1266         return;
1267       }
1268 
1269       if (length < 0) {
1270         throw InvalidProtocolBufferException.negativeSize();
1271       }
1272       throw InvalidProtocolBufferException.truncatedMessage();
1273     }
1274   }
1275 
1276   /**
1277    * A {@link CodedInputStream} implementation that uses a backing direct ByteBuffer as the input.
1278    * Requires the use of {@code sun.misc.Unsafe} to perform fast reads on the buffer.
1279    */
1280   private static final class UnsafeDirectNioDecoder extends CodedInputStream {
1281     /** The direct buffer that is backing this stream. */
1282     private final ByteBuffer buffer;
1283 
1284     /**
1285      * If {@code true}, indicates that the buffer is backing a {@link ByteString} and is therefore
1286      * considered to be an immutable input source.
1287      */
1288     private final boolean immutable;
1289 
1290     /** The unsafe address of the content of {@link #buffer}. */
1291     private final long address;
1292 
1293     /** The unsafe address of the current read limit of the buffer. */
1294     private long limit;
1295 
1296     /** The unsafe address of the current read position of the buffer. */
1297     private long pos;
1298 
1299     /** The unsafe address of the starting read position. */
1300     private long startPos;
1301 
1302     /** The amount of available data in the buffer beyond {@link #limit}. */
1303     private int bufferSizeAfterLimit;
1304 
1305     /** The last tag that was read from this stream. */
1306     private int lastTag;
1307 
1308     /**
1309      * If {@code true}, indicates that calls to read {@link ByteString} or {@code byte[]}
1310      * <strong>may</strong> return slices of the underlying buffer, rather than copies.
1311      */
1312     private boolean enableAliasing;
1313 
1314     /** The absolute position of the end of the current message. */
1315     private int currentLimit = Integer.MAX_VALUE;
1316 
isSupported()1317     static boolean isSupported() {
1318       return UnsafeUtil.hasUnsafeByteBufferOperations();
1319     }
1320 
UnsafeDirectNioDecoder(ByteBuffer buffer, boolean immutable)1321     private UnsafeDirectNioDecoder(ByteBuffer buffer, boolean immutable) {
1322       this.buffer = buffer;
1323       address = UnsafeUtil.addressOffset(buffer);
1324       limit = address + buffer.limit();
1325       pos = address + buffer.position();
1326       startPos = pos;
1327       this.immutable = immutable;
1328     }
1329 
1330     @Override
readTag()1331     public int readTag() throws IOException {
1332       if (isAtEnd()) {
1333         lastTag = 0;
1334         return 0;
1335       }
1336 
1337       lastTag = readRawVarint32();
1338       if (WireFormat.getTagFieldNumber(lastTag) == 0) {
1339         // If we actually read zero (or any tag number corresponding to field
1340         // number zero), that's not a valid tag.
1341         throw InvalidProtocolBufferException.invalidTag();
1342       }
1343       return lastTag;
1344     }
1345 
1346     @Override
checkLastTagWas(final int value)1347     public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
1348       if (lastTag != value) {
1349         throw InvalidProtocolBufferException.invalidEndTag();
1350       }
1351     }
1352 
1353     @Override
getLastTag()1354     public int getLastTag() {
1355       return lastTag;
1356     }
1357 
1358     @Override
skipField(final int tag)1359     public boolean skipField(final int tag) throws IOException {
1360       switch (WireFormat.getTagWireType(tag)) {
1361         case WireFormat.WIRETYPE_VARINT:
1362           skipRawVarint();
1363           return true;
1364         case WireFormat.WIRETYPE_FIXED64:
1365           skipRawBytes(FIXED64_SIZE);
1366           return true;
1367         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
1368           skipRawBytes(readRawVarint32());
1369           return true;
1370         case WireFormat.WIRETYPE_START_GROUP:
1371           skipMessage();
1372           checkLastTagWas(
1373               WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
1374           return true;
1375         case WireFormat.WIRETYPE_END_GROUP:
1376           return false;
1377         case WireFormat.WIRETYPE_FIXED32:
1378           skipRawBytes(FIXED32_SIZE);
1379           return true;
1380         default:
1381           throw InvalidProtocolBufferException.invalidWireType();
1382       }
1383     }
1384 
1385     @Override
skipField(final int tag, final CodedOutputStream output)1386     public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
1387       switch (WireFormat.getTagWireType(tag)) {
1388         case WireFormat.WIRETYPE_VARINT:
1389           {
1390             long value = readInt64();
1391             output.writeRawVarint32(tag);
1392             output.writeUInt64NoTag(value);
1393             return true;
1394           }
1395         case WireFormat.WIRETYPE_FIXED64:
1396           {
1397             long value = readRawLittleEndian64();
1398             output.writeRawVarint32(tag);
1399             output.writeFixed64NoTag(value);
1400             return true;
1401           }
1402         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
1403           {
1404             ByteString value = readBytes();
1405             output.writeRawVarint32(tag);
1406             output.writeBytesNoTag(value);
1407             return true;
1408           }
1409         case WireFormat.WIRETYPE_START_GROUP:
1410           {
1411             output.writeRawVarint32(tag);
1412             skipMessage(output);
1413             int endtag =
1414                 WireFormat.makeTag(
1415                     WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
1416             checkLastTagWas(endtag);
1417             output.writeRawVarint32(endtag);
1418             return true;
1419           }
1420         case WireFormat.WIRETYPE_END_GROUP:
1421           {
1422             return false;
1423           }
1424         case WireFormat.WIRETYPE_FIXED32:
1425           {
1426             int value = readRawLittleEndian32();
1427             output.writeRawVarint32(tag);
1428             output.writeFixed32NoTag(value);
1429             return true;
1430           }
1431         default:
1432           throw InvalidProtocolBufferException.invalidWireType();
1433       }
1434     }
1435 
1436     @Override
skipMessage()1437     public void skipMessage() throws IOException {
1438       while (true) {
1439         final int tag = readTag();
1440         if (tag == 0 || !skipField(tag)) {
1441           return;
1442         }
1443       }
1444     }
1445 
1446     @Override
skipMessage(CodedOutputStream output)1447     public void skipMessage(CodedOutputStream output) throws IOException {
1448       while (true) {
1449         final int tag = readTag();
1450         if (tag == 0 || !skipField(tag, output)) {
1451           return;
1452         }
1453       }
1454     }
1455 
1456 
1457     // -----------------------------------------------------------------
1458 
1459     @Override
readDouble()1460     public double readDouble() throws IOException {
1461       return Double.longBitsToDouble(readRawLittleEndian64());
1462     }
1463 
1464     @Override
readFloat()1465     public float readFloat() throws IOException {
1466       return Float.intBitsToFloat(readRawLittleEndian32());
1467     }
1468 
1469     @Override
readUInt64()1470     public long readUInt64() throws IOException {
1471       return readRawVarint64();
1472     }
1473 
1474     @Override
readInt64()1475     public long readInt64() throws IOException {
1476       return readRawVarint64();
1477     }
1478 
1479     @Override
readInt32()1480     public int readInt32() throws IOException {
1481       return readRawVarint32();
1482     }
1483 
1484     @Override
readFixed64()1485     public long readFixed64() throws IOException {
1486       return readRawLittleEndian64();
1487     }
1488 
1489     @Override
readFixed32()1490     public int readFixed32() throws IOException {
1491       return readRawLittleEndian32();
1492     }
1493 
1494     @Override
readBool()1495     public boolean readBool() throws IOException {
1496       return readRawVarint64() != 0;
1497     }
1498 
1499     @Override
readString()1500     public String readString() throws IOException {
1501       final int size = readRawVarint32();
1502       if (size > 0 && size <= remaining()) {
1503         // TODO(nathanmittler): Is there a way to avoid this copy?
1504         // TODO(anuraaga): It might be possible to share the optimized loop with
1505         // readStringRequireUtf8 by implementing Java replacement logic there.
1506         // The same as readBytes' logic
1507         byte[] bytes = new byte[size];
1508         UnsafeUtil.copyMemory(pos, bytes, 0, size);
1509         String result = new String(bytes, UTF_8);
1510         pos += size;
1511         return result;
1512       }
1513 
1514       if (size == 0) {
1515         return "";
1516       }
1517       if (size < 0) {
1518         throw InvalidProtocolBufferException.negativeSize();
1519       }
1520       throw InvalidProtocolBufferException.truncatedMessage();
1521     }
1522 
1523     @Override
readStringRequireUtf8()1524     public String readStringRequireUtf8() throws IOException {
1525       final int size = readRawVarint32();
1526       if (size > 0 && size <= remaining()) {
1527         final int bufferPos = bufferPos(pos);
1528         String result = Utf8.decodeUtf8(buffer, bufferPos, size);
1529         pos += size;
1530         return result;
1531       }
1532 
1533       if (size == 0) {
1534         return "";
1535       }
1536       if (size <= 0) {
1537         throw InvalidProtocolBufferException.negativeSize();
1538       }
1539       throw InvalidProtocolBufferException.truncatedMessage();
1540     }
1541 
1542     @Override
readGroup( final int fieldNumber, final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)1543     public void readGroup(
1544         final int fieldNumber,
1545         final MessageLite.Builder builder,
1546         final ExtensionRegistryLite extensionRegistry)
1547         throws IOException {
1548       if (recursionDepth >= recursionLimit) {
1549         throw InvalidProtocolBufferException.recursionLimitExceeded();
1550       }
1551       ++recursionDepth;
1552       builder.mergeFrom(this, extensionRegistry);
1553       checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
1554       --recursionDepth;
1555     }
1556 
1557 
1558     @Override
readGroup( final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)1559     public <T extends MessageLite> T readGroup(
1560         final int fieldNumber,
1561         final Parser<T> parser,
1562         final ExtensionRegistryLite extensionRegistry)
1563         throws IOException {
1564       if (recursionDepth >= recursionLimit) {
1565         throw InvalidProtocolBufferException.recursionLimitExceeded();
1566       }
1567       ++recursionDepth;
1568       T result = parser.parsePartialFrom(this, extensionRegistry);
1569       checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
1570       --recursionDepth;
1571       return result;
1572     }
1573 
1574     @Deprecated
1575     @Override
readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)1576     public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
1577         throws IOException {
1578       readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
1579     }
1580 
1581     @Override
readMessage( final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)1582     public void readMessage(
1583         final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
1584         throws IOException {
1585       final int length = readRawVarint32();
1586       if (recursionDepth >= recursionLimit) {
1587         throw InvalidProtocolBufferException.recursionLimitExceeded();
1588       }
1589       final int oldLimit = pushLimit(length);
1590       ++recursionDepth;
1591       builder.mergeFrom(this, extensionRegistry);
1592       checkLastTagWas(0);
1593       --recursionDepth;
1594       popLimit(oldLimit);
1595     }
1596 
1597 
1598     @Override
readMessage( final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)1599     public <T extends MessageLite> T readMessage(
1600         final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
1601       int length = readRawVarint32();
1602       if (recursionDepth >= recursionLimit) {
1603         throw InvalidProtocolBufferException.recursionLimitExceeded();
1604       }
1605       final int oldLimit = pushLimit(length);
1606       ++recursionDepth;
1607       T result = parser.parsePartialFrom(this, extensionRegistry);
1608       checkLastTagWas(0);
1609       --recursionDepth;
1610       popLimit(oldLimit);
1611       return result;
1612     }
1613 
1614     @Override
readBytes()1615     public ByteString readBytes() throws IOException {
1616       final int size = readRawVarint32();
1617       if (size > 0 && size <= remaining()) {
1618         if (immutable && enableAliasing) {
1619           final ByteBuffer result = slice(pos, pos + size);
1620           pos += size;
1621           return ByteString.wrap(result);
1622         } else {
1623           // Use UnsafeUtil to copy the memory to bytes instead of using ByteBuffer ways.
1624           byte[] bytes = new byte[size];
1625           UnsafeUtil.copyMemory(pos, bytes, 0, size);
1626           pos += size;
1627           return ByteString.wrap(bytes);
1628         }
1629       }
1630 
1631       if (size == 0) {
1632         return ByteString.EMPTY;
1633       }
1634       if (size < 0) {
1635         throw InvalidProtocolBufferException.negativeSize();
1636       }
1637       throw InvalidProtocolBufferException.truncatedMessage();
1638     }
1639 
1640     @Override
readByteArray()1641     public byte[] readByteArray() throws IOException {
1642       return readRawBytes(readRawVarint32());
1643     }
1644 
1645     @Override
readByteBuffer()1646     public ByteBuffer readByteBuffer() throws IOException {
1647       final int size = readRawVarint32();
1648       if (size > 0 && size <= remaining()) {
1649         // "Immutable" implies that buffer is backing a ByteString.
1650         // Disallow slicing in this case to prevent the caller from modifying the contents
1651         // of the ByteString.
1652         if (!immutable && enableAliasing) {
1653           final ByteBuffer result = slice(pos, pos + size);
1654           pos += size;
1655           return result;
1656         } else {
1657           // The same as readBytes' logic
1658           byte[] bytes = new byte[size];
1659           UnsafeUtil.copyMemory(pos, bytes, 0, size);
1660           pos += size;
1661           return ByteBuffer.wrap(bytes);
1662         }
1663         // TODO(nathanmittler): Investigate making the ByteBuffer be made read-only
1664       }
1665 
1666       if (size == 0) {
1667         return EMPTY_BYTE_BUFFER;
1668       }
1669       if (size < 0) {
1670         throw InvalidProtocolBufferException.negativeSize();
1671       }
1672       throw InvalidProtocolBufferException.truncatedMessage();
1673     }
1674 
1675     @Override
readUInt32()1676     public int readUInt32() throws IOException {
1677       return readRawVarint32();
1678     }
1679 
1680     @Override
readEnum()1681     public int readEnum() throws IOException {
1682       return readRawVarint32();
1683     }
1684 
1685     @Override
readSFixed32()1686     public int readSFixed32() throws IOException {
1687       return readRawLittleEndian32();
1688     }
1689 
1690     @Override
readSFixed64()1691     public long readSFixed64() throws IOException {
1692       return readRawLittleEndian64();
1693     }
1694 
1695     @Override
readSInt32()1696     public int readSInt32() throws IOException {
1697       return decodeZigZag32(readRawVarint32());
1698     }
1699 
1700     @Override
readSInt64()1701     public long readSInt64() throws IOException {
1702       return decodeZigZag64(readRawVarint64());
1703     }
1704 
1705     // =================================================================
1706 
1707     @Override
readRawVarint32()1708     public int readRawVarint32() throws IOException {
1709       // See implementation notes for readRawVarint64
1710       fastpath:
1711       {
1712         long tempPos = pos;
1713 
1714         if (limit == tempPos) {
1715           break fastpath;
1716         }
1717 
1718         int x;
1719         if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) {
1720           pos = tempPos;
1721           return x;
1722         } else if (limit - tempPos < 9) {
1723           break fastpath;
1724         } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
1725           x ^= (~0 << 7);
1726         } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
1727           x ^= (~0 << 7) ^ (~0 << 14);
1728         } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
1729           x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
1730         } else {
1731           int y = UnsafeUtil.getByte(tempPos++);
1732           x ^= y << 28;
1733           x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
1734           if (y < 0
1735               && UnsafeUtil.getByte(tempPos++) < 0
1736               && UnsafeUtil.getByte(tempPos++) < 0
1737               && UnsafeUtil.getByte(tempPos++) < 0
1738               && UnsafeUtil.getByte(tempPos++) < 0
1739               && UnsafeUtil.getByte(tempPos++) < 0) {
1740             break fastpath; // Will throw malformedVarint()
1741           }
1742         }
1743         pos = tempPos;
1744         return x;
1745       }
1746       return (int) readRawVarint64SlowPath();
1747     }
1748 
skipRawVarint()1749     private void skipRawVarint() throws IOException {
1750       if (remaining() >= MAX_VARINT_SIZE) {
1751         skipRawVarintFastPath();
1752       } else {
1753         skipRawVarintSlowPath();
1754       }
1755     }
1756 
skipRawVarintFastPath()1757     private void skipRawVarintFastPath() throws IOException {
1758       for (int i = 0; i < MAX_VARINT_SIZE; i++) {
1759         if (UnsafeUtil.getByte(pos++) >= 0) {
1760           return;
1761         }
1762       }
1763       throw InvalidProtocolBufferException.malformedVarint();
1764     }
1765 
skipRawVarintSlowPath()1766     private void skipRawVarintSlowPath() throws IOException {
1767       for (int i = 0; i < MAX_VARINT_SIZE; i++) {
1768         if (readRawByte() >= 0) {
1769           return;
1770         }
1771       }
1772       throw InvalidProtocolBufferException.malformedVarint();
1773     }
1774 
1775     @Override
readRawVarint64()1776     public long readRawVarint64() throws IOException {
1777       // Implementation notes:
1778       //
1779       // Optimized for one-byte values, expected to be common.
1780       // The particular code below was selected from various candidates
1781       // empirically, by winning VarintBenchmark.
1782       //
1783       // Sign extension of (signed) Java bytes is usually a nuisance, but
1784       // we exploit it here to more easily obtain the sign of bytes read.
1785       // Instead of cleaning up the sign extension bits by masking eagerly,
1786       // we delay until we find the final (positive) byte, when we clear all
1787       // accumulated bits with one xor.  We depend on javac to constant fold.
1788       fastpath:
1789       {
1790         long tempPos = pos;
1791 
1792         if (limit == tempPos) {
1793           break fastpath;
1794         }
1795 
1796         long x;
1797         int y;
1798         if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) {
1799           pos = tempPos;
1800           return y;
1801         } else if (limit - tempPos < 9) {
1802           break fastpath;
1803         } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
1804           x = y ^ (~0 << 7);
1805         } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
1806           x = y ^ ((~0 << 7) ^ (~0 << 14));
1807         } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
1808           x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
1809         } else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) {
1810           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
1811         } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) {
1812           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
1813         } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) {
1814           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
1815         } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) {
1816           x ^=
1817               (~0L << 7)
1818                   ^ (~0L << 14)
1819                   ^ (~0L << 21)
1820                   ^ (~0L << 28)
1821                   ^ (~0L << 35)
1822                   ^ (~0L << 42)
1823                   ^ (~0L << 49);
1824         } else {
1825           x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56);
1826           x ^=
1827               (~0L << 7)
1828                   ^ (~0L << 14)
1829                   ^ (~0L << 21)
1830                   ^ (~0L << 28)
1831                   ^ (~0L << 35)
1832                   ^ (~0L << 42)
1833                   ^ (~0L << 49)
1834                   ^ (~0L << 56);
1835           if (x < 0L) {
1836             if (UnsafeUtil.getByte(tempPos++) < 0L) {
1837               break fastpath; // Will throw malformedVarint()
1838             }
1839           }
1840         }
1841         pos = tempPos;
1842         return x;
1843       }
1844       return readRawVarint64SlowPath();
1845     }
1846 
1847     @Override
readRawVarint64SlowPath()1848     long readRawVarint64SlowPath() throws IOException {
1849       long result = 0;
1850       for (int shift = 0; shift < 64; shift += 7) {
1851         final byte b = readRawByte();
1852         result |= (long) (b & 0x7F) << shift;
1853         if ((b & 0x80) == 0) {
1854           return result;
1855         }
1856       }
1857       throw InvalidProtocolBufferException.malformedVarint();
1858     }
1859 
1860     @Override
readRawLittleEndian32()1861     public int readRawLittleEndian32() throws IOException {
1862       long tempPos = pos;
1863 
1864       if (limit - tempPos < FIXED32_SIZE) {
1865         throw InvalidProtocolBufferException.truncatedMessage();
1866       }
1867 
1868       pos = tempPos + FIXED32_SIZE;
1869       return (((UnsafeUtil.getByte(tempPos) & 0xff))
1870           | ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8)
1871           | ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16)
1872           | ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24));
1873     }
1874 
1875     @Override
readRawLittleEndian64()1876     public long readRawLittleEndian64() throws IOException {
1877       long tempPos = pos;
1878 
1879       if (limit - tempPos < FIXED64_SIZE) {
1880         throw InvalidProtocolBufferException.truncatedMessage();
1881       }
1882 
1883       pos = tempPos + FIXED64_SIZE;
1884       return (((UnsafeUtil.getByte(tempPos) & 0xffL))
1885           | ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8)
1886           | ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16)
1887           | ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24)
1888           | ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32)
1889           | ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40)
1890           | ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48)
1891           | ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56));
1892     }
1893 
1894     @Override
enableAliasing(boolean enabled)1895     public void enableAliasing(boolean enabled) {
1896       this.enableAliasing = enabled;
1897     }
1898 
1899     @Override
resetSizeCounter()1900     public void resetSizeCounter() {
1901       startPos = pos;
1902     }
1903 
1904     @Override
pushLimit(int byteLimit)1905     public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
1906       if (byteLimit < 0) {
1907         throw InvalidProtocolBufferException.negativeSize();
1908       }
1909       byteLimit += getTotalBytesRead();
1910       final int oldLimit = currentLimit;
1911       if (byteLimit > oldLimit) {
1912         throw InvalidProtocolBufferException.truncatedMessage();
1913       }
1914       currentLimit = byteLimit;
1915 
1916       recomputeBufferSizeAfterLimit();
1917 
1918       return oldLimit;
1919     }
1920 
1921     @Override
popLimit(final int oldLimit)1922     public void popLimit(final int oldLimit) {
1923       currentLimit = oldLimit;
1924       recomputeBufferSizeAfterLimit();
1925     }
1926 
1927     @Override
getBytesUntilLimit()1928     public int getBytesUntilLimit() {
1929       if (currentLimit == Integer.MAX_VALUE) {
1930         return -1;
1931       }
1932 
1933       return currentLimit - getTotalBytesRead();
1934     }
1935 
1936     @Override
isAtEnd()1937     public boolean isAtEnd() throws IOException {
1938       return pos == limit;
1939     }
1940 
1941     @Override
getTotalBytesRead()1942     public int getTotalBytesRead() {
1943       return (int) (pos - startPos);
1944     }
1945 
1946     @Override
readRawByte()1947     public byte readRawByte() throws IOException {
1948       if (pos == limit) {
1949         throw InvalidProtocolBufferException.truncatedMessage();
1950       }
1951       return UnsafeUtil.getByte(pos++);
1952     }
1953 
1954     @Override
readRawBytes(final int length)1955     public byte[] readRawBytes(final int length) throws IOException {
1956       if (length >= 0 && length <= remaining()) {
1957         byte[] bytes = new byte[length];
1958         slice(pos, pos + length).get(bytes);
1959         pos += length;
1960         return bytes;
1961       }
1962 
1963       if (length <= 0) {
1964         if (length == 0) {
1965           return EMPTY_BYTE_ARRAY;
1966         } else {
1967           throw InvalidProtocolBufferException.negativeSize();
1968         }
1969       }
1970 
1971       throw InvalidProtocolBufferException.truncatedMessage();
1972     }
1973 
1974     @Override
skipRawBytes(final int length)1975     public void skipRawBytes(final int length) throws IOException {
1976       if (length >= 0 && length <= remaining()) {
1977         // We have all the bytes we need already.
1978         pos += length;
1979         return;
1980       }
1981 
1982       if (length < 0) {
1983         throw InvalidProtocolBufferException.negativeSize();
1984       }
1985       throw InvalidProtocolBufferException.truncatedMessage();
1986     }
1987 
recomputeBufferSizeAfterLimit()1988     private void recomputeBufferSizeAfterLimit() {
1989       limit += bufferSizeAfterLimit;
1990       final int bufferEnd = (int) (limit - startPos);
1991       if (bufferEnd > currentLimit) {
1992         // Limit is in current buffer.
1993         bufferSizeAfterLimit = bufferEnd - currentLimit;
1994         limit -= bufferSizeAfterLimit;
1995       } else {
1996         bufferSizeAfterLimit = 0;
1997       }
1998     }
1999 
remaining()2000     private int remaining() {
2001       return (int) (limit - pos);
2002     }
2003 
bufferPos(long pos)2004     private int bufferPos(long pos) {
2005       return (int) (pos - address);
2006     }
2007 
slice(long begin, long end)2008     private ByteBuffer slice(long begin, long end) throws IOException {
2009       int prevPos = buffer.position();
2010       int prevLimit = buffer.limit();
2011       try {
2012         buffer.position(bufferPos(begin));
2013         buffer.limit(bufferPos(end));
2014         return buffer.slice();
2015       } catch (IllegalArgumentException e) {
2016         throw InvalidProtocolBufferException.truncatedMessage();
2017       } finally {
2018         buffer.position(prevPos);
2019         buffer.limit(prevLimit);
2020       }
2021     }
2022   }
2023 
2024   /**
2025    * Implementation of {@link CodedInputStream} that uses an {@link InputStream} as the data source.
2026    */
2027   private static final class StreamDecoder extends CodedInputStream {
2028     private final InputStream input;
2029     private final byte[] buffer;
2030     /** bufferSize represents how many bytes are currently filled in the buffer */
2031     private int bufferSize;
2032 
2033     private int bufferSizeAfterLimit;
2034     private int pos;
2035     private int lastTag;
2036 
2037     /**
2038      * The total number of bytes read before the current buffer. The total bytes read up to the
2039      * current position can be computed as {@code totalBytesRetired + pos}. This value may be
2040      * negative if reading started in the middle of the current buffer (e.g. if the constructor that
2041      * takes a byte array and an offset was used).
2042      */
2043     private int totalBytesRetired;
2044 
2045     /** The absolute position of the end of the current message. */
2046     private int currentLimit = Integer.MAX_VALUE;
2047 
StreamDecoder(final InputStream input, int bufferSize)2048     private StreamDecoder(final InputStream input, int bufferSize) {
2049       checkNotNull(input, "input");
2050       this.input = input;
2051       this.buffer = new byte[bufferSize];
2052       this.bufferSize = 0;
2053       pos = 0;
2054       totalBytesRetired = 0;
2055     }
2056 
2057     @Override
readTag()2058     public int readTag() throws IOException {
2059       if (isAtEnd()) {
2060         lastTag = 0;
2061         return 0;
2062       }
2063 
2064       lastTag = readRawVarint32();
2065       if (WireFormat.getTagFieldNumber(lastTag) == 0) {
2066         // If we actually read zero (or any tag number corresponding to field
2067         // number zero), that's not a valid tag.
2068         throw InvalidProtocolBufferException.invalidTag();
2069       }
2070       return lastTag;
2071     }
2072 
2073     @Override
checkLastTagWas(final int value)2074     public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
2075       if (lastTag != value) {
2076         throw InvalidProtocolBufferException.invalidEndTag();
2077       }
2078     }
2079 
2080     @Override
getLastTag()2081     public int getLastTag() {
2082       return lastTag;
2083     }
2084 
2085     @Override
skipField(final int tag)2086     public boolean skipField(final int tag) throws IOException {
2087       switch (WireFormat.getTagWireType(tag)) {
2088         case WireFormat.WIRETYPE_VARINT:
2089           skipRawVarint();
2090           return true;
2091         case WireFormat.WIRETYPE_FIXED64:
2092           skipRawBytes(FIXED64_SIZE);
2093           return true;
2094         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
2095           skipRawBytes(readRawVarint32());
2096           return true;
2097         case WireFormat.WIRETYPE_START_GROUP:
2098           skipMessage();
2099           checkLastTagWas(
2100               WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
2101           return true;
2102         case WireFormat.WIRETYPE_END_GROUP:
2103           return false;
2104         case WireFormat.WIRETYPE_FIXED32:
2105           skipRawBytes(FIXED32_SIZE);
2106           return true;
2107         default:
2108           throw InvalidProtocolBufferException.invalidWireType();
2109       }
2110     }
2111 
2112     @Override
skipField(final int tag, final CodedOutputStream output)2113     public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
2114       switch (WireFormat.getTagWireType(tag)) {
2115         case WireFormat.WIRETYPE_VARINT:
2116           {
2117             long value = readInt64();
2118             output.writeRawVarint32(tag);
2119             output.writeUInt64NoTag(value);
2120             return true;
2121           }
2122         case WireFormat.WIRETYPE_FIXED64:
2123           {
2124             long value = readRawLittleEndian64();
2125             output.writeRawVarint32(tag);
2126             output.writeFixed64NoTag(value);
2127             return true;
2128           }
2129         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
2130           {
2131             ByteString value = readBytes();
2132             output.writeRawVarint32(tag);
2133             output.writeBytesNoTag(value);
2134             return true;
2135           }
2136         case WireFormat.WIRETYPE_START_GROUP:
2137           {
2138             output.writeRawVarint32(tag);
2139             skipMessage(output);
2140             int endtag =
2141                 WireFormat.makeTag(
2142                     WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
2143             checkLastTagWas(endtag);
2144             output.writeRawVarint32(endtag);
2145             return true;
2146           }
2147         case WireFormat.WIRETYPE_END_GROUP:
2148           {
2149             return false;
2150           }
2151         case WireFormat.WIRETYPE_FIXED32:
2152           {
2153             int value = readRawLittleEndian32();
2154             output.writeRawVarint32(tag);
2155             output.writeFixed32NoTag(value);
2156             return true;
2157           }
2158         default:
2159           throw InvalidProtocolBufferException.invalidWireType();
2160       }
2161     }
2162 
2163     @Override
skipMessage()2164     public void skipMessage() throws IOException {
2165       while (true) {
2166         final int tag = readTag();
2167         if (tag == 0 || !skipField(tag)) {
2168           return;
2169         }
2170       }
2171     }
2172 
2173     @Override
skipMessage(CodedOutputStream output)2174     public void skipMessage(CodedOutputStream output) throws IOException {
2175       while (true) {
2176         final int tag = readTag();
2177         if (tag == 0 || !skipField(tag, output)) {
2178           return;
2179         }
2180       }
2181     }
2182 
2183     /** Collects the bytes skipped and returns the data in a ByteBuffer. */
2184     private class SkippedDataSink implements RefillCallback {
2185       private int lastPos = pos;
2186       private ByteArrayOutputStream byteArrayStream;
2187 
2188       @Override
onRefill()2189       public void onRefill() {
2190         if (byteArrayStream == null) {
2191           byteArrayStream = new ByteArrayOutputStream();
2192         }
2193         byteArrayStream.write(buffer, lastPos, pos - lastPos);
2194         lastPos = 0;
2195       }
2196 
2197       /** Gets skipped data in a ByteBuffer. This method should only be called once. */
getSkippedData()2198       ByteBuffer getSkippedData() {
2199         if (byteArrayStream == null) {
2200           return ByteBuffer.wrap(buffer, lastPos, pos - lastPos);
2201         } else {
2202           byteArrayStream.write(buffer, lastPos, pos);
2203           return ByteBuffer.wrap(byteArrayStream.toByteArray());
2204         }
2205       }
2206     }
2207 
2208 
2209     // -----------------------------------------------------------------
2210 
2211     @Override
readDouble()2212     public double readDouble() throws IOException {
2213       return Double.longBitsToDouble(readRawLittleEndian64());
2214     }
2215 
2216     @Override
readFloat()2217     public float readFloat() throws IOException {
2218       return Float.intBitsToFloat(readRawLittleEndian32());
2219     }
2220 
2221     @Override
readUInt64()2222     public long readUInt64() throws IOException {
2223       return readRawVarint64();
2224     }
2225 
2226     @Override
readInt64()2227     public long readInt64() throws IOException {
2228       return readRawVarint64();
2229     }
2230 
2231     @Override
readInt32()2232     public int readInt32() throws IOException {
2233       return readRawVarint32();
2234     }
2235 
2236     @Override
readFixed64()2237     public long readFixed64() throws IOException {
2238       return readRawLittleEndian64();
2239     }
2240 
2241     @Override
readFixed32()2242     public int readFixed32() throws IOException {
2243       return readRawLittleEndian32();
2244     }
2245 
2246     @Override
readBool()2247     public boolean readBool() throws IOException {
2248       return readRawVarint64() != 0;
2249     }
2250 
2251     @Override
readString()2252     public String readString() throws IOException {
2253       final int size = readRawVarint32();
2254       if (size > 0 && size <= (bufferSize - pos)) {
2255         // Fast path:  We already have the bytes in a contiguous buffer, so
2256         //   just copy directly from it.
2257         final String result = new String(buffer, pos, size, UTF_8);
2258         pos += size;
2259         return result;
2260       }
2261       if (size == 0) {
2262         return "";
2263       }
2264       if (size <= bufferSize) {
2265         refillBuffer(size);
2266         String result = new String(buffer, pos, size, UTF_8);
2267         pos += size;
2268         return result;
2269       }
2270       // Slow path:  Build a byte array first then copy it.
2271       return new String(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false), UTF_8);
2272     }
2273 
2274     @Override
readStringRequireUtf8()2275     public String readStringRequireUtf8() throws IOException {
2276       final int size = readRawVarint32();
2277       final byte[] bytes;
2278       final int oldPos = pos;
2279       final int tempPos;
2280       if (size <= (bufferSize - oldPos) && size > 0) {
2281         // Fast path:  We already have the bytes in a contiguous buffer, so
2282         //   just copy directly from it.
2283         bytes = buffer;
2284         pos = oldPos + size;
2285         tempPos = oldPos;
2286       } else if (size == 0) {
2287         return "";
2288       } else if (size <= bufferSize) {
2289         refillBuffer(size);
2290         bytes = buffer;
2291         tempPos = 0;
2292         pos = tempPos + size;
2293       } else {
2294         // Slow path:  Build a byte array first then copy it.
2295         bytes = readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false);
2296         tempPos = 0;
2297       }
2298       return Utf8.decodeUtf8(bytes, tempPos, size);
2299     }
2300 
2301     @Override
readGroup( final int fieldNumber, final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)2302     public void readGroup(
2303         final int fieldNumber,
2304         final MessageLite.Builder builder,
2305         final ExtensionRegistryLite extensionRegistry)
2306         throws IOException {
2307       if (recursionDepth >= recursionLimit) {
2308         throw InvalidProtocolBufferException.recursionLimitExceeded();
2309       }
2310       ++recursionDepth;
2311       builder.mergeFrom(this, extensionRegistry);
2312       checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
2313       --recursionDepth;
2314     }
2315 
2316 
2317     @Override
readGroup( final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)2318     public <T extends MessageLite> T readGroup(
2319         final int fieldNumber,
2320         final Parser<T> parser,
2321         final ExtensionRegistryLite extensionRegistry)
2322         throws IOException {
2323       if (recursionDepth >= recursionLimit) {
2324         throw InvalidProtocolBufferException.recursionLimitExceeded();
2325       }
2326       ++recursionDepth;
2327       T result = parser.parsePartialFrom(this, extensionRegistry);
2328       checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
2329       --recursionDepth;
2330       return result;
2331     }
2332 
2333     @Deprecated
2334     @Override
readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)2335     public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
2336         throws IOException {
2337       readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
2338     }
2339 
2340     @Override
readMessage( final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)2341     public void readMessage(
2342         final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
2343         throws IOException {
2344       final int length = readRawVarint32();
2345       if (recursionDepth >= recursionLimit) {
2346         throw InvalidProtocolBufferException.recursionLimitExceeded();
2347       }
2348       final int oldLimit = pushLimit(length);
2349       ++recursionDepth;
2350       builder.mergeFrom(this, extensionRegistry);
2351       checkLastTagWas(0);
2352       --recursionDepth;
2353       popLimit(oldLimit);
2354     }
2355 
2356 
2357     @Override
readMessage( final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)2358     public <T extends MessageLite> T readMessage(
2359         final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
2360       int length = readRawVarint32();
2361       if (recursionDepth >= recursionLimit) {
2362         throw InvalidProtocolBufferException.recursionLimitExceeded();
2363       }
2364       final int oldLimit = pushLimit(length);
2365       ++recursionDepth;
2366       T result = parser.parsePartialFrom(this, extensionRegistry);
2367       checkLastTagWas(0);
2368       --recursionDepth;
2369       popLimit(oldLimit);
2370       return result;
2371     }
2372 
2373     @Override
readBytes()2374     public ByteString readBytes() throws IOException {
2375       final int size = readRawVarint32();
2376       if (size <= (bufferSize - pos) && size > 0) {
2377         // Fast path:  We already have the bytes in a contiguous buffer, so
2378         //   just copy directly from it.
2379         final ByteString result = ByteString.copyFrom(buffer, pos, size);
2380         pos += size;
2381         return result;
2382       }
2383       if (size == 0) {
2384         return ByteString.EMPTY;
2385       }
2386       return readBytesSlowPath(size);
2387     }
2388 
2389     @Override
readByteArray()2390     public byte[] readByteArray() throws IOException {
2391       final int size = readRawVarint32();
2392       if (size <= (bufferSize - pos) && size > 0) {
2393         // Fast path: We already have the bytes in a contiguous buffer, so
2394         // just copy directly from it.
2395         final byte[] result = Arrays.copyOfRange(buffer, pos, pos + size);
2396         pos += size;
2397         return result;
2398       } else {
2399         // Slow path: Build a byte array first then copy it.
2400         // TODO(dweis): Do we want to protect from malicious input streams here?
2401         return readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false);
2402       }
2403     }
2404 
2405     @Override
readByteBuffer()2406     public ByteBuffer readByteBuffer() throws IOException {
2407       final int size = readRawVarint32();
2408       if (size <= (bufferSize - pos) && size > 0) {
2409         // Fast path: We already have the bytes in a contiguous buffer.
2410         ByteBuffer result = ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size));
2411         pos += size;
2412         return result;
2413       }
2414       if (size == 0) {
2415         return Internal.EMPTY_BYTE_BUFFER;
2416       }
2417       // Slow path: Build a byte array first then copy it.
2418 
2419       // We must copy as the byte array was handed off to the InputStream and a malicious
2420       // implementation could retain a reference.
2421       return ByteBuffer.wrap(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ true));
2422     }
2423 
2424     @Override
readUInt32()2425     public int readUInt32() throws IOException {
2426       return readRawVarint32();
2427     }
2428 
2429     @Override
readEnum()2430     public int readEnum() throws IOException {
2431       return readRawVarint32();
2432     }
2433 
2434     @Override
readSFixed32()2435     public int readSFixed32() throws IOException {
2436       return readRawLittleEndian32();
2437     }
2438 
2439     @Override
readSFixed64()2440     public long readSFixed64() throws IOException {
2441       return readRawLittleEndian64();
2442     }
2443 
2444     @Override
readSInt32()2445     public int readSInt32() throws IOException {
2446       return decodeZigZag32(readRawVarint32());
2447     }
2448 
2449     @Override
readSInt64()2450     public long readSInt64() throws IOException {
2451       return decodeZigZag64(readRawVarint64());
2452     }
2453 
2454     // =================================================================
2455 
2456     @Override
readRawVarint32()2457     public int readRawVarint32() throws IOException {
2458       // See implementation notes for readRawVarint64
2459       fastpath:
2460       {
2461         int tempPos = pos;
2462 
2463         if (bufferSize == tempPos) {
2464           break fastpath;
2465         }
2466 
2467         final byte[] buffer = this.buffer;
2468         int x;
2469         if ((x = buffer[tempPos++]) >= 0) {
2470           pos = tempPos;
2471           return x;
2472         } else if (bufferSize - tempPos < 9) {
2473           break fastpath;
2474         } else if ((x ^= (buffer[tempPos++] << 7)) < 0) {
2475           x ^= (~0 << 7);
2476         } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) {
2477           x ^= (~0 << 7) ^ (~0 << 14);
2478         } else if ((x ^= (buffer[tempPos++] << 21)) < 0) {
2479           x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
2480         } else {
2481           int y = buffer[tempPos++];
2482           x ^= y << 28;
2483           x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
2484           if (y < 0
2485               && buffer[tempPos++] < 0
2486               && buffer[tempPos++] < 0
2487               && buffer[tempPos++] < 0
2488               && buffer[tempPos++] < 0
2489               && buffer[tempPos++] < 0) {
2490             break fastpath; // Will throw malformedVarint()
2491           }
2492         }
2493         pos = tempPos;
2494         return x;
2495       }
2496       return (int) readRawVarint64SlowPath();
2497     }
2498 
skipRawVarint()2499     private void skipRawVarint() throws IOException {
2500       if (bufferSize - pos >= MAX_VARINT_SIZE) {
2501         skipRawVarintFastPath();
2502       } else {
2503         skipRawVarintSlowPath();
2504       }
2505     }
2506 
skipRawVarintFastPath()2507     private void skipRawVarintFastPath() throws IOException {
2508       for (int i = 0; i < MAX_VARINT_SIZE; i++) {
2509         if (buffer[pos++] >= 0) {
2510           return;
2511         }
2512       }
2513       throw InvalidProtocolBufferException.malformedVarint();
2514     }
2515 
skipRawVarintSlowPath()2516     private void skipRawVarintSlowPath() throws IOException {
2517       for (int i = 0; i < MAX_VARINT_SIZE; i++) {
2518         if (readRawByte() >= 0) {
2519           return;
2520         }
2521       }
2522       throw InvalidProtocolBufferException.malformedVarint();
2523     }
2524 
2525     @Override
readRawVarint64()2526     public long readRawVarint64() throws IOException {
2527       // Implementation notes:
2528       //
2529       // Optimized for one-byte values, expected to be common.
2530       // The particular code below was selected from various candidates
2531       // empirically, by winning VarintBenchmark.
2532       //
2533       // Sign extension of (signed) Java bytes is usually a nuisance, but
2534       // we exploit it here to more easily obtain the sign of bytes read.
2535       // Instead of cleaning up the sign extension bits by masking eagerly,
2536       // we delay until we find the final (positive) byte, when we clear all
2537       // accumulated bits with one xor.  We depend on javac to constant fold.
2538       fastpath:
2539       {
2540         int tempPos = pos;
2541 
2542         if (bufferSize == tempPos) {
2543           break fastpath;
2544         }
2545 
2546         final byte[] buffer = this.buffer;
2547         long x;
2548         int y;
2549         if ((y = buffer[tempPos++]) >= 0) {
2550           pos = tempPos;
2551           return y;
2552         } else if (bufferSize - tempPos < 9) {
2553           break fastpath;
2554         } else if ((y ^= (buffer[tempPos++] << 7)) < 0) {
2555           x = y ^ (~0 << 7);
2556         } else if ((y ^= (buffer[tempPos++] << 14)) >= 0) {
2557           x = y ^ ((~0 << 7) ^ (~0 << 14));
2558         } else if ((y ^= (buffer[tempPos++] << 21)) < 0) {
2559           x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
2560         } else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) {
2561           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
2562         } else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) {
2563           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
2564         } else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) {
2565           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
2566         } else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) {
2567           x ^=
2568               (~0L << 7)
2569                   ^ (~0L << 14)
2570                   ^ (~0L << 21)
2571                   ^ (~0L << 28)
2572                   ^ (~0L << 35)
2573                   ^ (~0L << 42)
2574                   ^ (~0L << 49);
2575         } else {
2576           x ^= ((long) buffer[tempPos++] << 56);
2577           x ^=
2578               (~0L << 7)
2579                   ^ (~0L << 14)
2580                   ^ (~0L << 21)
2581                   ^ (~0L << 28)
2582                   ^ (~0L << 35)
2583                   ^ (~0L << 42)
2584                   ^ (~0L << 49)
2585                   ^ (~0L << 56);
2586           if (x < 0L) {
2587             if (buffer[tempPos++] < 0L) {
2588               break fastpath; // Will throw malformedVarint()
2589             }
2590           }
2591         }
2592         pos = tempPos;
2593         return x;
2594       }
2595       return readRawVarint64SlowPath();
2596     }
2597 
2598     @Override
readRawVarint64SlowPath()2599     long readRawVarint64SlowPath() throws IOException {
2600       long result = 0;
2601       for (int shift = 0; shift < 64; shift += 7) {
2602         final byte b = readRawByte();
2603         result |= (long) (b & 0x7F) << shift;
2604         if ((b & 0x80) == 0) {
2605           return result;
2606         }
2607       }
2608       throw InvalidProtocolBufferException.malformedVarint();
2609     }
2610 
2611     @Override
readRawLittleEndian32()2612     public int readRawLittleEndian32() throws IOException {
2613       int tempPos = pos;
2614 
2615       if (bufferSize - tempPos < FIXED32_SIZE) {
2616         refillBuffer(FIXED32_SIZE);
2617         tempPos = pos;
2618       }
2619 
2620       final byte[] buffer = this.buffer;
2621       pos = tempPos + FIXED32_SIZE;
2622       return (((buffer[tempPos] & 0xff))
2623           | ((buffer[tempPos + 1] & 0xff) << 8)
2624           | ((buffer[tempPos + 2] & 0xff) << 16)
2625           | ((buffer[tempPos + 3] & 0xff) << 24));
2626     }
2627 
2628     @Override
readRawLittleEndian64()2629     public long readRawLittleEndian64() throws IOException {
2630       int tempPos = pos;
2631 
2632       if (bufferSize - tempPos < FIXED64_SIZE) {
2633         refillBuffer(FIXED64_SIZE);
2634         tempPos = pos;
2635       }
2636 
2637       final byte[] buffer = this.buffer;
2638       pos = tempPos + FIXED64_SIZE;
2639       return (((buffer[tempPos] & 0xffL))
2640           | ((buffer[tempPos + 1] & 0xffL) << 8)
2641           | ((buffer[tempPos + 2] & 0xffL) << 16)
2642           | ((buffer[tempPos + 3] & 0xffL) << 24)
2643           | ((buffer[tempPos + 4] & 0xffL) << 32)
2644           | ((buffer[tempPos + 5] & 0xffL) << 40)
2645           | ((buffer[tempPos + 6] & 0xffL) << 48)
2646           | ((buffer[tempPos + 7] & 0xffL) << 56));
2647     }
2648 
2649     // -----------------------------------------------------------------
2650 
2651     @Override
enableAliasing(boolean enabled)2652     public void enableAliasing(boolean enabled) {
2653       // TODO(nathanmittler): Ideally we should throw here. Do nothing for backward compatibility.
2654     }
2655 
2656     @Override
resetSizeCounter()2657     public void resetSizeCounter() {
2658       totalBytesRetired = -pos;
2659     }
2660 
2661     @Override
pushLimit(int byteLimit)2662     public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
2663       if (byteLimit < 0) {
2664         throw InvalidProtocolBufferException.negativeSize();
2665       }
2666       byteLimit += totalBytesRetired + pos;
2667       final int oldLimit = currentLimit;
2668       if (byteLimit > oldLimit) {
2669         throw InvalidProtocolBufferException.truncatedMessage();
2670       }
2671       currentLimit = byteLimit;
2672 
2673       recomputeBufferSizeAfterLimit();
2674 
2675       return oldLimit;
2676     }
2677 
recomputeBufferSizeAfterLimit()2678     private void recomputeBufferSizeAfterLimit() {
2679       bufferSize += bufferSizeAfterLimit;
2680       final int bufferEnd = totalBytesRetired + bufferSize;
2681       if (bufferEnd > currentLimit) {
2682         // Limit is in current buffer.
2683         bufferSizeAfterLimit = bufferEnd - currentLimit;
2684         bufferSize -= bufferSizeAfterLimit;
2685       } else {
2686         bufferSizeAfterLimit = 0;
2687       }
2688     }
2689 
2690     @Override
popLimit(final int oldLimit)2691     public void popLimit(final int oldLimit) {
2692       currentLimit = oldLimit;
2693       recomputeBufferSizeAfterLimit();
2694     }
2695 
2696     @Override
getBytesUntilLimit()2697     public int getBytesUntilLimit() {
2698       if (currentLimit == Integer.MAX_VALUE) {
2699         return -1;
2700       }
2701 
2702       final int currentAbsolutePosition = totalBytesRetired + pos;
2703       return currentLimit - currentAbsolutePosition;
2704     }
2705 
2706     @Override
isAtEnd()2707     public boolean isAtEnd() throws IOException {
2708       return pos == bufferSize && !tryRefillBuffer(1);
2709     }
2710 
2711     @Override
getTotalBytesRead()2712     public int getTotalBytesRead() {
2713       return totalBytesRetired + pos;
2714     }
2715 
2716     private interface RefillCallback {
onRefill()2717       void onRefill();
2718     }
2719 
2720     private RefillCallback refillCallback = null;
2721 
2722     /**
2723      * Reads more bytes from the input, making at least {@code n} bytes available in the buffer.
2724      * Caller must ensure that the requested space is not yet available, and that the requested
2725      * space is less than BUFFER_SIZE.
2726      *
2727      * @throws InvalidProtocolBufferException The end of the stream or the current limit was
2728      *     reached.
2729      */
refillBuffer(int n)2730     private void refillBuffer(int n) throws IOException {
2731       if (!tryRefillBuffer(n)) {
2732         // We have to distinguish the exception between sizeLimitExceeded and truncatedMessage. So
2733         // we just throw an sizeLimitExceeded exception here if it exceeds the sizeLimit
2734         if (n > sizeLimit - totalBytesRetired - pos) {
2735           throw InvalidProtocolBufferException.sizeLimitExceeded();
2736         } else {
2737           throw InvalidProtocolBufferException.truncatedMessage();
2738         }
2739       }
2740     }
2741 
2742     /**
2743      * Tries to read more bytes from the input, making at least {@code n} bytes available in the
2744      * buffer. Caller must ensure that the requested space is not yet available, and that the
2745      * requested space is less than BUFFER_SIZE.
2746      *
2747      * @return {@code true} If the bytes could be made available; {@code false} 1. Current at the
2748      *     end of the stream 2. The current limit was reached 3. The total size limit was reached
2749      */
tryRefillBuffer(int n)2750     private boolean tryRefillBuffer(int n) throws IOException {
2751       if (pos + n <= bufferSize) {
2752         throw new IllegalStateException(
2753             "refillBuffer() called when " + n + " bytes were already available in buffer");
2754       }
2755 
2756       // Check whether the size of total message needs to read is bigger than the size limit.
2757       // We shouldn't throw an exception here as isAtEnd() function needs to get this function's
2758       // return as the result.
2759       if (n > sizeLimit - totalBytesRetired - pos) {
2760         return false;
2761       }
2762 
2763       // Shouldn't throw the exception here either.
2764       if (totalBytesRetired + pos + n > currentLimit) {
2765         // Oops, we hit a limit.
2766         return false;
2767       }
2768 
2769       if (refillCallback != null) {
2770         refillCallback.onRefill();
2771       }
2772 
2773       int tempPos = pos;
2774       if (tempPos > 0) {
2775         if (bufferSize > tempPos) {
2776           System.arraycopy(buffer, tempPos, buffer, 0, bufferSize - tempPos);
2777         }
2778         totalBytesRetired += tempPos;
2779         bufferSize -= tempPos;
2780         pos = 0;
2781       }
2782 
2783       // Here we should refill the buffer as many bytes as possible.
2784       int bytesRead =
2785           input.read(
2786               buffer,
2787               bufferSize,
2788               Math.min(
2789                   //  the size of allocated but unused bytes in the buffer
2790                   buffer.length - bufferSize,
2791                   //  do not exceed the total bytes limit
2792                   sizeLimit - totalBytesRetired - bufferSize));
2793       if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
2794         throw new IllegalStateException(
2795             input.getClass()
2796                 + "#read(byte[]) returned invalid result: "
2797                 + bytesRead
2798                 + "\nThe InputStream implementation is buggy.");
2799       }
2800       if (bytesRead > 0) {
2801         bufferSize += bytesRead;
2802         recomputeBufferSizeAfterLimit();
2803         return (bufferSize >= n) ? true : tryRefillBuffer(n);
2804       }
2805 
2806       return false;
2807     }
2808 
2809     @Override
readRawByte()2810     public byte readRawByte() throws IOException {
2811       if (pos == bufferSize) {
2812         refillBuffer(1);
2813       }
2814       return buffer[pos++];
2815     }
2816 
2817     @Override
readRawBytes(final int size)2818     public byte[] readRawBytes(final int size) throws IOException {
2819       final int tempPos = pos;
2820       if (size <= (bufferSize - tempPos) && size > 0) {
2821         pos = tempPos + size;
2822         return Arrays.copyOfRange(buffer, tempPos, tempPos + size);
2823       } else {
2824         // TODO(dweis): Do we want to protect from malicious input streams here?
2825         return readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false);
2826       }
2827     }
2828 
2829     /**
2830      * Exactly like readRawBytes, but caller must have already checked the fast path: (size <=
2831      * (bufferSize - pos) && size > 0)
2832      *
2833      * If ensureNoLeakedReferences is true, the value is guaranteed to have not escaped to
2834      * untrusted code.
2835      */
readRawBytesSlowPath( final int size, boolean ensureNoLeakedReferences)2836     private byte[] readRawBytesSlowPath(
2837         final int size, boolean ensureNoLeakedReferences) throws IOException {
2838       // Attempt to read the data in one byte array when it's safe to do.
2839       byte[] result = readRawBytesSlowPathOneChunk(size);
2840       if (result != null) {
2841         return ensureNoLeakedReferences ? result.clone() : result;
2842       }
2843 
2844       final int originalBufferPos = pos;
2845       final int bufferedBytes = bufferSize - pos;
2846 
2847       // Mark the current buffer consumed.
2848       totalBytesRetired += bufferSize;
2849       pos = 0;
2850       bufferSize = 0;
2851 
2852       // Determine the number of bytes we need to read from the input stream.
2853       int sizeLeft = size - bufferedBytes;
2854 
2855       // The size is very large. For security reasons we read them in small
2856       // chunks.
2857       List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
2858 
2859       // OK, got everything.  Now concatenate it all into one buffer.
2860       final byte[] bytes = new byte[size];
2861 
2862       // Start by copying the leftover bytes from this.buffer.
2863       System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
2864 
2865       // And now all the chunks.
2866       int tempPos = bufferedBytes;
2867       for (final byte[] chunk : chunks) {
2868         System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
2869         tempPos += chunk.length;
2870       }
2871 
2872       // Done.
2873       return bytes;
2874     }
2875 
2876     /**
2877      * Attempts to read the data in one byte array when it's safe to do. Returns null if the size to
2878      * read is too large and needs to be allocated in smaller chunks for security reasons.
2879      *
2880      * Returns a byte[] that may have escaped to user code via InputStream APIs.
2881      */
readRawBytesSlowPathOneChunk(final int size)2882     private byte[] readRawBytesSlowPathOneChunk(final int size) throws IOException {
2883       if (size == 0) {
2884         return Internal.EMPTY_BYTE_ARRAY;
2885       }
2886       if (size < 0) {
2887         throw InvalidProtocolBufferException.negativeSize();
2888       }
2889 
2890       // Integer-overflow-conscious check that the message size so far has not exceeded sizeLimit.
2891       int currentMessageSize = totalBytesRetired + pos + size;
2892       if (currentMessageSize - sizeLimit > 0) {
2893         throw InvalidProtocolBufferException.sizeLimitExceeded();
2894       }
2895 
2896       // Verify that the message size so far has not exceeded currentLimit.
2897       if (currentMessageSize > currentLimit) {
2898         // Read to the end of the stream anyway.
2899         skipRawBytes(currentLimit - totalBytesRetired - pos);
2900         throw InvalidProtocolBufferException.truncatedMessage();
2901       }
2902 
2903       final int bufferedBytes = bufferSize - pos;
2904       // Determine the number of bytes we need to read from the input stream.
2905       int sizeLeft = size - bufferedBytes;
2906       // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_SIZE.
2907       if (sizeLeft < DEFAULT_BUFFER_SIZE || sizeLeft <= input.available()) {
2908         // Either the bytes we need are known to be available, or the required buffer is
2909         // within an allowed threshold - go ahead and allocate the buffer now.
2910         final byte[] bytes = new byte[size];
2911 
2912         // Copy all of the buffered bytes to the result buffer.
2913         System.arraycopy(buffer, pos, bytes, 0, bufferedBytes);
2914         totalBytesRetired += bufferSize;
2915         pos = 0;
2916         bufferSize = 0;
2917 
2918         // Fill the remaining bytes from the input stream.
2919         int tempPos = bufferedBytes;
2920         while (tempPos < bytes.length) {
2921           int n = input.read(bytes, tempPos, size - tempPos);
2922           if (n == -1) {
2923             throw InvalidProtocolBufferException.truncatedMessage();
2924           }
2925           totalBytesRetired += n;
2926           tempPos += n;
2927         }
2928 
2929         return bytes;
2930       }
2931 
2932       return null;
2933     }
2934 
2935     /**
2936      * Reads the remaining data in small chunks from the input stream.
2937      *
2938      * Returns a byte[] that may have escaped to user code via InputStream APIs.
2939      */
readRawBytesSlowPathRemainingChunks(int sizeLeft)2940     private List<byte[]> readRawBytesSlowPathRemainingChunks(int sizeLeft) throws IOException {
2941       // The size is very large.  For security reasons, we can't allocate the
2942       // entire byte array yet.  The size comes directly from the input, so a
2943       // maliciously-crafted message could provide a bogus very large size in
2944       // order to trick the app into allocating a lot of memory.  We avoid this
2945       // by allocating and reading only a small chunk at a time, so that the
2946       // malicious message must actually *be* extremely large to cause
2947       // problems.  Meanwhile, we limit the allowed size of a message elsewhere.
2948       final List<byte[]> chunks = new ArrayList<byte[]>();
2949 
2950       while (sizeLeft > 0) {
2951         // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_SIZE.
2952         final byte[] chunk = new byte[Math.min(sizeLeft, DEFAULT_BUFFER_SIZE)];
2953         int tempPos = 0;
2954         while (tempPos < chunk.length) {
2955           final int n = input.read(chunk, tempPos, chunk.length - tempPos);
2956           if (n == -1) {
2957             throw InvalidProtocolBufferException.truncatedMessage();
2958           }
2959           totalBytesRetired += n;
2960           tempPos += n;
2961         }
2962         sizeLeft -= chunk.length;
2963         chunks.add(chunk);
2964       }
2965 
2966       return chunks;
2967     }
2968 
2969     /**
2970      * Like readBytes, but caller must have already checked the fast path: (size <= (bufferSize -
2971      * pos) && size > 0 || size == 0)
2972      */
readBytesSlowPath(final int size)2973     private ByteString readBytesSlowPath(final int size) throws IOException {
2974       final byte[] result = readRawBytesSlowPathOneChunk(size);
2975       if (result != null) {
2976         // We must copy as the byte array was handed off to the InputStream and a malicious
2977         // implementation could retain a reference.
2978         return ByteString.copyFrom(result);
2979       }
2980 
2981       final int originalBufferPos = pos;
2982       final int bufferedBytes = bufferSize - pos;
2983 
2984       // Mark the current buffer consumed.
2985       totalBytesRetired += bufferSize;
2986       pos = 0;
2987       bufferSize = 0;
2988 
2989       // Determine the number of bytes we need to read from the input stream.
2990       int sizeLeft = size - bufferedBytes;
2991 
2992       // The size is very large. For security reasons we read them in small
2993       // chunks.
2994       List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
2995 
2996       // OK, got everything.  Now concatenate it all into one buffer.
2997       final byte[] bytes = new byte[size];
2998 
2999       // Start by copying the leftover bytes from this.buffer.
3000       System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
3001 
3002       // And now all the chunks.
3003       int tempPos = bufferedBytes;
3004       for (final byte[] chunk : chunks) {
3005         System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
3006         tempPos += chunk.length;
3007       }
3008 
3009       return ByteString.wrap(bytes);
3010     }
3011 
3012     @Override
skipRawBytes(final int size)3013     public void skipRawBytes(final int size) throws IOException {
3014       if (size <= (bufferSize - pos) && size >= 0) {
3015         // We have all the bytes we need already.
3016         pos += size;
3017       } else {
3018         skipRawBytesSlowPath(size);
3019       }
3020     }
3021 
3022     /**
3023      * Exactly like skipRawBytes, but caller must have already checked the fast path: (size <=
3024      * (bufferSize - pos) && size >= 0)
3025      */
skipRawBytesSlowPath(final int size)3026     private void skipRawBytesSlowPath(final int size) throws IOException {
3027       if (size < 0) {
3028         throw InvalidProtocolBufferException.negativeSize();
3029       }
3030 
3031       if (totalBytesRetired + pos + size > currentLimit) {
3032         // Read to the end of the stream anyway.
3033         skipRawBytes(currentLimit - totalBytesRetired - pos);
3034         // Then fail.
3035         throw InvalidProtocolBufferException.truncatedMessage();
3036       }
3037 
3038       int totalSkipped = 0;
3039       if (refillCallback == null) {
3040         // Skipping more bytes than are in the buffer.  First skip what we have.
3041         totalBytesRetired += pos;
3042         totalSkipped = bufferSize - pos;
3043         bufferSize = 0;
3044         pos = 0;
3045 
3046         try {
3047           while (totalSkipped < size) {
3048             int toSkip = size - totalSkipped;
3049             long skipped = input.skip(toSkip);
3050             if (skipped < 0 || skipped > toSkip) {
3051               throw new IllegalStateException(
3052                   input.getClass()
3053                       + "#skip returned invalid result: "
3054                       + skipped
3055                       + "\nThe InputStream implementation is buggy.");
3056             } else if (skipped == 0) {
3057               // The API contract of skip() permits an inputstream to skip zero bytes for any reason
3058               // it wants. In particular, ByteArrayInputStream will just return zero over and over
3059               // when it's at the end of its input. In order to actually confirm that we've hit the
3060               // end of input, we need to issue a read call via the other path.
3061               break;
3062             }
3063             totalSkipped += (int) skipped;
3064           }
3065         } finally {
3066           totalBytesRetired += totalSkipped;
3067           recomputeBufferSizeAfterLimit();
3068         }
3069       }
3070       if (totalSkipped < size) {
3071         // Skipping more bytes than are in the buffer.  First skip what we have.
3072         int tempPos = bufferSize - pos;
3073         pos = bufferSize;
3074 
3075         // Keep refilling the buffer until we get to the point we wanted to skip to.
3076         // This has the side effect of ensuring the limits are updated correctly.
3077         refillBuffer(1);
3078         while (size - tempPos > bufferSize) {
3079           tempPos += bufferSize;
3080           pos = bufferSize;
3081           refillBuffer(1);
3082         }
3083 
3084         pos = size - tempPos;
3085       }
3086     }
3087   }
3088 
3089   /**
3090    * Implementation of {@link CodedInputStream} that uses an {@link Iterable <ByteBuffer>} as the
3091    * data source. Requires the use of {@code sun.misc.Unsafe} to perform fast reads on the buffer.
3092    */
3093   private static final class IterableDirectByteBufferDecoder extends CodedInputStream {
3094     /** The object that need to decode. */
3095     private Iterable<ByteBuffer> input;
3096     /** The {@link Iterator} with type {@link ByteBuffer} of {@code input} */
3097     private Iterator<ByteBuffer> iterator;
3098     /** The current ByteBuffer; */
3099     private ByteBuffer currentByteBuffer;
3100     /**
3101      * If {@code true}, indicates that all the buffer are backing a {@link ByteString} and are
3102      * therefore considered to be an immutable input source.
3103      */
3104     private boolean immutable;
3105     /**
3106      * If {@code true}, indicates that calls to read {@link ByteString} or {@code byte[]}
3107      * <strong>may</strong> return slices of the underlying buffer, rather than copies.
3108      */
3109     private boolean enableAliasing;
3110     /** The global total message length limit */
3111     private int totalBufferSize;
3112     /** The amount of available data in the input beyond {@link #currentLimit}. */
3113     private int bufferSizeAfterCurrentLimit;
3114     /** The absolute position of the end of the current message. */
3115     private int currentLimit = Integer.MAX_VALUE;
3116     /** The last tag that was read from this stream. */
3117     private int lastTag;
3118     /** Total Bytes have been Read from the {@link Iterable} {@link ByteBuffer} */
3119     private int totalBytesRead;
3120     /** The start position offset of the whole message, used as to reset the totalBytesRead */
3121     private int startOffset;
3122     /** The current position for current ByteBuffer */
3123     private long currentByteBufferPos;
3124 
3125     private long currentByteBufferStartPos;
3126     /**
3127      * If the current ByteBuffer is unsafe-direct based, currentAddress is the start address of this
3128      * ByteBuffer; otherwise should be zero.
3129      */
3130     private long currentAddress;
3131     /** The limit position for current ByteBuffer */
3132     private long currentByteBufferLimit;
3133 
3134     /**
3135      * The constructor of {@code Iterable<ByteBuffer>} decoder.
3136      *
3137      * @param inputBufs The input data.
3138      * @param size The total size of the input data.
3139      * @param immutableFlag whether the input data is immutable.
3140      */
IterableDirectByteBufferDecoder( Iterable<ByteBuffer> inputBufs, int size, boolean immutableFlag)3141     private IterableDirectByteBufferDecoder(
3142         Iterable<ByteBuffer> inputBufs, int size, boolean immutableFlag) {
3143       totalBufferSize = size;
3144       input = inputBufs;
3145       iterator = input.iterator();
3146       immutable = immutableFlag;
3147       startOffset = totalBytesRead = 0;
3148       if (size == 0) {
3149         currentByteBuffer = EMPTY_BYTE_BUFFER;
3150         currentByteBufferPos = 0;
3151         currentByteBufferStartPos = 0;
3152         currentByteBufferLimit = 0;
3153         currentAddress = 0;
3154       } else {
3155         tryGetNextByteBuffer();
3156       }
3157     }
3158 
3159     /** To get the next ByteBuffer from {@code input}, and then update the parameters */
getNextByteBuffer()3160     private void getNextByteBuffer() throws InvalidProtocolBufferException {
3161       if (!iterator.hasNext()) {
3162         throw InvalidProtocolBufferException.truncatedMessage();
3163       }
3164       tryGetNextByteBuffer();
3165     }
3166 
tryGetNextByteBuffer()3167     private void tryGetNextByteBuffer() {
3168       currentByteBuffer = iterator.next();
3169       totalBytesRead += (int) (currentByteBufferPos - currentByteBufferStartPos);
3170       currentByteBufferPos = currentByteBuffer.position();
3171       currentByteBufferStartPos = currentByteBufferPos;
3172       currentByteBufferLimit = currentByteBuffer.limit();
3173       currentAddress = UnsafeUtil.addressOffset(currentByteBuffer);
3174       currentByteBufferPos += currentAddress;
3175       currentByteBufferStartPos += currentAddress;
3176       currentByteBufferLimit += currentAddress;
3177     }
3178 
3179     @Override
readTag()3180     public int readTag() throws IOException {
3181       if (isAtEnd()) {
3182         lastTag = 0;
3183         return 0;
3184       }
3185 
3186       lastTag = readRawVarint32();
3187       if (WireFormat.getTagFieldNumber(lastTag) == 0) {
3188         // If we actually read zero (or any tag number corresponding to field
3189         // number zero), that's not a valid tag.
3190         throw InvalidProtocolBufferException.invalidTag();
3191       }
3192       return lastTag;
3193     }
3194 
3195     @Override
checkLastTagWas(final int value)3196     public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
3197       if (lastTag != value) {
3198         throw InvalidProtocolBufferException.invalidEndTag();
3199       }
3200     }
3201 
3202     @Override
getLastTag()3203     public int getLastTag() {
3204       return lastTag;
3205     }
3206 
3207     @Override
skipField(final int tag)3208     public boolean skipField(final int tag) throws IOException {
3209       switch (WireFormat.getTagWireType(tag)) {
3210         case WireFormat.WIRETYPE_VARINT:
3211           skipRawVarint();
3212           return true;
3213         case WireFormat.WIRETYPE_FIXED64:
3214           skipRawBytes(FIXED64_SIZE);
3215           return true;
3216         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
3217           skipRawBytes(readRawVarint32());
3218           return true;
3219         case WireFormat.WIRETYPE_START_GROUP:
3220           skipMessage();
3221           checkLastTagWas(
3222               WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
3223           return true;
3224         case WireFormat.WIRETYPE_END_GROUP:
3225           return false;
3226         case WireFormat.WIRETYPE_FIXED32:
3227           skipRawBytes(FIXED32_SIZE);
3228           return true;
3229         default:
3230           throw InvalidProtocolBufferException.invalidWireType();
3231       }
3232     }
3233 
3234     @Override
skipField(final int tag, final CodedOutputStream output)3235     public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
3236       switch (WireFormat.getTagWireType(tag)) {
3237         case WireFormat.WIRETYPE_VARINT:
3238           {
3239             long value = readInt64();
3240             output.writeRawVarint32(tag);
3241             output.writeUInt64NoTag(value);
3242             return true;
3243           }
3244         case WireFormat.WIRETYPE_FIXED64:
3245           {
3246             long value = readRawLittleEndian64();
3247             output.writeRawVarint32(tag);
3248             output.writeFixed64NoTag(value);
3249             return true;
3250           }
3251         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
3252           {
3253             ByteString value = readBytes();
3254             output.writeRawVarint32(tag);
3255             output.writeBytesNoTag(value);
3256             return true;
3257           }
3258         case WireFormat.WIRETYPE_START_GROUP:
3259           {
3260             output.writeRawVarint32(tag);
3261             skipMessage(output);
3262             int endtag =
3263                 WireFormat.makeTag(
3264                     WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
3265             checkLastTagWas(endtag);
3266             output.writeRawVarint32(endtag);
3267             return true;
3268           }
3269         case WireFormat.WIRETYPE_END_GROUP:
3270           {
3271             return false;
3272           }
3273         case WireFormat.WIRETYPE_FIXED32:
3274           {
3275             int value = readRawLittleEndian32();
3276             output.writeRawVarint32(tag);
3277             output.writeFixed32NoTag(value);
3278             return true;
3279           }
3280         default:
3281           throw InvalidProtocolBufferException.invalidWireType();
3282       }
3283     }
3284 
3285     @Override
skipMessage()3286     public void skipMessage() throws IOException {
3287       while (true) {
3288         final int tag = readTag();
3289         if (tag == 0 || !skipField(tag)) {
3290           return;
3291         }
3292       }
3293     }
3294 
3295     @Override
skipMessage(CodedOutputStream output)3296     public void skipMessage(CodedOutputStream output) throws IOException {
3297       while (true) {
3298         final int tag = readTag();
3299         if (tag == 0 || !skipField(tag, output)) {
3300           return;
3301         }
3302       }
3303     }
3304 
3305     // -----------------------------------------------------------------
3306 
3307     @Override
readDouble()3308     public double readDouble() throws IOException {
3309       return Double.longBitsToDouble(readRawLittleEndian64());
3310     }
3311 
3312     @Override
readFloat()3313     public float readFloat() throws IOException {
3314       return Float.intBitsToFloat(readRawLittleEndian32());
3315     }
3316 
3317     @Override
readUInt64()3318     public long readUInt64() throws IOException {
3319       return readRawVarint64();
3320     }
3321 
3322     @Override
readInt64()3323     public long readInt64() throws IOException {
3324       return readRawVarint64();
3325     }
3326 
3327     @Override
readInt32()3328     public int readInt32() throws IOException {
3329       return readRawVarint32();
3330     }
3331 
3332     @Override
readFixed64()3333     public long readFixed64() throws IOException {
3334       return readRawLittleEndian64();
3335     }
3336 
3337     @Override
readFixed32()3338     public int readFixed32() throws IOException {
3339       return readRawLittleEndian32();
3340     }
3341 
3342     @Override
readBool()3343     public boolean readBool() throws IOException {
3344       return readRawVarint64() != 0;
3345     }
3346 
3347     @Override
readString()3348     public String readString() throws IOException {
3349       final int size = readRawVarint32();
3350       if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) {
3351         byte[] bytes = new byte[size];
3352         UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size);
3353         String result = new String(bytes, UTF_8);
3354         currentByteBufferPos += size;
3355         return result;
3356       } else if (size > 0 && size <= remaining()) {
3357         // TODO(yilunchong): To use an underlying bytes[] instead of allocating a new bytes[]
3358         byte[] bytes = new byte[size];
3359         readRawBytesTo(bytes, 0, size);
3360         String result = new String(bytes, UTF_8);
3361         return result;
3362       }
3363 
3364       if (size == 0) {
3365         return "";
3366       }
3367       if (size < 0) {
3368         throw InvalidProtocolBufferException.negativeSize();
3369       }
3370       throw InvalidProtocolBufferException.truncatedMessage();
3371     }
3372 
3373     @Override
readStringRequireUtf8()3374     public String readStringRequireUtf8() throws IOException {
3375       final int size = readRawVarint32();
3376       if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) {
3377         final int bufferPos = (int) (currentByteBufferPos - currentByteBufferStartPos);
3378         String result = Utf8.decodeUtf8(currentByteBuffer, bufferPos, size);
3379         currentByteBufferPos += size;
3380         return result;
3381       }
3382       if (size >= 0 && size <= remaining()) {
3383         byte[] bytes = new byte[size];
3384         readRawBytesTo(bytes, 0, size);
3385         return Utf8.decodeUtf8(bytes, 0, size);
3386       }
3387 
3388       if (size == 0) {
3389         return "";
3390       }
3391       if (size <= 0) {
3392         throw InvalidProtocolBufferException.negativeSize();
3393       }
3394       throw InvalidProtocolBufferException.truncatedMessage();
3395     }
3396 
3397     @Override
readGroup( final int fieldNumber, final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)3398     public void readGroup(
3399         final int fieldNumber,
3400         final MessageLite.Builder builder,
3401         final ExtensionRegistryLite extensionRegistry)
3402         throws IOException {
3403       if (recursionDepth >= recursionLimit) {
3404         throw InvalidProtocolBufferException.recursionLimitExceeded();
3405       }
3406       ++recursionDepth;
3407       builder.mergeFrom(this, extensionRegistry);
3408       checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
3409       --recursionDepth;
3410     }
3411 
3412 
3413     @Override
readGroup( final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)3414     public <T extends MessageLite> T readGroup(
3415         final int fieldNumber,
3416         final Parser<T> parser,
3417         final ExtensionRegistryLite extensionRegistry)
3418         throws IOException {
3419       if (recursionDepth >= recursionLimit) {
3420         throw InvalidProtocolBufferException.recursionLimitExceeded();
3421       }
3422       ++recursionDepth;
3423       T result = parser.parsePartialFrom(this, extensionRegistry);
3424       checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
3425       --recursionDepth;
3426       return result;
3427     }
3428 
3429     @Deprecated
3430     @Override
readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)3431     public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
3432         throws IOException {
3433       readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
3434     }
3435 
3436     @Override
readMessage( final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)3437     public void readMessage(
3438         final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
3439         throws IOException {
3440       final int length = readRawVarint32();
3441       if (recursionDepth >= recursionLimit) {
3442         throw InvalidProtocolBufferException.recursionLimitExceeded();
3443       }
3444       final int oldLimit = pushLimit(length);
3445       ++recursionDepth;
3446       builder.mergeFrom(this, extensionRegistry);
3447       checkLastTagWas(0);
3448       --recursionDepth;
3449       popLimit(oldLimit);
3450     }
3451 
3452 
3453     @Override
readMessage( final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)3454     public <T extends MessageLite> T readMessage(
3455         final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
3456       int length = readRawVarint32();
3457       if (recursionDepth >= recursionLimit) {
3458         throw InvalidProtocolBufferException.recursionLimitExceeded();
3459       }
3460       final int oldLimit = pushLimit(length);
3461       ++recursionDepth;
3462       T result = parser.parsePartialFrom(this, extensionRegistry);
3463       checkLastTagWas(0);
3464       --recursionDepth;
3465       popLimit(oldLimit);
3466       return result;
3467     }
3468 
3469     @Override
readBytes()3470     public ByteString readBytes() throws IOException {
3471       final int size = readRawVarint32();
3472       if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) {
3473         if (immutable && enableAliasing) {
3474           final int idx = (int) (currentByteBufferPos - currentAddress);
3475           final ByteString result = ByteString.wrap(slice(idx, idx + size));
3476           currentByteBufferPos += size;
3477           return result;
3478         } else {
3479           byte[] bytes;
3480           bytes = new byte[size];
3481           UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size);
3482           currentByteBufferPos += size;
3483           return ByteString.wrap(bytes);
3484         }
3485       } else if (size > 0 && size <= remaining()) {
3486         byte[] temp = new byte[size];
3487         readRawBytesTo(temp, 0, size);
3488         return ByteString.wrap(temp);
3489       }
3490 
3491       if (size == 0) {
3492         return ByteString.EMPTY;
3493       }
3494       if (size < 0) {
3495         throw InvalidProtocolBufferException.negativeSize();
3496       }
3497       throw InvalidProtocolBufferException.truncatedMessage();
3498     }
3499 
3500     @Override
readByteArray()3501     public byte[] readByteArray() throws IOException {
3502       return readRawBytes(readRawVarint32());
3503     }
3504 
3505     @Override
readByteBuffer()3506     public ByteBuffer readByteBuffer() throws IOException {
3507       final int size = readRawVarint32();
3508       if (size > 0 && size <= currentRemaining()) {
3509         if (!immutable && enableAliasing) {
3510           currentByteBufferPos += size;
3511           return slice(
3512               (int) (currentByteBufferPos - currentAddress - size),
3513               (int) (currentByteBufferPos - currentAddress));
3514         } else {
3515           byte[] bytes = new byte[size];
3516           UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size);
3517           currentByteBufferPos += size;
3518           return ByteBuffer.wrap(bytes);
3519         }
3520       } else if (size > 0 && size <= remaining()) {
3521         byte[] temp = new byte[size];
3522         readRawBytesTo(temp, 0, size);
3523         return ByteBuffer.wrap(temp);
3524       }
3525 
3526       if (size == 0) {
3527         return EMPTY_BYTE_BUFFER;
3528       }
3529       if (size < 0) {
3530         throw InvalidProtocolBufferException.negativeSize();
3531       }
3532       throw InvalidProtocolBufferException.truncatedMessage();
3533     }
3534 
3535     @Override
readUInt32()3536     public int readUInt32() throws IOException {
3537       return readRawVarint32();
3538     }
3539 
3540     @Override
readEnum()3541     public int readEnum() throws IOException {
3542       return readRawVarint32();
3543     }
3544 
3545     @Override
readSFixed32()3546     public int readSFixed32() throws IOException {
3547       return readRawLittleEndian32();
3548     }
3549 
3550     @Override
readSFixed64()3551     public long readSFixed64() throws IOException {
3552       return readRawLittleEndian64();
3553     }
3554 
3555     @Override
readSInt32()3556     public int readSInt32() throws IOException {
3557       return decodeZigZag32(readRawVarint32());
3558     }
3559 
3560     @Override
readSInt64()3561     public long readSInt64() throws IOException {
3562       return decodeZigZag64(readRawVarint64());
3563     }
3564 
3565     @Override
readRawVarint32()3566     public int readRawVarint32() throws IOException {
3567       fastpath:
3568       {
3569         long tempPos = currentByteBufferPos;
3570 
3571         if (currentByteBufferLimit == currentByteBufferPos) {
3572           break fastpath;
3573         }
3574 
3575         int x;
3576         if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) {
3577           currentByteBufferPos++;
3578           return x;
3579         } else if (currentByteBufferLimit - currentByteBufferPos < 10) {
3580           break fastpath;
3581         } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
3582           x ^= (~0 << 7);
3583         } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
3584           x ^= (~0 << 7) ^ (~0 << 14);
3585         } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
3586           x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
3587         } else {
3588           int y = UnsafeUtil.getByte(tempPos++);
3589           x ^= y << 28;
3590           x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
3591           if (y < 0
3592               && UnsafeUtil.getByte(tempPos++) < 0
3593               && UnsafeUtil.getByte(tempPos++) < 0
3594               && UnsafeUtil.getByte(tempPos++) < 0
3595               && UnsafeUtil.getByte(tempPos++) < 0
3596               && UnsafeUtil.getByte(tempPos++) < 0) {
3597             break fastpath; // Will throw malformedVarint()
3598           }
3599         }
3600         currentByteBufferPos = tempPos;
3601         return x;
3602       }
3603       return (int) readRawVarint64SlowPath();
3604     }
3605 
3606     @Override
readRawVarint64()3607     public long readRawVarint64() throws IOException {
3608       fastpath:
3609       {
3610         long tempPos = currentByteBufferPos;
3611 
3612         if (currentByteBufferLimit == currentByteBufferPos) {
3613           break fastpath;
3614         }
3615 
3616         long x;
3617         int y;
3618         if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) {
3619           currentByteBufferPos++;
3620           return y;
3621         } else if (currentByteBufferLimit - currentByteBufferPos < 10) {
3622           break fastpath;
3623         } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
3624           x = y ^ (~0 << 7);
3625         } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
3626           x = y ^ ((~0 << 7) ^ (~0 << 14));
3627         } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
3628           x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
3629         } else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) {
3630           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
3631         } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) {
3632           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
3633         } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) {
3634           x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
3635         } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) {
3636           x ^=
3637               (~0L << 7)
3638                   ^ (~0L << 14)
3639                   ^ (~0L << 21)
3640                   ^ (~0L << 28)
3641                   ^ (~0L << 35)
3642                   ^ (~0L << 42)
3643                   ^ (~0L << 49);
3644         } else {
3645           x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56);
3646           x ^=
3647               (~0L << 7)
3648                   ^ (~0L << 14)
3649                   ^ (~0L << 21)
3650                   ^ (~0L << 28)
3651                   ^ (~0L << 35)
3652                   ^ (~0L << 42)
3653                   ^ (~0L << 49)
3654                   ^ (~0L << 56);
3655           if (x < 0L) {
3656             if (UnsafeUtil.getByte(tempPos++) < 0L) {
3657               break fastpath; // Will throw malformedVarint()
3658             }
3659           }
3660         }
3661         currentByteBufferPos = tempPos;
3662         return x;
3663       }
3664       return readRawVarint64SlowPath();
3665     }
3666 
3667     @Override
readRawVarint64SlowPath()3668     long readRawVarint64SlowPath() throws IOException {
3669       long result = 0;
3670       for (int shift = 0; shift < 64; shift += 7) {
3671         final byte b = readRawByte();
3672         result |= (long) (b & 0x7F) << shift;
3673         if ((b & 0x80) == 0) {
3674           return result;
3675         }
3676       }
3677       throw InvalidProtocolBufferException.malformedVarint();
3678     }
3679 
3680     @Override
readRawLittleEndian32()3681     public int readRawLittleEndian32() throws IOException {
3682       if (currentRemaining() >= FIXED32_SIZE) {
3683         long tempPos = currentByteBufferPos;
3684         currentByteBufferPos += FIXED32_SIZE;
3685         return (((UnsafeUtil.getByte(tempPos) & 0xff))
3686             | ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8)
3687             | ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16)
3688             | ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24));
3689       }
3690       return ((readRawByte() & 0xff)
3691           | ((readRawByte() & 0xff) << 8)
3692           | ((readRawByte() & 0xff) << 16)
3693           | ((readRawByte() & 0xff) << 24));
3694     }
3695 
3696     @Override
readRawLittleEndian64()3697     public long readRawLittleEndian64() throws IOException {
3698       if (currentRemaining() >= FIXED64_SIZE) {
3699         long tempPos = currentByteBufferPos;
3700         currentByteBufferPos += FIXED64_SIZE;
3701         return (((UnsafeUtil.getByte(tempPos) & 0xffL))
3702             | ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8)
3703             | ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16)
3704             | ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24)
3705             | ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32)
3706             | ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40)
3707             | ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48)
3708             | ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56));
3709       }
3710       return ((readRawByte() & 0xffL)
3711           | ((readRawByte() & 0xffL) << 8)
3712           | ((readRawByte() & 0xffL) << 16)
3713           | ((readRawByte() & 0xffL) << 24)
3714           | ((readRawByte() & 0xffL) << 32)
3715           | ((readRawByte() & 0xffL) << 40)
3716           | ((readRawByte() & 0xffL) << 48)
3717           | ((readRawByte() & 0xffL) << 56));
3718     }
3719 
3720     @Override
enableAliasing(boolean enabled)3721     public void enableAliasing(boolean enabled) {
3722       this.enableAliasing = enabled;
3723     }
3724 
3725     @Override
resetSizeCounter()3726     public void resetSizeCounter() {
3727       startOffset = (int) (totalBytesRead + currentByteBufferPos - currentByteBufferStartPos);
3728     }
3729 
3730     @Override
pushLimit(int byteLimit)3731     public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
3732       if (byteLimit < 0) {
3733         throw InvalidProtocolBufferException.negativeSize();
3734       }
3735       byteLimit += getTotalBytesRead();
3736       final int oldLimit = currentLimit;
3737       if (byteLimit > oldLimit) {
3738         throw InvalidProtocolBufferException.truncatedMessage();
3739       }
3740       currentLimit = byteLimit;
3741 
3742       recomputeBufferSizeAfterLimit();
3743 
3744       return oldLimit;
3745     }
3746 
recomputeBufferSizeAfterLimit()3747     private void recomputeBufferSizeAfterLimit() {
3748       totalBufferSize += bufferSizeAfterCurrentLimit;
3749       final int bufferEnd = totalBufferSize - startOffset;
3750       if (bufferEnd > currentLimit) {
3751         // Limit is in current buffer.
3752         bufferSizeAfterCurrentLimit = bufferEnd - currentLimit;
3753         totalBufferSize -= bufferSizeAfterCurrentLimit;
3754       } else {
3755         bufferSizeAfterCurrentLimit = 0;
3756       }
3757     }
3758 
3759     @Override
popLimit(final int oldLimit)3760     public void popLimit(final int oldLimit) {
3761       currentLimit = oldLimit;
3762       recomputeBufferSizeAfterLimit();
3763     }
3764 
3765     @Override
getBytesUntilLimit()3766     public int getBytesUntilLimit() {
3767       if (currentLimit == Integer.MAX_VALUE) {
3768         return -1;
3769       }
3770 
3771       return currentLimit - getTotalBytesRead();
3772     }
3773 
3774     @Override
isAtEnd()3775     public boolean isAtEnd() throws IOException {
3776       return totalBytesRead + currentByteBufferPos - currentByteBufferStartPos == totalBufferSize;
3777     }
3778 
3779     @Override
getTotalBytesRead()3780     public int getTotalBytesRead() {
3781       return (int)
3782           (totalBytesRead - startOffset + currentByteBufferPos - currentByteBufferStartPos);
3783     }
3784 
3785     @Override
readRawByte()3786     public byte readRawByte() throws IOException {
3787       if (currentRemaining() == 0) {
3788         getNextByteBuffer();
3789       }
3790       return UnsafeUtil.getByte(currentByteBufferPos++);
3791     }
3792 
3793     @Override
readRawBytes(final int length)3794     public byte[] readRawBytes(final int length) throws IOException {
3795       if (length >= 0 && length <= currentRemaining()) {
3796         byte[] bytes = new byte[length];
3797         UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, length);
3798         currentByteBufferPos += length;
3799         return bytes;
3800       }
3801       if (length >= 0 && length <= remaining()) {
3802         byte[] bytes = new byte[length];
3803         readRawBytesTo(bytes, 0, length);
3804         return bytes;
3805       }
3806 
3807       if (length <= 0) {
3808         if (length == 0) {
3809           return EMPTY_BYTE_ARRAY;
3810         } else {
3811           throw InvalidProtocolBufferException.negativeSize();
3812         }
3813       }
3814 
3815       throw InvalidProtocolBufferException.truncatedMessage();
3816     }
3817 
3818     /**
3819      * Try to get raw bytes from {@code input} with the size of {@code length} and copy to {@code
3820      * bytes} array. If the size is bigger than the number of remaining bytes in the input, then
3821      * throw {@code truncatedMessage} exception.
3822      *
3823      * @param bytes
3824      * @param offset
3825      * @param length
3826      * @throws IOException
3827      */
readRawBytesTo(byte[] bytes, int offset, final int length)3828     private void readRawBytesTo(byte[] bytes, int offset, final int length) throws IOException {
3829       if (length >= 0 && length <= remaining()) {
3830         int l = length;
3831         while (l > 0) {
3832           if (currentRemaining() == 0) {
3833             getNextByteBuffer();
3834           }
3835           int bytesToCopy = Math.min(l, (int) currentRemaining());
3836           UnsafeUtil.copyMemory(currentByteBufferPos, bytes, length - l + offset, bytesToCopy);
3837           l -= bytesToCopy;
3838           currentByteBufferPos += bytesToCopy;
3839         }
3840         return;
3841       }
3842 
3843       if (length <= 0) {
3844         if (length == 0) {
3845           return;
3846         } else {
3847           throw InvalidProtocolBufferException.negativeSize();
3848         }
3849       }
3850       throw InvalidProtocolBufferException.truncatedMessage();
3851     }
3852 
3853     @Override
skipRawBytes(final int length)3854     public void skipRawBytes(final int length) throws IOException {
3855       if (length >= 0
3856           && length
3857               <= (totalBufferSize
3858                   - totalBytesRead
3859                   - currentByteBufferPos
3860                   + currentByteBufferStartPos)) {
3861         // We have all the bytes we need already.
3862         int l = length;
3863         while (l > 0) {
3864           if (currentRemaining() == 0) {
3865             getNextByteBuffer();
3866           }
3867           int rl = Math.min(l, (int) currentRemaining());
3868           l -= rl;
3869           currentByteBufferPos += rl;
3870         }
3871         return;
3872       }
3873 
3874       if (length < 0) {
3875         throw InvalidProtocolBufferException.negativeSize();
3876       }
3877       throw InvalidProtocolBufferException.truncatedMessage();
3878     }
3879 
3880     // TODO: optimize to fastpath
skipRawVarint()3881     private void skipRawVarint() throws IOException {
3882       for (int i = 0; i < MAX_VARINT_SIZE; i++) {
3883         if (readRawByte() >= 0) {
3884           return;
3885         }
3886       }
3887       throw InvalidProtocolBufferException.malformedVarint();
3888     }
3889 
3890     /**
3891      * Try to get the number of remaining bytes in {@code input}.
3892      *
3893      * @return the number of remaining bytes in {@code input}.
3894      */
remaining()3895     private int remaining() {
3896       return (int)
3897           (totalBufferSize - totalBytesRead - currentByteBufferPos + currentByteBufferStartPos);
3898     }
3899 
3900     /**
3901      * Try to get the number of remaining bytes in {@code currentByteBuffer}.
3902      *
3903      * @return the number of remaining bytes in {@code currentByteBuffer}
3904      */
currentRemaining()3905     private long currentRemaining() {
3906       return (currentByteBufferLimit - currentByteBufferPos);
3907     }
3908 
slice(int begin, int end)3909     private ByteBuffer slice(int begin, int end) throws IOException {
3910       int prevPos = currentByteBuffer.position();
3911       int prevLimit = currentByteBuffer.limit();
3912       try {
3913         currentByteBuffer.position(begin);
3914         currentByteBuffer.limit(end);
3915         return currentByteBuffer.slice();
3916       } catch (IllegalArgumentException e) {
3917         throw InvalidProtocolBufferException.truncatedMessage();
3918       } finally {
3919         currentByteBuffer.position(prevPos);
3920         currentByteBuffer.limit(prevLimit);
3921       }
3922     }
3923   }
3924 }
3925