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