• 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.util.List;
44 import java.util.Map;
45 
46 /** An adapter between the {@link Reader} interface and {@link CodedInputStream}. */
47 @ExperimentalApi
48 final class CodedInputStreamReader implements Reader {
49   private static final int FIXED32_MULTIPLE_MASK = FIXED32_SIZE - 1;
50   private static final int FIXED64_MULTIPLE_MASK = FIXED64_SIZE - 1;
51   private static final int NEXT_TAG_UNSET = 0;
52 
53   private final CodedInputStream input;
54   private int tag;
55   private int endGroupTag;
56   private int nextTag = NEXT_TAG_UNSET;
57 
forCodedInput(CodedInputStream input)58   public static CodedInputStreamReader forCodedInput(CodedInputStream input) {
59     if (input.wrapper != null) {
60       return input.wrapper;
61     }
62     return new CodedInputStreamReader(input);
63   }
64 
CodedInputStreamReader(CodedInputStream input)65   private CodedInputStreamReader(CodedInputStream input) {
66     this.input = Internal.checkNotNull(input, "input");
67     this.input.wrapper = this;
68   }
69 
70   @Override
shouldDiscardUnknownFields()71   public boolean shouldDiscardUnknownFields() {
72     return input.shouldDiscardUnknownFields();
73   }
74 
75   @Override
getFieldNumber()76   public int getFieldNumber() throws IOException {
77     if (nextTag != NEXT_TAG_UNSET) {
78       tag = nextTag;
79       nextTag = NEXT_TAG_UNSET;
80     } else {
81       tag = input.readTag();
82     }
83     if (tag == 0 || tag == endGroupTag) {
84       return Reader.READ_DONE;
85     }
86     return WireFormat.getTagFieldNumber(tag);
87   }
88 
89   @Override
getTag()90   public int getTag() {
91     return tag;
92   }
93 
94   @Override
skipField()95   public boolean skipField() throws IOException {
96     if (input.isAtEnd() || tag == endGroupTag) {
97       return false;
98     }
99     return input.skipField(tag);
100   }
101 
requireWireType(int requiredWireType)102   private void requireWireType(int requiredWireType) throws IOException {
103     if (WireFormat.getTagWireType(tag) != requiredWireType) {
104       throw InvalidProtocolBufferException.invalidWireType();
105     }
106   }
107 
108   @Override
readDouble()109   public double readDouble() throws IOException {
110     requireWireType(WIRETYPE_FIXED64);
111     return input.readDouble();
112   }
113 
114   @Override
readFloat()115   public float readFloat() throws IOException {
116     requireWireType(WIRETYPE_FIXED32);
117     return input.readFloat();
118   }
119 
120   @Override
readUInt64()121   public long readUInt64() throws IOException {
122     requireWireType(WIRETYPE_VARINT);
123     return input.readUInt64();
124   }
125 
126   @Override
readInt64()127   public long readInt64() throws IOException {
128     requireWireType(WIRETYPE_VARINT);
129     return input.readInt64();
130   }
131 
132   @Override
readInt32()133   public int readInt32() throws IOException {
134     requireWireType(WIRETYPE_VARINT);
135     return input.readInt32();
136   }
137 
138   @Override
readFixed64()139   public long readFixed64() throws IOException {
140     requireWireType(WIRETYPE_FIXED64);
141     return input.readFixed64();
142   }
143 
144   @Override
readFixed32()145   public int readFixed32() throws IOException {
146     requireWireType(WIRETYPE_FIXED32);
147     return input.readFixed32();
148   }
149 
150   @Override
readBool()151   public boolean readBool() throws IOException {
152     requireWireType(WIRETYPE_VARINT);
153     return input.readBool();
154   }
155 
156   @Override
readString()157   public String readString() throws IOException {
158     requireWireType(WIRETYPE_LENGTH_DELIMITED);
159     return input.readString();
160   }
161 
162   @Override
readStringRequireUtf8()163   public String readStringRequireUtf8() throws IOException {
164     requireWireType(WIRETYPE_LENGTH_DELIMITED);
165     return input.readStringRequireUtf8();
166   }
167 
168   @SuppressWarnings("unchecked")
169   @Override
readMessage(Class<T> clazz, ExtensionRegistryLite extensionRegistry)170   public <T> T readMessage(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
171       throws IOException {
172     requireWireType(WIRETYPE_LENGTH_DELIMITED);
173     return readMessage(Protobuf.getInstance().schemaFor(clazz), extensionRegistry);
174   }
175 
176   @SuppressWarnings("unchecked")
177   @Override
readMessageBySchemaWithCheck( Schema<T> schema, ExtensionRegistryLite extensionRegistry)178   public <T> T readMessageBySchemaWithCheck(
179       Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
180     requireWireType(WIRETYPE_LENGTH_DELIMITED);
181     return readMessage(schema, extensionRegistry);
182   }
183 
184   @SuppressWarnings("unchecked")
185   @Override
readGroup(Class<T> clazz, ExtensionRegistryLite extensionRegistry)186   public <T> T readGroup(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
187       throws IOException {
188     requireWireType(WIRETYPE_START_GROUP);
189     return readGroup(Protobuf.getInstance().schemaFor(clazz), extensionRegistry);
190   }
191 
192   @SuppressWarnings("unchecked")
193   @Override
readGroupBySchemaWithCheck(Schema<T> schema, ExtensionRegistryLite extensionRegistry)194   public <T> T readGroupBySchemaWithCheck(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
195       throws IOException {
196     requireWireType(WIRETYPE_START_GROUP);
197     return readGroup(schema, extensionRegistry);
198   }
199 
200   @Override
mergeMessageField( T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)201   public <T> void mergeMessageField(
202       T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
203     requireWireType(WIRETYPE_LENGTH_DELIMITED);
204     mergeMessageFieldInternal(target, schema, extensionRegistry);
205   }
206 
mergeMessageFieldInternal( T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)207   private <T> void mergeMessageFieldInternal(
208       T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
209     int size = input.readUInt32();
210     if (input.recursionDepth >= input.recursionLimit) {
211       throw InvalidProtocolBufferException.recursionLimitExceeded();
212     }
213 
214     // Push the new limit.
215     final int prevLimit = input.pushLimit(size);
216     ++input.recursionDepth;
217     schema.mergeFrom(target, this, extensionRegistry);
218     input.checkLastTagWas(0);
219     --input.recursionDepth;
220     // Restore the previous limit.
221     input.popLimit(prevLimit);
222   }
223 
224   // Should have the same semantics of CodedInputStream#readMessage()
readMessage(Schema<T> schema, ExtensionRegistryLite extensionRegistry)225   private <T> T readMessage(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
226       throws IOException {
227     T newInstance = schema.newInstance();
228     mergeMessageFieldInternal(newInstance, schema, extensionRegistry);
229     schema.makeImmutable(newInstance);
230     return newInstance;
231   }
232 
233   @Override
mergeGroupField( T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)234   public <T> void mergeGroupField(
235       T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
236     requireWireType(WIRETYPE_START_GROUP);
237     mergeGroupFieldInternal(target, schema, extensionRegistry);
238   }
239 
mergeGroupFieldInternal( T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)240   private <T> void mergeGroupFieldInternal(
241       T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
242     int prevEndGroupTag = endGroupTag;
243     endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP);
244 
245     try {
246       schema.mergeFrom(target, this, extensionRegistry);
247       if (tag != endGroupTag) {
248         throw InvalidProtocolBufferException.parseFailure();
249       }
250     } finally {
251       // Restore the old end group tag.
252       endGroupTag = prevEndGroupTag;
253     }
254   }
255 
readGroup(Schema<T> schema, ExtensionRegistryLite extensionRegistry)256   private <T> T readGroup(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
257       throws IOException {
258     T newInstance = schema.newInstance();
259     mergeGroupFieldInternal(newInstance, schema, extensionRegistry);
260     schema.makeImmutable(newInstance);
261     return newInstance;
262   }
263 
264   @Override
readBytes()265   public ByteString readBytes() throws IOException {
266     requireWireType(WIRETYPE_LENGTH_DELIMITED);
267     return input.readBytes();
268   }
269 
270   @Override
readUInt32()271   public int readUInt32() throws IOException {
272     requireWireType(WIRETYPE_VARINT);
273     return input.readUInt32();
274   }
275 
276   @Override
readEnum()277   public int readEnum() throws IOException {
278     requireWireType(WIRETYPE_VARINT);
279     return input.readEnum();
280   }
281 
282   @Override
readSFixed32()283   public int readSFixed32() throws IOException {
284     requireWireType(WIRETYPE_FIXED32);
285     return input.readSFixed32();
286   }
287 
288   @Override
readSFixed64()289   public long readSFixed64() throws IOException {
290     requireWireType(WIRETYPE_FIXED64);
291     return input.readSFixed64();
292   }
293 
294   @Override
readSInt32()295   public int readSInt32() throws IOException {
296     requireWireType(WIRETYPE_VARINT);
297     return input.readSInt32();
298   }
299 
300   @Override
readSInt64()301   public long readSInt64() throws IOException {
302     requireWireType(WIRETYPE_VARINT);
303     return input.readSInt64();
304   }
305 
306   @Override
readDoubleList(List<Double> target)307   public void readDoubleList(List<Double> target) throws IOException {
308     if (target instanceof DoubleArrayList) {
309       DoubleArrayList plist = (DoubleArrayList) target;
310       switch (WireFormat.getTagWireType(tag)) {
311         case WIRETYPE_LENGTH_DELIMITED:
312           final int bytes = input.readUInt32();
313           verifyPackedFixed64Length(bytes);
314           int endPos = input.getTotalBytesRead() + bytes;
315           do {
316             plist.addDouble(input.readDouble());
317           } while (input.getTotalBytesRead() < endPos);
318           break;
319         case WIRETYPE_FIXED64:
320           while (true) {
321             plist.addDouble(input.readDouble());
322             if (input.isAtEnd()) {
323               return;
324             }
325             int nextTag = input.readTag();
326             if (nextTag != tag) {
327               // We've reached the end of the repeated field. Save the next tag value.
328               this.nextTag = nextTag;
329               return;
330             }
331           }
332         default:
333           throw InvalidProtocolBufferException.invalidWireType();
334       }
335     } else {
336       switch (WireFormat.getTagWireType(tag)) {
337         case WIRETYPE_LENGTH_DELIMITED:
338           final int bytes = input.readUInt32();
339           verifyPackedFixed64Length(bytes);
340           int endPos = input.getTotalBytesRead() + bytes;
341           do {
342             target.add(input.readDouble());
343           } while (input.getTotalBytesRead() < endPos);
344           break;
345         case WIRETYPE_FIXED64:
346           while (true) {
347             target.add(input.readDouble());
348             if (input.isAtEnd()) {
349               return;
350             }
351             int nextTag = input.readTag();
352             if (nextTag != tag) {
353               // We've reached the end of the repeated field. Save the next tag value.
354               this.nextTag = nextTag;
355               return;
356             }
357           }
358         default:
359           throw InvalidProtocolBufferException.invalidWireType();
360       }
361     }
362   }
363 
364   @Override
readFloatList(List<Float> target)365   public void readFloatList(List<Float> target) throws IOException {
366     if (target instanceof FloatArrayList) {
367       FloatArrayList plist = (FloatArrayList) target;
368       switch (WireFormat.getTagWireType(tag)) {
369         case WIRETYPE_LENGTH_DELIMITED:
370           final int bytes = input.readUInt32();
371           verifyPackedFixed32Length(bytes);
372           int endPos = input.getTotalBytesRead() + bytes;
373           do {
374             plist.addFloat(input.readFloat());
375           } while (input.getTotalBytesRead() < endPos);
376           break;
377         case WIRETYPE_FIXED32:
378           while (true) {
379             plist.addFloat(input.readFloat());
380             if (input.isAtEnd()) {
381               return;
382             }
383             int nextTag = input.readTag();
384             if (nextTag != tag) {
385               // We've reached the end of the repeated field. Save the next tag value.
386               this.nextTag = nextTag;
387               return;
388             }
389           }
390         default:
391           throw InvalidProtocolBufferException.invalidWireType();
392       }
393     } else {
394       switch (WireFormat.getTagWireType(tag)) {
395         case WIRETYPE_LENGTH_DELIMITED:
396           final int bytes = input.readUInt32();
397           verifyPackedFixed32Length(bytes);
398           int endPos = input.getTotalBytesRead() + bytes;
399           do {
400             target.add(input.readFloat());
401           } while (input.getTotalBytesRead() < endPos);
402           break;
403         case WIRETYPE_FIXED32:
404           while (true) {
405             target.add(input.readFloat());
406             if (input.isAtEnd()) {
407               return;
408             }
409             int nextTag = input.readTag();
410             if (nextTag != tag) {
411               // We've reached the end of the repeated field. Save the next tag value.
412               this.nextTag = nextTag;
413               return;
414             }
415           }
416         default:
417           throw InvalidProtocolBufferException.invalidWireType();
418       }
419     }
420   }
421 
422   @Override
readUInt64List(List<Long> target)423   public void readUInt64List(List<Long> target) throws IOException {
424     if (target instanceof LongArrayList) {
425       LongArrayList plist = (LongArrayList) target;
426       switch (WireFormat.getTagWireType(tag)) {
427         case WIRETYPE_LENGTH_DELIMITED:
428           final int bytes = input.readUInt32();
429           int endPos = input.getTotalBytesRead() + bytes;
430           do {
431             plist.addLong(input.readUInt64());
432           } while (input.getTotalBytesRead() < endPos);
433           requirePosition(endPos);
434           break;
435         case WIRETYPE_VARINT:
436           while (true) {
437             plist.addLong(input.readUInt64());
438             if (input.isAtEnd()) {
439               return;
440             }
441             int nextTag = input.readTag();
442             if (nextTag != tag) {
443               // We've reached the end of the repeated field. Save the next tag value.
444               this.nextTag = nextTag;
445               return;
446             }
447           }
448         default:
449           throw InvalidProtocolBufferException.invalidWireType();
450       }
451     } else {
452       switch (WireFormat.getTagWireType(tag)) {
453         case WIRETYPE_LENGTH_DELIMITED:
454           final int bytes = input.readUInt32();
455           int endPos = input.getTotalBytesRead() + bytes;
456           do {
457             target.add(input.readUInt64());
458           } while (input.getTotalBytesRead() < endPos);
459           requirePosition(endPos);
460           break;
461         case WIRETYPE_VARINT:
462           while (true) {
463             target.add(input.readUInt64());
464             if (input.isAtEnd()) {
465               return;
466             }
467             int nextTag = input.readTag();
468             if (nextTag != tag) {
469               // We've reached the end of the repeated field. Save the next tag value.
470               this.nextTag = nextTag;
471               return;
472             }
473           }
474         default:
475           throw InvalidProtocolBufferException.invalidWireType();
476       }
477     }
478   }
479 
480   @Override
readInt64List(List<Long> target)481   public void readInt64List(List<Long> target) throws IOException {
482     if (target instanceof LongArrayList) {
483       LongArrayList plist = (LongArrayList) target;
484       switch (WireFormat.getTagWireType(tag)) {
485         case WIRETYPE_LENGTH_DELIMITED:
486           final int bytes = input.readUInt32();
487           int endPos = input.getTotalBytesRead() + bytes;
488           do {
489             plist.addLong(input.readInt64());
490           } while (input.getTotalBytesRead() < endPos);
491           requirePosition(endPos);
492           break;
493         case WIRETYPE_VARINT:
494           while (true) {
495             plist.addLong(input.readInt64());
496             if (input.isAtEnd()) {
497               return;
498             }
499             int nextTag = input.readTag();
500             if (nextTag != tag) {
501               // We've reached the end of the repeated field. Save the next tag value.
502               this.nextTag = nextTag;
503               return;
504             }
505           }
506         default:
507           throw InvalidProtocolBufferException.invalidWireType();
508       }
509     } else {
510       switch (WireFormat.getTagWireType(tag)) {
511         case WIRETYPE_LENGTH_DELIMITED:
512           final int bytes = input.readUInt32();
513           int endPos = input.getTotalBytesRead() + bytes;
514           do {
515             target.add(input.readInt64());
516           } while (input.getTotalBytesRead() < endPos);
517           requirePosition(endPos);
518           break;
519         case WIRETYPE_VARINT:
520           while (true) {
521             target.add(input.readInt64());
522             if (input.isAtEnd()) {
523               return;
524             }
525             int nextTag = input.readTag();
526             if (nextTag != tag) {
527               // We've reached the end of the repeated field. Save the next tag value.
528               this.nextTag = nextTag;
529               return;
530             }
531           }
532         default:
533           throw InvalidProtocolBufferException.invalidWireType();
534       }
535     }
536   }
537 
538   @Override
readInt32List(List<Integer> target)539   public void readInt32List(List<Integer> target) throws IOException {
540     if (target instanceof IntArrayList) {
541       IntArrayList plist = (IntArrayList) target;
542       switch (WireFormat.getTagWireType(tag)) {
543         case WIRETYPE_LENGTH_DELIMITED:
544           final int bytes = input.readUInt32();
545           int endPos = input.getTotalBytesRead() + bytes;
546           do {
547             plist.addInt(input.readInt32());
548           } while (input.getTotalBytesRead() < endPos);
549           requirePosition(endPos);
550           break;
551         case WIRETYPE_VARINT:
552           while (true) {
553             plist.addInt(input.readInt32());
554             if (input.isAtEnd()) {
555               return;
556             }
557             int nextTag = input.readTag();
558             if (nextTag != tag) {
559               // We've reached the end of the repeated field. Save the next tag value.
560               this.nextTag = nextTag;
561               return;
562             }
563           }
564         default:
565           throw InvalidProtocolBufferException.invalidWireType();
566       }
567     } else {
568       switch (WireFormat.getTagWireType(tag)) {
569         case WIRETYPE_LENGTH_DELIMITED:
570           final int bytes = input.readUInt32();
571           int endPos = input.getTotalBytesRead() + bytes;
572           do {
573             target.add(input.readInt32());
574           } while (input.getTotalBytesRead() < endPos);
575           requirePosition(endPos);
576           break;
577         case WIRETYPE_VARINT:
578           while (true) {
579             target.add(input.readInt32());
580             if (input.isAtEnd()) {
581               return;
582             }
583             int nextTag = input.readTag();
584             if (nextTag != tag) {
585               // We've reached the end of the repeated field. Save the next tag value.
586               this.nextTag = nextTag;
587               return;
588             }
589           }
590         default:
591           throw InvalidProtocolBufferException.invalidWireType();
592       }
593     }
594   }
595 
596   @Override
readFixed64List(List<Long> target)597   public void readFixed64List(List<Long> target) throws IOException {
598     if (target instanceof LongArrayList) {
599       LongArrayList plist = (LongArrayList) target;
600       switch (WireFormat.getTagWireType(tag)) {
601         case WIRETYPE_LENGTH_DELIMITED:
602           final int bytes = input.readUInt32();
603           verifyPackedFixed64Length(bytes);
604           int endPos = input.getTotalBytesRead() + bytes;
605           do {
606             plist.addLong(input.readFixed64());
607           } while (input.getTotalBytesRead() < endPos);
608           break;
609         case WIRETYPE_FIXED64:
610           while (true) {
611             plist.addLong(input.readFixed64());
612             if (input.isAtEnd()) {
613               return;
614             }
615             int nextTag = input.readTag();
616             if (nextTag != tag) {
617               // We've reached the end of the repeated field. Save the next tag value.
618               this.nextTag = nextTag;
619               return;
620             }
621           }
622         default:
623           throw InvalidProtocolBufferException.invalidWireType();
624       }
625     } else {
626       switch (WireFormat.getTagWireType(tag)) {
627         case WIRETYPE_LENGTH_DELIMITED:
628           final int bytes = input.readUInt32();
629           verifyPackedFixed64Length(bytes);
630           int endPos = input.getTotalBytesRead() + bytes;
631           do {
632             target.add(input.readFixed64());
633           } while (input.getTotalBytesRead() < endPos);
634           break;
635         case WIRETYPE_FIXED64:
636           while (true) {
637             target.add(input.readFixed64());
638             if (input.isAtEnd()) {
639               return;
640             }
641             int nextTag = input.readTag();
642             if (nextTag != tag) {
643               // We've reached the end of the repeated field. Save the next tag value.
644               this.nextTag = nextTag;
645               return;
646             }
647           }
648         default:
649           throw InvalidProtocolBufferException.invalidWireType();
650       }
651     }
652   }
653 
654   @Override
readFixed32List(List<Integer> target)655   public void readFixed32List(List<Integer> target) throws IOException {
656     if (target instanceof IntArrayList) {
657       IntArrayList plist = (IntArrayList) target;
658       switch (WireFormat.getTagWireType(tag)) {
659         case WIRETYPE_LENGTH_DELIMITED:
660           final int bytes = input.readUInt32();
661           verifyPackedFixed32Length(bytes);
662           int endPos = input.getTotalBytesRead() + bytes;
663           do {
664             plist.addInt(input.readFixed32());
665           } while (input.getTotalBytesRead() < endPos);
666           break;
667         case WIRETYPE_FIXED32:
668           while (true) {
669             plist.addInt(input.readFixed32());
670             if (input.isAtEnd()) {
671               return;
672             }
673             int nextTag = input.readTag();
674             if (nextTag != tag) {
675               // We've reached the end of the repeated field. Save the next tag value.
676               this.nextTag = nextTag;
677               return;
678             }
679           }
680         default:
681           throw InvalidProtocolBufferException.invalidWireType();
682       }
683     } else {
684       switch (WireFormat.getTagWireType(tag)) {
685         case WIRETYPE_LENGTH_DELIMITED:
686           final int bytes = input.readUInt32();
687           verifyPackedFixed32Length(bytes);
688           int endPos = input.getTotalBytesRead() + bytes;
689           do {
690             target.add(input.readFixed32());
691           } while (input.getTotalBytesRead() < endPos);
692           break;
693         case WIRETYPE_FIXED32:
694           while (true) {
695             target.add(input.readFixed32());
696             if (input.isAtEnd()) {
697               return;
698             }
699             int nextTag = input.readTag();
700             if (nextTag != tag) {
701               // We've reached the end of the repeated field. Save the next tag value.
702               this.nextTag = nextTag;
703               return;
704             }
705           }
706         default:
707           throw InvalidProtocolBufferException.invalidWireType();
708       }
709     }
710   }
711 
712   @Override
readBoolList(List<Boolean> target)713   public void readBoolList(List<Boolean> target) throws IOException {
714     if (target instanceof BooleanArrayList) {
715       BooleanArrayList plist = (BooleanArrayList) target;
716       switch (WireFormat.getTagWireType(tag)) {
717         case WIRETYPE_LENGTH_DELIMITED:
718           final int bytes = input.readUInt32();
719           int endPos = input.getTotalBytesRead() + bytes;
720           do {
721             plist.addBoolean(input.readBool());
722           } while (input.getTotalBytesRead() < endPos);
723           requirePosition(endPos);
724           break;
725         case WIRETYPE_VARINT:
726           while (true) {
727             plist.addBoolean(input.readBool());
728             if (input.isAtEnd()) {
729               return;
730             }
731             int nextTag = input.readTag();
732             if (nextTag != tag) {
733               // We've reached the end of the repeated field. Save the next tag value.
734               this.nextTag = nextTag;
735               return;
736             }
737           }
738         default:
739           throw InvalidProtocolBufferException.invalidWireType();
740       }
741     } else {
742       switch (WireFormat.getTagWireType(tag)) {
743         case WIRETYPE_LENGTH_DELIMITED:
744           final int bytes = input.readUInt32();
745           int endPos = input.getTotalBytesRead() + bytes;
746           do {
747             target.add(input.readBool());
748           } while (input.getTotalBytesRead() < endPos);
749           requirePosition(endPos);
750           break;
751         case WIRETYPE_VARINT:
752           while (true) {
753             target.add(input.readBool());
754             if (input.isAtEnd()) {
755               return;
756             }
757             int nextTag = input.readTag();
758             if (nextTag != tag) {
759               // We've reached the end of the repeated field. Save the next tag value.
760               this.nextTag = nextTag;
761               return;
762             }
763           }
764         default:
765           throw InvalidProtocolBufferException.invalidWireType();
766       }
767     }
768   }
769 
770   @Override
readStringList(List<String> target)771   public void readStringList(List<String> target) throws IOException {
772     readStringListInternal(target, false);
773   }
774 
775   @Override
readStringListRequireUtf8(List<String> target)776   public void readStringListRequireUtf8(List<String> target) throws IOException {
777     readStringListInternal(target, true);
778   }
779 
readStringListInternal(List<String> target, boolean requireUtf8)780   public void readStringListInternal(List<String> target, boolean requireUtf8) throws IOException {
781     if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
782       throw InvalidProtocolBufferException.invalidWireType();
783     }
784 
785     if (target instanceof LazyStringList && !requireUtf8) {
786       LazyStringList lazyList = (LazyStringList) target;
787       while (true) {
788         lazyList.add(readBytes());
789         if (input.isAtEnd()) {
790           return;
791         }
792         int nextTag = input.readTag();
793         if (nextTag != tag) {
794           // We've reached the end of the repeated field. Save the next tag value.
795           this.nextTag = nextTag;
796           return;
797         }
798       }
799     } else {
800       while (true) {
801         target.add(requireUtf8 ? readStringRequireUtf8() : readString());
802         if (input.isAtEnd()) {
803           return;
804         }
805         int nextTag = input.readTag();
806         if (nextTag != tag) {
807           // We've reached the end of the repeated field. Save the next tag value.
808           this.nextTag = nextTag;
809           return;
810         }
811       }
812     }
813   }
814 
815   @Override
readMessageList( List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)816   public <T> void readMessageList(
817       List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
818       throws IOException {
819     final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
820     readMessageList(target, schema, extensionRegistry);
821   }
822 
823   @Override
readMessageList( List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)824   public <T> void readMessageList(
825       List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
826       throws IOException {
827     if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
828       throw InvalidProtocolBufferException.invalidWireType();
829     }
830     final int listTag = tag;
831     while (true) {
832       target.add(readMessage(schema, extensionRegistry));
833       if (input.isAtEnd() || nextTag != NEXT_TAG_UNSET) {
834         return;
835       }
836       int nextTag = input.readTag();
837       if (nextTag != listTag) {
838         // We've reached the end of the repeated field. Save the next tag value.
839         this.nextTag = nextTag;
840         return;
841       }
842     }
843   }
844 
845   @Override
readGroupList( List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)846   public <T> void readGroupList(
847       List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
848       throws IOException {
849     final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
850     readGroupList(target, schema, extensionRegistry);
851   }
852 
853   @Override
readGroupList( List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)854   public <T> void readGroupList(
855       List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
856       throws IOException {
857     if (WireFormat.getTagWireType(tag) != WIRETYPE_START_GROUP) {
858       throw InvalidProtocolBufferException.invalidWireType();
859     }
860     final int listTag = tag;
861     while (true) {
862       target.add(readGroup(schema, extensionRegistry));
863       if (input.isAtEnd() || nextTag != NEXT_TAG_UNSET) {
864         return;
865       }
866       int nextTag = input.readTag();
867       if (nextTag != listTag) {
868         // We've reached the end of the repeated field. Save the next tag value.
869         this.nextTag = nextTag;
870         return;
871       }
872     }
873   }
874 
875   @Override
readBytesList(List<ByteString> target)876   public void readBytesList(List<ByteString> target) throws IOException {
877     if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
878       throw InvalidProtocolBufferException.invalidWireType();
879     }
880 
881     while (true) {
882       target.add(readBytes());
883       if (input.isAtEnd()) {
884         return;
885       }
886       int nextTag = input.readTag();
887       if (nextTag != tag) {
888         // We've reached the end of the repeated field. Save the next tag value.
889         this.nextTag = nextTag;
890         return;
891       }
892     }
893   }
894 
895   @Override
readUInt32List(List<Integer> target)896   public void readUInt32List(List<Integer> target) throws IOException {
897     if (target instanceof IntArrayList) {
898       IntArrayList plist = (IntArrayList) target;
899       switch (WireFormat.getTagWireType(tag)) {
900         case WIRETYPE_LENGTH_DELIMITED:
901           final int bytes = input.readUInt32();
902           int endPos = input.getTotalBytesRead() + bytes;
903           do {
904             plist.addInt(input.readUInt32());
905           } while (input.getTotalBytesRead() < endPos);
906           requirePosition(endPos);
907           break;
908         case WIRETYPE_VARINT:
909           while (true) {
910             plist.addInt(input.readUInt32());
911             if (input.isAtEnd()) {
912               return;
913             }
914             int nextTag = input.readTag();
915             if (nextTag != tag) {
916               // We've reached the end of the repeated field. Save the next tag value.
917               this.nextTag = nextTag;
918               return;
919             }
920           }
921         default:
922           throw InvalidProtocolBufferException.invalidWireType();
923       }
924     } else {
925       switch (WireFormat.getTagWireType(tag)) {
926         case WIRETYPE_LENGTH_DELIMITED:
927           final int bytes = input.readUInt32();
928           int endPos = input.getTotalBytesRead() + bytes;
929           do {
930             target.add(input.readUInt32());
931           } while (input.getTotalBytesRead() < endPos);
932           requirePosition(endPos);
933           break;
934         case WIRETYPE_VARINT:
935           while (true) {
936             target.add(input.readUInt32());
937             if (input.isAtEnd()) {
938               return;
939             }
940             int nextTag = input.readTag();
941             if (nextTag != tag) {
942               // We've reached the end of the repeated field. Save the next tag value.
943               this.nextTag = nextTag;
944               return;
945             }
946           }
947         default:
948           throw InvalidProtocolBufferException.invalidWireType();
949       }
950     }
951   }
952 
953   @Override
readEnumList(List<Integer> target)954   public void readEnumList(List<Integer> target) throws IOException {
955     if (target instanceof IntArrayList) {
956       IntArrayList plist = (IntArrayList) target;
957       switch (WireFormat.getTagWireType(tag)) {
958         case WIRETYPE_LENGTH_DELIMITED:
959           final int bytes = input.readUInt32();
960           int endPos = input.getTotalBytesRead() + bytes;
961           do {
962             plist.addInt(input.readEnum());
963           } while (input.getTotalBytesRead() < endPos);
964           requirePosition(endPos);
965           break;
966         case WIRETYPE_VARINT:
967           while (true) {
968             plist.addInt(input.readEnum());
969             if (input.isAtEnd()) {
970               return;
971             }
972             int nextTag = input.readTag();
973             if (nextTag != tag) {
974               // We've reached the end of the repeated field. Save the next tag value.
975               this.nextTag = nextTag;
976               return;
977             }
978           }
979         default:
980           throw InvalidProtocolBufferException.invalidWireType();
981       }
982     } else {
983       switch (WireFormat.getTagWireType(tag)) {
984         case WIRETYPE_LENGTH_DELIMITED:
985           final int bytes = input.readUInt32();
986           int endPos = input.getTotalBytesRead() + bytes;
987           do {
988             target.add(input.readEnum());
989           } while (input.getTotalBytesRead() < endPos);
990           requirePosition(endPos);
991           break;
992         case WIRETYPE_VARINT:
993           while (true) {
994             target.add(input.readEnum());
995             if (input.isAtEnd()) {
996               return;
997             }
998             int nextTag = input.readTag();
999             if (nextTag != tag) {
1000               // We've reached the end of the repeated field. Save the next tag value.
1001               this.nextTag = nextTag;
1002               return;
1003             }
1004           }
1005         default:
1006           throw InvalidProtocolBufferException.invalidWireType();
1007       }
1008     }
1009   }
1010 
1011   @Override
readSFixed32List(List<Integer> target)1012   public void readSFixed32List(List<Integer> target) throws IOException {
1013     if (target instanceof IntArrayList) {
1014       IntArrayList plist = (IntArrayList) target;
1015       switch (WireFormat.getTagWireType(tag)) {
1016         case WIRETYPE_LENGTH_DELIMITED:
1017           final int bytes = input.readUInt32();
1018           verifyPackedFixed32Length(bytes);
1019           int endPos = input.getTotalBytesRead() + bytes;
1020           do {
1021             plist.addInt(input.readSFixed32());
1022           } while (input.getTotalBytesRead() < endPos);
1023           break;
1024         case WIRETYPE_FIXED32:
1025           while (true) {
1026             plist.addInt(input.readSFixed32());
1027             if (input.isAtEnd()) {
1028               return;
1029             }
1030             int nextTag = input.readTag();
1031             if (nextTag != tag) {
1032               // We've reached the end of the repeated field. Save the next tag value.
1033               this.nextTag = nextTag;
1034               return;
1035             }
1036           }
1037         default:
1038           throw InvalidProtocolBufferException.invalidWireType();
1039       }
1040     } else {
1041       switch (WireFormat.getTagWireType(tag)) {
1042         case WIRETYPE_LENGTH_DELIMITED:
1043           final int bytes = input.readUInt32();
1044           verifyPackedFixed32Length(bytes);
1045           int endPos = input.getTotalBytesRead() + bytes;
1046           do {
1047             target.add(input.readSFixed32());
1048           } while (input.getTotalBytesRead() < endPos);
1049           break;
1050         case WIRETYPE_FIXED32:
1051           while (true) {
1052             target.add(input.readSFixed32());
1053             if (input.isAtEnd()) {
1054               return;
1055             }
1056             int nextTag = input.readTag();
1057             if (nextTag != tag) {
1058               // We've reached the end of the repeated field. Save the next tag value.
1059               this.nextTag = nextTag;
1060               return;
1061             }
1062           }
1063         default:
1064           throw InvalidProtocolBufferException.invalidWireType();
1065       }
1066     }
1067   }
1068 
1069   @Override
readSFixed64List(List<Long> target)1070   public void readSFixed64List(List<Long> target) throws IOException {
1071     if (target instanceof LongArrayList) {
1072       LongArrayList plist = (LongArrayList) target;
1073       switch (WireFormat.getTagWireType(tag)) {
1074         case WIRETYPE_LENGTH_DELIMITED:
1075           final int bytes = input.readUInt32();
1076           verifyPackedFixed64Length(bytes);
1077           int endPos = input.getTotalBytesRead() + bytes;
1078           do {
1079             plist.addLong(input.readSFixed64());
1080           } while (input.getTotalBytesRead() < endPos);
1081           break;
1082         case WIRETYPE_FIXED64:
1083           while (true) {
1084             plist.addLong(input.readSFixed64());
1085             if (input.isAtEnd()) {
1086               return;
1087             }
1088             int nextTag = input.readTag();
1089             if (nextTag != tag) {
1090               // We've reached the end of the repeated field. Save the next tag value.
1091               this.nextTag = nextTag;
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 = input.readUInt32();
1102           verifyPackedFixed64Length(bytes);
1103           int endPos = input.getTotalBytesRead() + bytes;
1104           do {
1105             target.add(input.readSFixed64());
1106           } while (input.getTotalBytesRead() < endPos);
1107           break;
1108         case WIRETYPE_FIXED64:
1109           while (true) {
1110             target.add(input.readSFixed64());
1111             if (input.isAtEnd()) {
1112               return;
1113             }
1114             int nextTag = input.readTag();
1115             if (nextTag != tag) {
1116               // We've reached the end of the repeated field. Save the next tag value.
1117               this.nextTag = nextTag;
1118               return;
1119             }
1120           }
1121         default:
1122           throw InvalidProtocolBufferException.invalidWireType();
1123       }
1124     }
1125   }
1126 
1127   @Override
readSInt32List(List<Integer> target)1128   public void readSInt32List(List<Integer> target) throws IOException {
1129     if (target instanceof IntArrayList) {
1130       IntArrayList plist = (IntArrayList) target;
1131       switch (WireFormat.getTagWireType(tag)) {
1132         case WIRETYPE_LENGTH_DELIMITED:
1133           final int bytes = input.readUInt32();
1134           int endPos = input.getTotalBytesRead() + bytes;
1135           do {
1136             plist.addInt(input.readSInt32());
1137           } while (input.getTotalBytesRead() < endPos);
1138           requirePosition(endPos);
1139           break;
1140         case WIRETYPE_VARINT:
1141           while (true) {
1142             plist.addInt(input.readSInt32());
1143             if (input.isAtEnd()) {
1144               return;
1145             }
1146             int nextTag = input.readTag();
1147             if (nextTag != tag) {
1148               // We've reached the end of the repeated field. Save the next tag value.
1149               this.nextTag = nextTag;
1150               return;
1151             }
1152           }
1153         default:
1154           throw InvalidProtocolBufferException.invalidWireType();
1155       }
1156     } else {
1157       switch (WireFormat.getTagWireType(tag)) {
1158         case WIRETYPE_LENGTH_DELIMITED:
1159           final int bytes = input.readUInt32();
1160           int endPos = input.getTotalBytesRead() + bytes;
1161           do {
1162             target.add(input.readSInt32());
1163           } while (input.getTotalBytesRead() < endPos);
1164           requirePosition(endPos);
1165           break;
1166         case WIRETYPE_VARINT:
1167           while (true) {
1168             target.add(input.readSInt32());
1169             if (input.isAtEnd()) {
1170               return;
1171             }
1172             int nextTag = input.readTag();
1173             if (nextTag != tag) {
1174               // We've reached the end of the repeated field. Save the next tag value.
1175               this.nextTag = nextTag;
1176               return;
1177             }
1178           }
1179         default:
1180           throw InvalidProtocolBufferException.invalidWireType();
1181       }
1182     }
1183   }
1184 
1185   @Override
readSInt64List(List<Long> target)1186   public void readSInt64List(List<Long> target) throws IOException {
1187     if (target instanceof LongArrayList) {
1188       LongArrayList plist = (LongArrayList) target;
1189       switch (WireFormat.getTagWireType(tag)) {
1190         case WIRETYPE_LENGTH_DELIMITED:
1191           final int bytes = input.readUInt32();
1192           int endPos = input.getTotalBytesRead() + bytes;
1193           do {
1194             plist.addLong(input.readSInt64());
1195           } while (input.getTotalBytesRead() < endPos);
1196           requirePosition(endPos);
1197           break;
1198         case WIRETYPE_VARINT:
1199           while (true) {
1200             plist.addLong(input.readSInt64());
1201             if (input.isAtEnd()) {
1202               return;
1203             }
1204             int nextTag = input.readTag();
1205             if (nextTag != tag) {
1206               // We've reached the end of the repeated field. Save the next tag value.
1207               this.nextTag = nextTag;
1208               return;
1209             }
1210           }
1211         default:
1212           throw InvalidProtocolBufferException.invalidWireType();
1213       }
1214     } else {
1215       switch (WireFormat.getTagWireType(tag)) {
1216         case WIRETYPE_LENGTH_DELIMITED:
1217           final int bytes = input.readUInt32();
1218           int endPos = input.getTotalBytesRead() + bytes;
1219           do {
1220             target.add(input.readSInt64());
1221           } while (input.getTotalBytesRead() < endPos);
1222           requirePosition(endPos);
1223           break;
1224         case WIRETYPE_VARINT:
1225           while (true) {
1226             target.add(input.readSInt64());
1227             if (input.isAtEnd()) {
1228               return;
1229             }
1230             int nextTag = input.readTag();
1231             if (nextTag != tag) {
1232               // We've reached the end of the repeated field. Save the next tag value.
1233               this.nextTag = nextTag;
1234               return;
1235             }
1236           }
1237         default:
1238           throw InvalidProtocolBufferException.invalidWireType();
1239       }
1240     }
1241   }
1242 
verifyPackedFixed64Length(int bytes)1243   private void verifyPackedFixed64Length(int bytes) throws IOException {
1244     if ((bytes & FIXED64_MULTIPLE_MASK) != 0) {
1245       // Require that the number of bytes be a multiple of 8.
1246       throw InvalidProtocolBufferException.parseFailure();
1247     }
1248   }
1249 
1250   @SuppressWarnings("unchecked")
1251   @Override
readMap( Map<K, V> target, MapEntryLite.Metadata<K, V> metadata, ExtensionRegistryLite extensionRegistry)1252   public <K, V> void readMap(
1253       Map<K, V> target,
1254       MapEntryLite.Metadata<K, V> metadata,
1255       ExtensionRegistryLite extensionRegistry)
1256       throws IOException {
1257     requireWireType(WIRETYPE_LENGTH_DELIMITED);
1258     int size = input.readUInt32();
1259     final int prevLimit = input.pushLimit(size);
1260     K key = metadata.defaultKey;
1261     V value = metadata.defaultValue;
1262     try {
1263       while (true) {
1264         int number = getFieldNumber();
1265         if (number == READ_DONE || input.isAtEnd()) {
1266           break;
1267         }
1268         try {
1269           switch (number) {
1270             case 1:
1271               key = (K) readField(metadata.keyType, null, null);
1272               break;
1273             case 2:
1274               value =
1275                   (V)
1276                       readField(
1277                           metadata.valueType, metadata.defaultValue.getClass(), extensionRegistry);
1278               break;
1279             default:
1280               if (!skipField()) {
1281                 throw new InvalidProtocolBufferException("Unable to parse map entry.");
1282               }
1283               break;
1284           }
1285         } catch (InvalidProtocolBufferException.InvalidWireTypeException ignore) {
1286           // the type doesn't match, skip the field.
1287           if (!skipField()) {
1288             throw new InvalidProtocolBufferException("Unable to parse map entry.");
1289           }
1290         }
1291       }
1292       target.put(key, value);
1293     } finally {
1294       // Restore the previous limit.
1295       input.popLimit(prevLimit);
1296     }
1297   }
1298 
readField( WireFormat.FieldType fieldType, Class<?> messageType, ExtensionRegistryLite extensionRegistry)1299   private Object readField(
1300       WireFormat.FieldType fieldType, Class<?> messageType, ExtensionRegistryLite extensionRegistry)
1301       throws IOException {
1302     switch (fieldType) {
1303       case BOOL:
1304         return readBool();
1305       case BYTES:
1306         return readBytes();
1307       case DOUBLE:
1308         return readDouble();
1309       case ENUM:
1310         return readEnum();
1311       case FIXED32:
1312         return readFixed32();
1313       case FIXED64:
1314         return readFixed64();
1315       case FLOAT:
1316         return readFloat();
1317       case INT32:
1318         return readInt32();
1319       case INT64:
1320         return readInt64();
1321       case MESSAGE:
1322         return readMessage(messageType, extensionRegistry);
1323       case SFIXED32:
1324         return readSFixed32();
1325       case SFIXED64:
1326         return readSFixed64();
1327       case SINT32:
1328         return readSInt32();
1329       case SINT64:
1330         return readSInt64();
1331       case STRING:
1332         return readStringRequireUtf8();
1333       case UINT32:
1334         return readUInt32();
1335       case UINT64:
1336         return readUInt64();
1337       default:
1338         throw new RuntimeException("unsupported field type.");
1339     }
1340   }
1341 
verifyPackedFixed32Length(int bytes)1342   private void verifyPackedFixed32Length(int bytes) throws IOException {
1343     if ((bytes & FIXED32_MULTIPLE_MASK) != 0) {
1344       // Require that the number of bytes be a multiple of 4.
1345       throw InvalidProtocolBufferException.parseFailure();
1346     }
1347   }
1348 
requirePosition(int expectedPosition)1349   private void requirePosition(int expectedPosition) throws IOException {
1350     if (input.getTotalBytesRead() != expectedPosition) {
1351       throw InvalidProtocolBufferException.truncatedMessage();
1352     }
1353   }
1354 }
1355