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