• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 package com.google.protobuf;
9 
10 import static com.google.protobuf.WireFormat.FIXED32_SIZE;
11 import static com.google.protobuf.WireFormat.FIXED64_SIZE;
12 import static com.google.protobuf.WireFormat.WIRETYPE_END_GROUP;
13 import static com.google.protobuf.WireFormat.WIRETYPE_FIXED32;
14 import static com.google.protobuf.WireFormat.WIRETYPE_FIXED64;
15 import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED;
16 import static com.google.protobuf.WireFormat.WIRETYPE_START_GROUP;
17 import static com.google.protobuf.WireFormat.WIRETYPE_VARINT;
18 
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21 import java.util.List;
22 import java.util.Map;
23 
24 /**
25  * A {@link Reader} that reads from a buffer containing a message serialized with the binary
26  * protocol.
27  */
28 @CheckReturnValue
29 @ExperimentalApi
30 abstract class BinaryReader implements Reader {
31   private static final int FIXED32_MULTIPLE_MASK = FIXED32_SIZE - 1;
32   private static final int FIXED64_MULTIPLE_MASK = FIXED64_SIZE - 1;
33 
34   /**
35    * Creates a new reader using the given {@code buffer} as input.
36    *
37    * @param buffer the input buffer. The buffer (including position, limit, etc.) will not be
38    *     modified. To increment the buffer position after the read completes, use the value returned
39    *     by {@link #getTotalBytesRead()}.
40    * @param bufferIsImmutable if {@code true} the reader assumes that the content of {@code buffer}
41    *     will never change and any allocated {@link ByteString} instances will by directly wrap
42    *     slices of {@code buffer}.
43    * @return the reader
44    */
newInstance(ByteBuffer buffer, boolean bufferIsImmutable)45   public static BinaryReader newInstance(ByteBuffer buffer, boolean bufferIsImmutable) {
46     if (buffer.hasArray()) {
47       // TODO: Add support for unsafe operations.
48       return new SafeHeapReader(buffer, bufferIsImmutable);
49     }
50     // TODO: Add support for direct buffers
51     throw new IllegalArgumentException("Direct buffers not yet supported");
52   }
53 
54   /** Only allow subclassing for inner classes. */
BinaryReader()55   private BinaryReader() {}
56 
57   /** Returns the total number of bytes read so far from the input buffer. */
getTotalBytesRead()58   public abstract int getTotalBytesRead();
59 
60   @Override
shouldDiscardUnknownFields()61   public boolean shouldDiscardUnknownFields() {
62     return false;
63   }
64 
65   /**
66    * A {@link BinaryReader} implementation that operates on a heap {@link ByteBuffer}. Uses only
67    * safe operations on the underlying array.
68    */
69   private static final class SafeHeapReader extends BinaryReader {
70     private final boolean bufferIsImmutable;
71     private final byte[] buffer;
72     private int pos;
73     private final int initialPos;
74     private int limit;
75     private int tag;
76     private int endGroupTag;
77 
SafeHeapReader(ByteBuffer bytebuf, boolean bufferIsImmutable)78     public SafeHeapReader(ByteBuffer bytebuf, boolean bufferIsImmutable) {
79       this.bufferIsImmutable = bufferIsImmutable;
80       buffer = bytebuf.array();
81       initialPos = pos = bytebuf.arrayOffset() + bytebuf.position();
82       limit = bytebuf.arrayOffset() + bytebuf.limit();
83     }
84 
isAtEnd()85     private boolean isAtEnd() {
86       return pos == limit;
87     }
88 
89     @Override
getTotalBytesRead()90     public int getTotalBytesRead() {
91       return pos - initialPos;
92     }
93 
94     @Override
getFieldNumber()95     public int getFieldNumber() throws IOException {
96       if (isAtEnd()) {
97         return Reader.READ_DONE;
98       }
99       tag = readVarint32();
100       if (tag == endGroupTag) {
101         return Reader.READ_DONE;
102       }
103       return WireFormat.getTagFieldNumber(tag);
104     }
105 
106     @Override
getTag()107     public int getTag() {
108       return tag;
109     }
110 
111     @Override
skipField()112     public boolean skipField() throws IOException {
113       if (isAtEnd() || tag == endGroupTag) {
114         return false;
115       }
116 
117       switch (WireFormat.getTagWireType(tag)) {
118         case WIRETYPE_VARINT:
119           skipVarint();
120           return true;
121         case WIRETYPE_FIXED64:
122           skipBytes(FIXED64_SIZE);
123           return true;
124         case WIRETYPE_LENGTH_DELIMITED:
125           skipBytes(readVarint32());
126           return true;
127         case WIRETYPE_FIXED32:
128           skipBytes(FIXED32_SIZE);
129           return true;
130         case WIRETYPE_START_GROUP:
131           skipGroup();
132           return true;
133         default:
134           throw InvalidProtocolBufferException.invalidWireType();
135       }
136     }
137 
138     @Override
readDouble()139     public double readDouble() throws IOException {
140       requireWireType(WIRETYPE_FIXED64);
141       return Double.longBitsToDouble(readLittleEndian64());
142     }
143 
144     @Override
readFloat()145     public float readFloat() throws IOException {
146       requireWireType(WIRETYPE_FIXED32);
147       return Float.intBitsToFloat(readLittleEndian32());
148     }
149 
150     @Override
readUInt64()151     public long readUInt64() throws IOException {
152       requireWireType(WIRETYPE_VARINT);
153       return readVarint64();
154     }
155 
156     @Override
readInt64()157     public long readInt64() throws IOException {
158       requireWireType(WIRETYPE_VARINT);
159       return readVarint64();
160     }
161 
162     @Override
readInt32()163     public int readInt32() throws IOException {
164       requireWireType(WIRETYPE_VARINT);
165       return readVarint32();
166     }
167 
168     @Override
readFixed64()169     public long readFixed64() throws IOException {
170       requireWireType(WIRETYPE_FIXED64);
171       return readLittleEndian64();
172     }
173 
174     @Override
readFixed32()175     public int readFixed32() throws IOException {
176       requireWireType(WIRETYPE_FIXED32);
177       return readLittleEndian32();
178     }
179 
180     @Override
readBool()181     public boolean readBool() throws IOException {
182       requireWireType(WIRETYPE_VARINT);
183       return readVarint32() != 0;
184     }
185 
186     @Override
readString()187     public String readString() throws IOException {
188       return readStringInternal(false);
189     }
190 
191     @Override
readStringRequireUtf8()192     public String readStringRequireUtf8() throws IOException {
193       return readStringInternal(true);
194     }
195 
readStringInternal(boolean requireUtf8)196     public String readStringInternal(boolean requireUtf8) throws IOException {
197       requireWireType(WIRETYPE_LENGTH_DELIMITED);
198       final int size = readVarint32();
199       if (size == 0) {
200         return "";
201       }
202 
203       requireBytes(size);
204       if (requireUtf8 && !Utf8.isValidUtf8(buffer, pos, pos + size)) {
205         throw InvalidProtocolBufferException.invalidUtf8();
206       }
207       String result = new String(buffer, pos, size, Internal.UTF_8);
208       pos += size;
209       return result;
210     }
211 
212     @Override
readMessage(Class<T> clazz, ExtensionRegistryLite extensionRegistry)213     public <T> T readMessage(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
214         throws IOException {
215       requireWireType(WIRETYPE_LENGTH_DELIMITED);
216       return readMessage(Protobuf.getInstance().schemaFor(clazz), extensionRegistry);
217     }
218 
219     @Override
readMessageBySchemaWithCheck( Schema<T> schema, ExtensionRegistryLite extensionRegistry)220     public <T> T readMessageBySchemaWithCheck(
221         Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
222       requireWireType(WIRETYPE_LENGTH_DELIMITED);
223       return readMessage(schema, extensionRegistry);
224     }
225 
readMessage(Schema<T> schema, ExtensionRegistryLite extensionRegistry)226     private <T> T readMessage(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
227         throws IOException {
228       T newInstance = schema.newInstance();
229       mergeMessageField(newInstance, schema, extensionRegistry);
230       schema.makeImmutable(newInstance);
231       return newInstance;
232     }
233 
234     @Override
mergeMessageField( T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)235     public <T> void mergeMessageField(
236         T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
237       int size = readVarint32();
238       requireBytes(size);
239 
240       // Update the limit.
241       int prevLimit = limit;
242       int newLimit = pos + size;
243       limit = newLimit;
244 
245       try {
246         schema.mergeFrom(target, this, extensionRegistry);
247         if (pos != newLimit) {
248           throw InvalidProtocolBufferException.parseFailure();
249         }
250       } finally {
251         // Restore the limit.
252         limit = prevLimit;
253       }
254     }
255 
256     @Deprecated
257     @Override
readGroup(Class<T> clazz, ExtensionRegistryLite extensionRegistry)258     public <T> T readGroup(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
259         throws IOException {
260       requireWireType(WIRETYPE_START_GROUP);
261       return readGroup(Protobuf.getInstance().schemaFor(clazz), extensionRegistry);
262     }
263 
264     @Deprecated
265     @Override
readGroupBySchemaWithCheck( Schema<T> schema, ExtensionRegistryLite extensionRegistry)266     public <T> T readGroupBySchemaWithCheck(
267         Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
268       requireWireType(WIRETYPE_START_GROUP);
269       return readGroup(schema, extensionRegistry);
270     }
271 
readGroup(Schema<T> schema, ExtensionRegistryLite extensionRegistry)272     private <T> T readGroup(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
273         throws IOException {
274       T newInstance = schema.newInstance();
275       mergeGroupField(newInstance, schema, extensionRegistry);
276       schema.makeImmutable(newInstance);
277       return newInstance;
278     }
279 
280     @Override
mergeGroupField( T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)281     public <T> void mergeGroupField(
282         T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
283       int prevEndGroupTag = endGroupTag;
284       endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP);
285 
286       try {
287         schema.mergeFrom(target, this, extensionRegistry);
288         if (tag != endGroupTag) {
289           throw InvalidProtocolBufferException.parseFailure();
290         }
291       } finally {
292         // Restore the old end group tag.
293         endGroupTag = prevEndGroupTag;
294       }
295     }
296 
297     @Override
readBytes()298     public ByteString readBytes() throws IOException {
299       requireWireType(WIRETYPE_LENGTH_DELIMITED);
300       int size = readVarint32();
301       if (size == 0) {
302         return ByteString.EMPTY;
303       }
304 
305       requireBytes(size);
306       ByteString bytes =
307           bufferIsImmutable
308               ? ByteString.wrap(buffer, pos, size)
309               : ByteString.copyFrom(buffer, pos, size);
310       pos += size;
311       return bytes;
312     }
313 
314     @Override
readUInt32()315     public int readUInt32() throws IOException {
316       requireWireType(WIRETYPE_VARINT);
317       return readVarint32();
318     }
319 
320     @Override
readEnum()321     public int readEnum() throws IOException {
322       requireWireType(WIRETYPE_VARINT);
323       return readVarint32();
324     }
325 
326     @Override
readSFixed32()327     public int readSFixed32() throws IOException {
328       requireWireType(WIRETYPE_FIXED32);
329       return readLittleEndian32();
330     }
331 
332     @Override
readSFixed64()333     public long readSFixed64() throws IOException {
334       requireWireType(WIRETYPE_FIXED64);
335       return readLittleEndian64();
336     }
337 
338     @Override
readSInt32()339     public int readSInt32() throws IOException {
340       requireWireType(WIRETYPE_VARINT);
341       return CodedInputStream.decodeZigZag32(readVarint32());
342     }
343 
344     @Override
readSInt64()345     public long readSInt64() throws IOException {
346       requireWireType(WIRETYPE_VARINT);
347       return CodedInputStream.decodeZigZag64(readVarint64());
348     }
349 
350     @Override
readDoubleList(List<Double> target)351     public void readDoubleList(List<Double> target) throws IOException {
352       if (target instanceof DoubleArrayList) {
353         DoubleArrayList plist = (DoubleArrayList) target;
354         switch (WireFormat.getTagWireType(tag)) {
355           case WIRETYPE_LENGTH_DELIMITED:
356             final int bytes = readVarint32();
357             verifyPackedFixed64Length(bytes);
358             final int fieldEndPos = pos + bytes;
359             while (pos < fieldEndPos) {
360               plist.addDouble(Double.longBitsToDouble(readLittleEndian64_NoCheck()));
361             }
362             break;
363           case WIRETYPE_FIXED64:
364             while (true) {
365               plist.addDouble(readDouble());
366 
367               if (isAtEnd()) {
368                 return;
369               }
370               int prevPos = pos;
371               int nextTag = readVarint32();
372               if (nextTag != tag) {
373                 // We've reached the end of the repeated field. Rewind the buffer position to before
374                 // the new tag.
375                 pos = prevPos;
376                 return;
377               }
378             }
379           default:
380             throw InvalidProtocolBufferException.invalidWireType();
381         }
382       } else {
383         switch (WireFormat.getTagWireType(tag)) {
384           case WIRETYPE_LENGTH_DELIMITED:
385             final int bytes = readVarint32();
386             verifyPackedFixed64Length(bytes);
387             final int fieldEndPos = pos + bytes;
388             while (pos < fieldEndPos) {
389               target.add(Double.longBitsToDouble(readLittleEndian64_NoCheck()));
390             }
391             break;
392           case WIRETYPE_FIXED64:
393             while (true) {
394               target.add(readDouble());
395 
396               if (isAtEnd()) {
397                 return;
398               }
399               int prevPos = pos;
400               int nextTag = readVarint32();
401               if (nextTag != tag) {
402                 // We've reached the end of the repeated field. Rewind the buffer position to before
403                 // the new tag.
404                 pos = prevPos;
405                 return;
406               }
407             }
408           default:
409             throw InvalidProtocolBufferException.invalidWireType();
410         }
411       }
412     }
413 
414     @Override
readFloatList(List<Float> target)415     public void readFloatList(List<Float> target) throws IOException {
416       if (target instanceof FloatArrayList) {
417         FloatArrayList plist = (FloatArrayList) target;
418         switch (WireFormat.getTagWireType(tag)) {
419           case WIRETYPE_LENGTH_DELIMITED:
420             final int bytes = readVarint32();
421             verifyPackedFixed32Length(bytes);
422             final int fieldEndPos = pos + bytes;
423             while (pos < fieldEndPos) {
424               plist.addFloat(Float.intBitsToFloat(readLittleEndian32_NoCheck()));
425             }
426             break;
427           case WIRETYPE_FIXED32:
428             while (true) {
429               plist.addFloat(readFloat());
430 
431               if (isAtEnd()) {
432                 return;
433               }
434               int prevPos = pos;
435               int nextTag = readVarint32();
436               if (nextTag != tag) {
437                 // We've reached the end of the repeated field. Rewind the buffer position to before
438                 // the new tag.
439                 pos = prevPos;
440                 return;
441               }
442             }
443           default:
444             throw InvalidProtocolBufferException.invalidWireType();
445         }
446       } else {
447         switch (WireFormat.getTagWireType(tag)) {
448           case WIRETYPE_LENGTH_DELIMITED:
449             final int bytes = readVarint32();
450             verifyPackedFixed32Length(bytes);
451             final int fieldEndPos = pos + bytes;
452             while (pos < fieldEndPos) {
453               target.add(Float.intBitsToFloat(readLittleEndian32_NoCheck()));
454             }
455             break;
456           case WIRETYPE_FIXED32:
457             while (true) {
458               target.add(readFloat());
459 
460               if (isAtEnd()) {
461                 return;
462               }
463               int prevPos = pos;
464               int nextTag = readVarint32();
465               if (nextTag != tag) {
466                 // We've reached the end of the repeated field. Rewind the buffer position to before
467                 // the new tag.
468                 pos = prevPos;
469                 return;
470               }
471             }
472           default:
473             throw InvalidProtocolBufferException.invalidWireType();
474         }
475       }
476     }
477 
478     @Override
readUInt64List(List<Long> target)479     public void readUInt64List(List<Long> target) throws IOException {
480       if (target instanceof LongArrayList) {
481         LongArrayList plist = (LongArrayList) target;
482         switch (WireFormat.getTagWireType(tag)) {
483           case WIRETYPE_LENGTH_DELIMITED:
484             final int bytes = readVarint32();
485             final int fieldEndPos = pos + bytes;
486             while (pos < fieldEndPos) {
487               plist.addLong(readVarint64());
488             }
489             requirePosition(fieldEndPos);
490             break;
491           case WIRETYPE_VARINT:
492             while (true) {
493               plist.addLong(readUInt64());
494 
495               if (isAtEnd()) {
496                 return;
497               }
498               int prevPos = pos;
499               int nextTag = readVarint32();
500               if (nextTag != tag) {
501                 // We've reached the end of the repeated field. Rewind the buffer position to before
502                 // the new tag.
503                 pos = prevPos;
504                 return;
505               }
506             }
507           default:
508             throw InvalidProtocolBufferException.invalidWireType();
509         }
510       } else {
511         switch (WireFormat.getTagWireType(tag)) {
512           case WIRETYPE_LENGTH_DELIMITED:
513             final int bytes = readVarint32();
514             final int fieldEndPos = pos + bytes;
515             while (pos < fieldEndPos) {
516               target.add(readVarint64());
517             }
518             requirePosition(fieldEndPos);
519             break;
520           case WIRETYPE_VARINT:
521             while (true) {
522               target.add(readUInt64());
523 
524               if (isAtEnd()) {
525                 return;
526               }
527               int prevPos = pos;
528               int nextTag = readVarint32();
529               if (nextTag != tag) {
530                 // We've reached the end of the repeated field. Rewind the buffer position to before
531                 // the new tag.
532                 pos = prevPos;
533                 return;
534               }
535             }
536           default:
537             throw InvalidProtocolBufferException.invalidWireType();
538         }
539       }
540     }
541 
542     @Override
readInt64List(List<Long> target)543     public void readInt64List(List<Long> target) throws IOException {
544       if (target instanceof LongArrayList) {
545         LongArrayList plist = (LongArrayList) target;
546         switch (WireFormat.getTagWireType(tag)) {
547           case WIRETYPE_LENGTH_DELIMITED:
548             final int bytes = readVarint32();
549             final int fieldEndPos = pos + bytes;
550             while (pos < fieldEndPos) {
551               plist.addLong(readVarint64());
552             }
553             requirePosition(fieldEndPos);
554             break;
555           case WIRETYPE_VARINT:
556             while (true) {
557               plist.addLong(readInt64());
558 
559               if (isAtEnd()) {
560                 return;
561               }
562               int prevPos = pos;
563               int nextTag = readVarint32();
564               if (nextTag != tag) {
565                 // We've reached the end of the repeated field. Rewind the buffer position to before
566                 // the new tag.
567                 pos = prevPos;
568                 return;
569               }
570             }
571           default:
572             throw InvalidProtocolBufferException.invalidWireType();
573         }
574       } else {
575         switch (WireFormat.getTagWireType(tag)) {
576           case WIRETYPE_LENGTH_DELIMITED:
577             final int bytes = readVarint32();
578             final int fieldEndPos = pos + bytes;
579             while (pos < fieldEndPos) {
580               target.add(readVarint64());
581             }
582             requirePosition(fieldEndPos);
583             break;
584           case WIRETYPE_VARINT:
585             while (true) {
586               target.add(readInt64());
587 
588               if (isAtEnd()) {
589                 return;
590               }
591               int prevPos = pos;
592               int nextTag = readVarint32();
593               if (nextTag != tag) {
594                 // We've reached the end of the repeated field. Rewind the buffer position to before
595                 // the new tag.
596                 pos = prevPos;
597                 return;
598               }
599             }
600           default:
601             throw InvalidProtocolBufferException.invalidWireType();
602         }
603       }
604     }
605 
606     @Override
readInt32List(List<Integer> target)607     public void readInt32List(List<Integer> target) throws IOException {
608       if (target instanceof IntArrayList) {
609         IntArrayList plist = (IntArrayList) target;
610         switch (WireFormat.getTagWireType(tag)) {
611           case WIRETYPE_LENGTH_DELIMITED:
612             final int bytes = readVarint32();
613             final int fieldEndPos = pos + bytes;
614             while (pos < fieldEndPos) {
615               plist.addInt(readVarint32());
616             }
617             requirePosition(fieldEndPos);
618             break;
619           case WIRETYPE_VARINT:
620             while (true) {
621               plist.addInt(readInt32());
622 
623               if (isAtEnd()) {
624                 return;
625               }
626               int prevPos = pos;
627               int nextTag = readVarint32();
628               if (nextTag != tag) {
629                 // We've reached the end of the repeated field. Rewind the buffer position to before
630                 // the new tag.
631                 pos = prevPos;
632                 return;
633               }
634             }
635           default:
636             throw InvalidProtocolBufferException.invalidWireType();
637         }
638       } else {
639         switch (WireFormat.getTagWireType(tag)) {
640           case WIRETYPE_LENGTH_DELIMITED:
641             final int bytes = readVarint32();
642             final int fieldEndPos = pos + bytes;
643             while (pos < fieldEndPos) {
644               target.add(readVarint32());
645             }
646             requirePosition(fieldEndPos);
647             break;
648           case WIRETYPE_VARINT:
649             while (true) {
650               target.add(readInt32());
651 
652               if (isAtEnd()) {
653                 return;
654               }
655               int prevPos = pos;
656               int nextTag = readVarint32();
657               if (nextTag != tag) {
658                 // We've reached the end of the repeated field. Rewind the buffer position to before
659                 // the new tag.
660                 pos = prevPos;
661                 return;
662               }
663             }
664           default:
665             throw InvalidProtocolBufferException.invalidWireType();
666         }
667       }
668     }
669 
670     @Override
readFixed64List(List<Long> target)671     public void readFixed64List(List<Long> target) throws IOException {
672       if (target instanceof LongArrayList) {
673         LongArrayList plist = (LongArrayList) target;
674         switch (WireFormat.getTagWireType(tag)) {
675           case WIRETYPE_LENGTH_DELIMITED:
676             final int bytes = readVarint32();
677             verifyPackedFixed64Length(bytes);
678             final int fieldEndPos = pos + bytes;
679             while (pos < fieldEndPos) {
680               plist.addLong(readLittleEndian64_NoCheck());
681             }
682             break;
683           case WIRETYPE_FIXED64:
684             while (true) {
685               plist.addLong(readFixed64());
686 
687               if (isAtEnd()) {
688                 return;
689               }
690               int prevPos = pos;
691               int nextTag = readVarint32();
692               if (nextTag != tag) {
693                 // We've reached the end of the repeated field. Rewind the buffer position to before
694                 // the new tag.
695                 pos = prevPos;
696                 return;
697               }
698             }
699           default:
700             throw InvalidProtocolBufferException.invalidWireType();
701         }
702       } else {
703         switch (WireFormat.getTagWireType(tag)) {
704           case WIRETYPE_LENGTH_DELIMITED:
705             final int bytes = readVarint32();
706             verifyPackedFixed64Length(bytes);
707             final int fieldEndPos = pos + bytes;
708             while (pos < fieldEndPos) {
709               target.add(readLittleEndian64_NoCheck());
710             }
711             break;
712           case WIRETYPE_FIXED64:
713             while (true) {
714               target.add(readFixed64());
715 
716               if (isAtEnd()) {
717                 return;
718               }
719               int prevPos = pos;
720               int nextTag = readVarint32();
721               if (nextTag != tag) {
722                 // We've reached the end of the repeated field. Rewind the buffer position to before
723                 // the new tag.
724                 pos = prevPos;
725                 return;
726               }
727             }
728           default:
729             throw InvalidProtocolBufferException.invalidWireType();
730         }
731       }
732     }
733 
734     @Override
readFixed32List(List<Integer> target)735     public void readFixed32List(List<Integer> target) throws IOException {
736       if (target instanceof IntArrayList) {
737         IntArrayList plist = (IntArrayList) target;
738         switch (WireFormat.getTagWireType(tag)) {
739           case WIRETYPE_LENGTH_DELIMITED:
740             final int bytes = readVarint32();
741             verifyPackedFixed32Length(bytes);
742             final int fieldEndPos = pos + bytes;
743             while (pos < fieldEndPos) {
744               plist.addInt(readLittleEndian32_NoCheck());
745             }
746             break;
747           case WIRETYPE_FIXED32:
748             while (true) {
749               plist.addInt(readFixed32());
750 
751               if (isAtEnd()) {
752                 return;
753               }
754               int prevPos = pos;
755               int nextTag = readVarint32();
756               if (nextTag != tag) {
757                 // We've reached the end of the repeated field. Rewind the buffer position to before
758                 // the new tag.
759                 pos = prevPos;
760                 return;
761               }
762             }
763           default:
764             throw InvalidProtocolBufferException.invalidWireType();
765         }
766       } else {
767         switch (WireFormat.getTagWireType(tag)) {
768           case WIRETYPE_LENGTH_DELIMITED:
769             final int bytes = readVarint32();
770             verifyPackedFixed32Length(bytes);
771             final int fieldEndPos = pos + bytes;
772             while (pos < fieldEndPos) {
773               target.add(readLittleEndian32_NoCheck());
774             }
775             break;
776           case WIRETYPE_FIXED32:
777             while (true) {
778               target.add(readFixed32());
779 
780               if (isAtEnd()) {
781                 return;
782               }
783               int prevPos = pos;
784               int nextTag = readVarint32();
785               if (nextTag != tag) {
786                 // We've reached the end of the repeated field. Rewind the buffer position to before
787                 // the new tag.
788                 pos = prevPos;
789                 return;
790               }
791             }
792           default:
793             throw InvalidProtocolBufferException.invalidWireType();
794         }
795       }
796     }
797 
798     @Override
readBoolList(List<Boolean> target)799     public void readBoolList(List<Boolean> target) throws IOException {
800       if (target instanceof BooleanArrayList) {
801         BooleanArrayList plist = (BooleanArrayList) target;
802         switch (WireFormat.getTagWireType(tag)) {
803           case WIRETYPE_LENGTH_DELIMITED:
804             final int bytes = readVarint32();
805             final int fieldEndPos = pos + bytes;
806             while (pos < fieldEndPos) {
807               plist.addBoolean(readVarint32() != 0);
808             }
809             requirePosition(fieldEndPos);
810             break;
811           case WIRETYPE_VARINT:
812             while (true) {
813               plist.addBoolean(readBool());
814 
815               if (isAtEnd()) {
816                 return;
817               }
818               int prevPos = pos;
819               int nextTag = readVarint32();
820               if (nextTag != tag) {
821                 // We've reached the end of the repeated field. Rewind the buffer position to before
822                 // the new tag.
823                 pos = prevPos;
824                 return;
825               }
826             }
827           default:
828             throw InvalidProtocolBufferException.invalidWireType();
829         }
830       } else {
831         switch (WireFormat.getTagWireType(tag)) {
832           case WIRETYPE_LENGTH_DELIMITED:
833             final int bytes = readVarint32();
834             final int fieldEndPos = pos + bytes;
835             while (pos < fieldEndPos) {
836               target.add(readVarint32() != 0);
837             }
838             requirePosition(fieldEndPos);
839             break;
840           case WIRETYPE_VARINT:
841             while (true) {
842               target.add(readBool());
843 
844               if (isAtEnd()) {
845                 return;
846               }
847               int prevPos = pos;
848               int nextTag = readVarint32();
849               if (nextTag != tag) {
850                 // We've reached the end of the repeated field. Rewind the buffer position to before
851                 // the new tag.
852                 pos = prevPos;
853                 return;
854               }
855             }
856           default:
857             throw InvalidProtocolBufferException.invalidWireType();
858         }
859       }
860     }
861 
862     @Override
readStringList(List<String> target)863     public void readStringList(List<String> target) throws IOException {
864       readStringListInternal(target, false);
865     }
866 
867     @Override
readStringListRequireUtf8(List<String> target)868     public void readStringListRequireUtf8(List<String> target) throws IOException {
869       readStringListInternal(target, true);
870     }
871 
readStringListInternal(List<String> target, boolean requireUtf8)872     public void readStringListInternal(List<String> target, boolean requireUtf8)
873         throws IOException {
874       if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
875         throw InvalidProtocolBufferException.invalidWireType();
876       }
877 
878       if (target instanceof LazyStringList && !requireUtf8) {
879         LazyStringList lazyList = (LazyStringList) target;
880         while (true) {
881           lazyList.add(readBytes());
882 
883           if (isAtEnd()) {
884             return;
885           }
886           int prevPos = pos;
887           int nextTag = readVarint32();
888           if (nextTag != tag) {
889             // We've reached the end of the repeated field. Rewind the buffer position to before
890             // the new tag.
891             pos = prevPos;
892             return;
893           }
894         }
895       } else {
896         while (true) {
897           target.add(readStringInternal(requireUtf8));
898 
899           if (isAtEnd()) {
900             return;
901           }
902           int prevPos = pos;
903           int nextTag = readVarint32();
904           if (nextTag != tag) {
905             // We've reached the end of the repeated field. Rewind the buffer position to before
906             // the new tag.
907             pos = prevPos;
908             return;
909           }
910         }
911       }
912     }
913 
914     @Override
readMessageList( List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)915     public <T> void readMessageList(
916         List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
917         throws IOException {
918       final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
919       readMessageList(target, schema, extensionRegistry);
920     }
921 
922     @Override
readMessageList( List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)923     public <T> void readMessageList(
924         List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
925         throws IOException {
926       if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
927         throw InvalidProtocolBufferException.invalidWireType();
928       }
929       final int listTag = tag;
930       while (true) {
931         target.add(readMessage(schema, extensionRegistry));
932 
933         if (isAtEnd()) {
934           return;
935         }
936         int prevPos = pos;
937         int nextTag = readVarint32();
938         if (nextTag != listTag) {
939           // We've reached the end of the repeated field. Rewind the buffer position to before
940           // the new tag.
941           pos = prevPos;
942           return;
943         }
944       }
945     }
946 
947     @Deprecated
948     @Override
readGroupList( List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)949     public <T> void readGroupList(
950         List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
951         throws IOException {
952       final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
953       readGroupList(target, schema, extensionRegistry);
954     }
955 
956     @Deprecated
957     @Override
readGroupList( List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)958     public <T> void readGroupList(
959         List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
960         throws IOException {
961       if (WireFormat.getTagWireType(tag) != WIRETYPE_START_GROUP) {
962         throw InvalidProtocolBufferException.invalidWireType();
963       }
964       final int listTag = tag;
965       while (true) {
966         target.add(readGroup(schema, extensionRegistry));
967 
968         if (isAtEnd()) {
969           return;
970         }
971         int prevPos = pos;
972         int nextTag = readVarint32();
973         if (nextTag != listTag) {
974           // We've reached the end of the repeated field. Rewind the buffer position to before
975           // the new tag.
976           pos = prevPos;
977           return;
978         }
979       }
980     }
981 
982     @Override
readBytesList(List<ByteString> target)983     public void readBytesList(List<ByteString> target) throws IOException {
984       if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
985         throw InvalidProtocolBufferException.invalidWireType();
986       }
987 
988       while (true) {
989         target.add(readBytes());
990 
991         if (isAtEnd()) {
992           return;
993         }
994         int prevPos = pos;
995         int nextTag = readVarint32();
996         if (nextTag != tag) {
997           // We've reached the end of the repeated field. Rewind the buffer position to before
998           // the new tag.
999           pos = prevPos;
1000           return;
1001         }
1002       }
1003     }
1004 
1005     @Override
readUInt32List(List<Integer> target)1006     public void readUInt32List(List<Integer> target) throws IOException {
1007       if (target instanceof IntArrayList) {
1008         IntArrayList plist = (IntArrayList) target;
1009         switch (WireFormat.getTagWireType(tag)) {
1010           case WIRETYPE_LENGTH_DELIMITED:
1011             final int bytes = readVarint32();
1012             final int fieldEndPos = pos + bytes;
1013             while (pos < fieldEndPos) {
1014               plist.addInt(readVarint32());
1015             }
1016             break;
1017           case WIRETYPE_VARINT:
1018             while (true) {
1019               plist.addInt(readUInt32());
1020 
1021               if (isAtEnd()) {
1022                 return;
1023               }
1024               int prevPos = pos;
1025               int nextTag = readVarint32();
1026               if (nextTag != tag) {
1027                 // We've reached the end of the repeated field. Rewind the buffer position to before
1028                 // the new tag.
1029                 pos = prevPos;
1030                 return;
1031               }
1032             }
1033           default:
1034             throw InvalidProtocolBufferException.invalidWireType();
1035         }
1036       } else {
1037         switch (WireFormat.getTagWireType(tag)) {
1038           case WIRETYPE_LENGTH_DELIMITED:
1039             final int bytes = readVarint32();
1040             final int fieldEndPos = pos + bytes;
1041             while (pos < fieldEndPos) {
1042               target.add(readVarint32());
1043             }
1044             break;
1045           case WIRETYPE_VARINT:
1046             while (true) {
1047               target.add(readUInt32());
1048 
1049               if (isAtEnd()) {
1050                 return;
1051               }
1052               int prevPos = pos;
1053               int nextTag = readVarint32();
1054               if (nextTag != tag) {
1055                 // We've reached the end of the repeated field. Rewind the buffer position to before
1056                 // the new tag.
1057                 pos = prevPos;
1058                 return;
1059               }
1060             }
1061           default:
1062             throw InvalidProtocolBufferException.invalidWireType();
1063         }
1064       }
1065     }
1066 
1067     @Override
readEnumList(List<Integer> target)1068     public void readEnumList(List<Integer> target) throws IOException {
1069       if (target instanceof IntArrayList) {
1070         IntArrayList plist = (IntArrayList) target;
1071         switch (WireFormat.getTagWireType(tag)) {
1072           case WIRETYPE_LENGTH_DELIMITED:
1073             final int bytes = readVarint32();
1074             final int fieldEndPos = pos + bytes;
1075             while (pos < fieldEndPos) {
1076               plist.addInt(readVarint32());
1077             }
1078             break;
1079           case WIRETYPE_VARINT:
1080             while (true) {
1081               plist.addInt(readEnum());
1082 
1083               if (isAtEnd()) {
1084                 return;
1085               }
1086               int prevPos = pos;
1087               int nextTag = readVarint32();
1088               if (nextTag != tag) {
1089                 // We've reached the end of the repeated field. Rewind the buffer position to before
1090                 // the new tag.
1091                 pos = prevPos;
1092                 return;
1093               }
1094             }
1095           default:
1096             throw InvalidProtocolBufferException.invalidWireType();
1097         }
1098       } else {
1099         switch (WireFormat.getTagWireType(tag)) {
1100           case WIRETYPE_LENGTH_DELIMITED:
1101             final int bytes = readVarint32();
1102             final int fieldEndPos = pos + bytes;
1103             while (pos < fieldEndPos) {
1104               target.add(readVarint32());
1105             }
1106             break;
1107           case WIRETYPE_VARINT:
1108             while (true) {
1109               target.add(readEnum());
1110 
1111               if (isAtEnd()) {
1112                 return;
1113               }
1114               int prevPos = pos;
1115               int nextTag = readVarint32();
1116               if (nextTag != tag) {
1117                 // We've reached the end of the repeated field. Rewind the buffer position to before
1118                 // the new tag.
1119                 pos = prevPos;
1120                 return;
1121               }
1122             }
1123           default:
1124             throw InvalidProtocolBufferException.invalidWireType();
1125         }
1126       }
1127     }
1128 
1129     @Override
readSFixed32List(List<Integer> target)1130     public void readSFixed32List(List<Integer> target) throws IOException {
1131       if (target instanceof IntArrayList) {
1132         IntArrayList plist = (IntArrayList) target;
1133         switch (WireFormat.getTagWireType(tag)) {
1134           case WIRETYPE_LENGTH_DELIMITED:
1135             final int bytes = readVarint32();
1136             verifyPackedFixed32Length(bytes);
1137             final int fieldEndPos = pos + bytes;
1138             while (pos < fieldEndPos) {
1139               plist.addInt(readLittleEndian32_NoCheck());
1140             }
1141             break;
1142           case WIRETYPE_FIXED32:
1143             while (true) {
1144               plist.addInt(readSFixed32());
1145 
1146               if (isAtEnd()) {
1147                 return;
1148               }
1149               int prevPos = pos;
1150               int nextTag = readVarint32();
1151               if (nextTag != tag) {
1152                 // We've reached the end of the repeated field. Rewind the buffer position to before
1153                 // the new tag.
1154                 pos = prevPos;
1155                 return;
1156               }
1157             }
1158           default:
1159             throw InvalidProtocolBufferException.invalidWireType();
1160         }
1161       } else {
1162         switch (WireFormat.getTagWireType(tag)) {
1163           case WIRETYPE_LENGTH_DELIMITED:
1164             final int bytes = readVarint32();
1165             verifyPackedFixed32Length(bytes);
1166             final int fieldEndPos = pos + bytes;
1167             while (pos < fieldEndPos) {
1168               target.add(readLittleEndian32_NoCheck());
1169             }
1170             break;
1171           case WIRETYPE_FIXED32:
1172             while (true) {
1173               target.add(readSFixed32());
1174 
1175               if (isAtEnd()) {
1176                 return;
1177               }
1178               int prevPos = pos;
1179               int nextTag = readVarint32();
1180               if (nextTag != tag) {
1181                 // We've reached the end of the repeated field. Rewind the buffer position to before
1182                 // the new tag.
1183                 pos = prevPos;
1184                 return;
1185               }
1186             }
1187           default:
1188             throw InvalidProtocolBufferException.invalidWireType();
1189         }
1190       }
1191     }
1192 
1193     @Override
readSFixed64List(List<Long> target)1194     public void readSFixed64List(List<Long> target) throws IOException {
1195       if (target instanceof LongArrayList) {
1196         LongArrayList plist = (LongArrayList) target;
1197         switch (WireFormat.getTagWireType(tag)) {
1198           case WIRETYPE_LENGTH_DELIMITED:
1199             final int bytes = readVarint32();
1200             verifyPackedFixed64Length(bytes);
1201             final int fieldEndPos = pos + bytes;
1202             while (pos < fieldEndPos) {
1203               plist.addLong(readLittleEndian64_NoCheck());
1204             }
1205             break;
1206           case WIRETYPE_FIXED64:
1207             while (true) {
1208               plist.addLong(readSFixed64());
1209 
1210               if (isAtEnd()) {
1211                 return;
1212               }
1213               int prevPos = pos;
1214               int nextTag = readVarint32();
1215               if (nextTag != tag) {
1216                 // We've reached the end of the repeated field. Rewind the buffer position to before
1217                 // the new tag.
1218                 pos = prevPos;
1219                 return;
1220               }
1221             }
1222           default:
1223             throw InvalidProtocolBufferException.invalidWireType();
1224         }
1225       } else {
1226         switch (WireFormat.getTagWireType(tag)) {
1227           case WIRETYPE_LENGTH_DELIMITED:
1228             final int bytes = readVarint32();
1229             verifyPackedFixed64Length(bytes);
1230             final int fieldEndPos = pos + bytes;
1231             while (pos < fieldEndPos) {
1232               target.add(readLittleEndian64_NoCheck());
1233             }
1234             break;
1235           case WIRETYPE_FIXED64:
1236             while (true) {
1237               target.add(readSFixed64());
1238 
1239               if (isAtEnd()) {
1240                 return;
1241               }
1242               int prevPos = pos;
1243               int nextTag = readVarint32();
1244               if (nextTag != tag) {
1245                 // We've reached the end of the repeated field. Rewind the buffer position to before
1246                 // the new tag.
1247                 pos = prevPos;
1248                 return;
1249               }
1250             }
1251           default:
1252             throw InvalidProtocolBufferException.invalidWireType();
1253         }
1254       }
1255     }
1256 
1257     @Override
readSInt32List(List<Integer> target)1258     public void readSInt32List(List<Integer> target) throws IOException {
1259       if (target instanceof IntArrayList) {
1260         IntArrayList plist = (IntArrayList) target;
1261         switch (WireFormat.getTagWireType(tag)) {
1262           case WIRETYPE_LENGTH_DELIMITED:
1263             final int bytes = readVarint32();
1264             final int fieldEndPos = pos + bytes;
1265             while (pos < fieldEndPos) {
1266               plist.addInt(CodedInputStream.decodeZigZag32(readVarint32()));
1267             }
1268             break;
1269           case WIRETYPE_VARINT:
1270             while (true) {
1271               plist.addInt(readSInt32());
1272 
1273               if (isAtEnd()) {
1274                 return;
1275               }
1276               int prevPos = pos;
1277               int nextTag = readVarint32();
1278               if (nextTag != tag) {
1279                 // We've reached the end of the repeated field. Rewind the buffer position to before
1280                 // the new tag.
1281                 pos = prevPos;
1282                 return;
1283               }
1284             }
1285           default:
1286             throw InvalidProtocolBufferException.invalidWireType();
1287         }
1288       } else {
1289         switch (WireFormat.getTagWireType(tag)) {
1290           case WIRETYPE_LENGTH_DELIMITED:
1291             final int bytes = readVarint32();
1292             final int fieldEndPos = pos + bytes;
1293             while (pos < fieldEndPos) {
1294               target.add(CodedInputStream.decodeZigZag32(readVarint32()));
1295             }
1296             break;
1297           case WIRETYPE_VARINT:
1298             while (true) {
1299               target.add(readSInt32());
1300 
1301               if (isAtEnd()) {
1302                 return;
1303               }
1304               int prevPos = pos;
1305               int nextTag = readVarint32();
1306               if (nextTag != tag) {
1307                 // We've reached the end of the repeated field. Rewind the buffer position to before
1308                 // the new tag.
1309                 pos = prevPos;
1310                 return;
1311               }
1312             }
1313           default:
1314             throw InvalidProtocolBufferException.invalidWireType();
1315         }
1316       }
1317     }
1318 
1319     @Override
readSInt64List(List<Long> target)1320     public void readSInt64List(List<Long> target) throws IOException {
1321       if (target instanceof LongArrayList) {
1322         LongArrayList plist = (LongArrayList) target;
1323         switch (WireFormat.getTagWireType(tag)) {
1324           case WIRETYPE_LENGTH_DELIMITED:
1325             final int bytes = readVarint32();
1326             final int fieldEndPos = pos + bytes;
1327             while (pos < fieldEndPos) {
1328               plist.addLong(CodedInputStream.decodeZigZag64(readVarint64()));
1329             }
1330             break;
1331           case WIRETYPE_VARINT:
1332             while (true) {
1333               plist.addLong(readSInt64());
1334 
1335               if (isAtEnd()) {
1336                 return;
1337               }
1338               int prevPos = pos;
1339               int nextTag = readVarint32();
1340               if (nextTag != tag) {
1341                 // We've reached the end of the repeated field. Rewind the buffer position to before
1342                 // the new tag.
1343                 pos = prevPos;
1344                 return;
1345               }
1346             }
1347           default:
1348             throw InvalidProtocolBufferException.invalidWireType();
1349         }
1350       } else {
1351         switch (WireFormat.getTagWireType(tag)) {
1352           case WIRETYPE_LENGTH_DELIMITED:
1353             final int bytes = readVarint32();
1354             final int fieldEndPos = pos + bytes;
1355             while (pos < fieldEndPos) {
1356               target.add(CodedInputStream.decodeZigZag64(readVarint64()));
1357             }
1358             break;
1359           case WIRETYPE_VARINT:
1360             while (true) {
1361               target.add(readSInt64());
1362 
1363               if (isAtEnd()) {
1364                 return;
1365               }
1366               int prevPos = pos;
1367               int nextTag = readVarint32();
1368               if (nextTag != tag) {
1369                 // We've reached the end of the repeated field. Rewind the buffer position to before
1370                 // the new tag.
1371                 pos = prevPos;
1372                 return;
1373               }
1374             }
1375           default:
1376             throw InvalidProtocolBufferException.invalidWireType();
1377         }
1378       }
1379     }
1380 
1381     @SuppressWarnings("unchecked")
1382     @Override
readMap( Map<K, V> target, MapEntryLite.Metadata<K, V> metadata, ExtensionRegistryLite extensionRegistry)1383     public <K, V> void readMap(
1384         Map<K, V> target,
1385         MapEntryLite.Metadata<K, V> metadata,
1386         ExtensionRegistryLite extensionRegistry)
1387         throws IOException {
1388       requireWireType(WIRETYPE_LENGTH_DELIMITED);
1389       int size = readVarint32();
1390       requireBytes(size);
1391 
1392       // Update the limit.
1393       int prevLimit = limit;
1394       int newLimit = pos + size;
1395       limit = newLimit;
1396 
1397       try {
1398         K key = metadata.defaultKey;
1399         V value = metadata.defaultValue;
1400         while (true) {
1401           int number = getFieldNumber();
1402           if (number == READ_DONE) {
1403             break;
1404           }
1405           try {
1406             switch (number) {
1407               case 1:
1408                 key = (K) readField(metadata.keyType, null, null);
1409                 break;
1410               case 2:
1411                 value =
1412                     (V)
1413                         readField(
1414                             metadata.valueType,
1415                             metadata.defaultValue.getClass(),
1416                             extensionRegistry);
1417                 break;
1418               default:
1419                 if (!skipField()) {
1420                   throw new InvalidProtocolBufferException("Unable to parse map entry.");
1421                 }
1422                 break;
1423             }
1424           } catch (InvalidProtocolBufferException.InvalidWireTypeException ignore) {
1425             // the type doesn't match, skip the field.
1426             if (!skipField()) {
1427               throw new InvalidProtocolBufferException("Unable to parse map entry.");
1428             }
1429           }
1430         }
1431         target.put(key, value);
1432       } finally {
1433         // Restore the limit.
1434         limit = prevLimit;
1435       }
1436     }
1437 
readField( WireFormat.FieldType fieldType, Class<?> messageType, ExtensionRegistryLite extensionRegistry)1438     private Object readField(
1439         WireFormat.FieldType fieldType,
1440         Class<?> messageType,
1441         ExtensionRegistryLite extensionRegistry)
1442         throws IOException {
1443       switch (fieldType) {
1444         case BOOL:
1445           return readBool();
1446         case BYTES:
1447           return readBytes();
1448         case DOUBLE:
1449           return readDouble();
1450         case ENUM:
1451           return readEnum();
1452         case FIXED32:
1453           return readFixed32();
1454         case FIXED64:
1455           return readFixed64();
1456         case FLOAT:
1457           return readFloat();
1458         case INT32:
1459           return readInt32();
1460         case INT64:
1461           return readInt64();
1462         case MESSAGE:
1463           return readMessage(messageType, extensionRegistry);
1464         case SFIXED32:
1465           return readSFixed32();
1466         case SFIXED64:
1467           return readSFixed64();
1468         case SINT32:
1469           return readSInt32();
1470         case SINT64:
1471           return readSInt64();
1472         case STRING:
1473           return readStringRequireUtf8();
1474         case UINT32:
1475           return readUInt32();
1476         case UINT64:
1477           return readUInt64();
1478         default:
1479           throw new RuntimeException("unsupported field type.");
1480       }
1481     }
1482 
1483     /** Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits. */
readVarint32()1484     private int readVarint32() throws IOException {
1485       // See implementation notes for readRawVarint64
1486       int i = pos;
1487 
1488       if (limit == pos) {
1489         throw InvalidProtocolBufferException.truncatedMessage();
1490       }
1491 
1492       int x;
1493       if ((x = buffer[i++]) >= 0) {
1494         pos = i;
1495         return x;
1496       } else if (limit - i < 9) {
1497         return (int) readVarint64SlowPath();
1498       } else if ((x ^= (buffer[i++] << 7)) < 0) {
1499         x ^= (~0 << 7);
1500       } else if ((x ^= (buffer[i++] << 14)) >= 0) {
1501         x ^= (~0 << 7) ^ (~0 << 14);
1502       } else if ((x ^= (buffer[i++] << 21)) < 0) {
1503         x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
1504       } else {
1505         int y = buffer[i++];
1506         x ^= y << 28;
1507         x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
1508         if (y < 0
1509             && buffer[i++] < 0
1510             && buffer[i++] < 0
1511             && buffer[i++] < 0
1512             && buffer[i++] < 0
1513             && buffer[i++] < 0) {
1514           throw InvalidProtocolBufferException.malformedVarint();
1515         }
1516       }
1517       pos = i;
1518       return x;
1519     }
1520 
readVarint64()1521     public long readVarint64() throws IOException {
1522       // Implementation notes:
1523       //
1524       // Optimized for one-byte values, expected to be common.
1525       // The particular code below was selected from various candidates
1526       // empirically, by winning VarintBenchmark.
1527       //
1528       // Sign extension of (signed) Java bytes is usually a nuisance, but
1529       // we exploit it here to more easily obtain the sign of bytes read.
1530       // Instead of cleaning up the sign extension bits by masking eagerly,
1531       // we delay until we find the final (positive) byte, when we clear all
1532       // accumulated bits with one xor.  We depend on javac to constant fold.
1533       int i = pos;
1534 
1535       if (limit == i) {
1536         throw InvalidProtocolBufferException.truncatedMessage();
1537       }
1538 
1539       final byte[] buffer = this.buffer;
1540       long x;
1541       int y;
1542       if ((y = buffer[i++]) >= 0) {
1543         pos = i;
1544         return y;
1545       } else if (limit - i < 9) {
1546         return readVarint64SlowPath();
1547       } else if ((y ^= (buffer[i++] << 7)) < 0) {
1548         x = y ^ (~0 << 7);
1549       } else if ((y ^= (buffer[i++] << 14)) >= 0) {
1550         x = y ^ ((~0 << 7) ^ (~0 << 14));
1551       } else if ((y ^= (buffer[i++] << 21)) < 0) {
1552         x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
1553       } else if ((x = y ^ ((long) buffer[i++] << 28)) >= 0L) {
1554         x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
1555       } else if ((x ^= ((long) buffer[i++] << 35)) < 0L) {
1556         x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
1557       } else if ((x ^= ((long) buffer[i++] << 42)) >= 0L) {
1558         x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
1559       } else if ((x ^= ((long) buffer[i++] << 49)) < 0L) {
1560         x ^=
1561             (~0L << 7)
1562                 ^ (~0L << 14)
1563                 ^ (~0L << 21)
1564                 ^ (~0L << 28)
1565                 ^ (~0L << 35)
1566                 ^ (~0L << 42)
1567                 ^ (~0L << 49);
1568       } else {
1569         x ^= ((long) buffer[i++] << 56);
1570         x ^=
1571             (~0L << 7)
1572                 ^ (~0L << 14)
1573                 ^ (~0L << 21)
1574                 ^ (~0L << 28)
1575                 ^ (~0L << 35)
1576                 ^ (~0L << 42)
1577                 ^ (~0L << 49)
1578                 ^ (~0L << 56);
1579         if (x < 0L) {
1580           if (buffer[i++] < 0L) {
1581             throw InvalidProtocolBufferException.malformedVarint();
1582           }
1583         }
1584       }
1585       pos = i;
1586       return x;
1587     }
1588 
readVarint64SlowPath()1589     private long readVarint64SlowPath() throws IOException {
1590       long result = 0;
1591       for (int shift = 0; shift < 64; shift += 7) {
1592         final byte b = readByte();
1593         result |= (long) (b & 0x7F) << shift;
1594         if ((b & 0x80) == 0) {
1595           return result;
1596         }
1597       }
1598       throw InvalidProtocolBufferException.malformedVarint();
1599     }
1600 
readByte()1601     private byte readByte() throws IOException {
1602       if (pos == limit) {
1603         throw InvalidProtocolBufferException.truncatedMessage();
1604       }
1605       return buffer[pos++];
1606     }
1607 
readLittleEndian32()1608     private int readLittleEndian32() throws IOException {
1609       requireBytes(FIXED32_SIZE);
1610       return readLittleEndian32_NoCheck();
1611     }
1612 
readLittleEndian64()1613     private long readLittleEndian64() throws IOException {
1614       requireBytes(FIXED64_SIZE);
1615       return readLittleEndian64_NoCheck();
1616     }
1617 
readLittleEndian32_NoCheck()1618     private int readLittleEndian32_NoCheck() {
1619       int p = pos;
1620       final byte[] buffer = this.buffer;
1621       pos = p + FIXED32_SIZE;
1622       return (((buffer[p] & 0xff))
1623           | ((buffer[p + 1] & 0xff) << 8)
1624           | ((buffer[p + 2] & 0xff) << 16)
1625           | ((buffer[p + 3] & 0xff) << 24));
1626     }
1627 
readLittleEndian64_NoCheck()1628     private long readLittleEndian64_NoCheck() {
1629       int p = pos;
1630       final byte[] buffer = this.buffer;
1631       pos = p + FIXED64_SIZE;
1632       return (((buffer[p] & 0xffL))
1633           | ((buffer[p + 1] & 0xffL) << 8)
1634           | ((buffer[p + 2] & 0xffL) << 16)
1635           | ((buffer[p + 3] & 0xffL) << 24)
1636           | ((buffer[p + 4] & 0xffL) << 32)
1637           | ((buffer[p + 5] & 0xffL) << 40)
1638           | ((buffer[p + 6] & 0xffL) << 48)
1639           | ((buffer[p + 7] & 0xffL) << 56));
1640     }
1641 
skipVarint()1642     private void skipVarint() throws IOException {
1643       if (limit - pos >= 10) {
1644         final byte[] buffer = this.buffer;
1645         int p = pos;
1646         for (int i = 0; i < 10; i++) {
1647           if (buffer[p++] >= 0) {
1648             pos = p;
1649             return;
1650           }
1651         }
1652       }
1653       skipVarintSlowPath();
1654     }
1655 
skipVarintSlowPath()1656     private void skipVarintSlowPath() throws IOException {
1657       for (int i = 0; i < 10; i++) {
1658         if (readByte() >= 0) {
1659           return;
1660         }
1661       }
1662       throw InvalidProtocolBufferException.malformedVarint();
1663     }
1664 
skipBytes(final int size)1665     private void skipBytes(final int size) throws IOException {
1666       requireBytes(size);
1667 
1668       pos += size;
1669     }
1670 
skipGroup()1671     private void skipGroup() throws IOException {
1672       int prevEndGroupTag = endGroupTag;
1673       endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP);
1674       while (true) {
1675         if (getFieldNumber() == READ_DONE || !skipField()) {
1676           break;
1677         }
1678       }
1679       if (tag != endGroupTag) {
1680         throw InvalidProtocolBufferException.parseFailure();
1681       }
1682       endGroupTag = prevEndGroupTag;
1683     }
1684 
requireBytes(int size)1685     private void requireBytes(int size) throws IOException {
1686       if (size < 0 || size > (limit - pos)) {
1687         throw InvalidProtocolBufferException.truncatedMessage();
1688       }
1689     }
1690 
requireWireType(int requiredWireType)1691     private void requireWireType(int requiredWireType) throws IOException {
1692       if (WireFormat.getTagWireType(tag) != requiredWireType) {
1693         throw InvalidProtocolBufferException.invalidWireType();
1694       }
1695     }
1696 
verifyPackedFixed64Length(int bytes)1697     private void verifyPackedFixed64Length(int bytes) throws IOException {
1698       requireBytes(bytes);
1699       if ((bytes & FIXED64_MULTIPLE_MASK) != 0) {
1700         // Require that the number of bytes be a multiple of 8.
1701         throw InvalidProtocolBufferException.parseFailure();
1702       }
1703     }
1704 
verifyPackedFixed32Length(int bytes)1705     private void verifyPackedFixed32Length(int bytes) throws IOException {
1706       requireBytes(bytes);
1707       if ((bytes & FIXED32_MULTIPLE_MASK) != 0) {
1708         // Require that the number of bytes be a multiple of 4.
1709         throw InvalidProtocolBufferException.parseFailure();
1710       }
1711     }
1712 
requirePosition(int expectedPosition)1713     private void requirePosition(int expectedPosition) throws IOException {
1714       if (pos != expectedPosition) {
1715         throw InvalidProtocolBufferException.truncatedMessage();
1716       }
1717     }
1718   }
1719 }
1720