• 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   // Should have the same semantics of CodedInputStream#readMessage()
readMessage(Schema<T> schema, ExtensionRegistryLite extensionRegistry)201   private <T> T readMessage(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
202       throws IOException {
203     int size = input.readUInt32();
204     if (input.recursionDepth >= input.recursionLimit) {
205       throw InvalidProtocolBufferException.recursionLimitExceeded();
206     }
207 
208     // Push the new limit.
209     final int prevLimit = input.pushLimit(size);
210     // Allocate and read the message.
211     T message = schema.newInstance();
212     ++input.recursionDepth;
213     schema.mergeFrom(message, this, extensionRegistry);
214     schema.makeImmutable(message);
215     input.checkLastTagWas(0);
216     --input.recursionDepth;
217     // Restore the previous limit.
218     input.popLimit(prevLimit);
219     return message;
220   }
221 
readGroup(Schema<T> schema, ExtensionRegistryLite extensionRegistry)222   private <T> T readGroup(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
223       throws IOException {
224     int prevEndGroupTag = endGroupTag;
225     endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP);
226 
227     try {
228       // Allocate and read the message.
229       T message = schema.newInstance();
230       schema.mergeFrom(message, this, extensionRegistry);
231       schema.makeImmutable(message);
232 
233       if (tag != endGroupTag) {
234         throw InvalidProtocolBufferException.parseFailure();
235       }
236       return message;
237     } finally {
238       // Restore the old end group tag.
239       endGroupTag = prevEndGroupTag;
240     }
241   }
242 
243   @Override
readBytes()244   public ByteString readBytes() throws IOException {
245     requireWireType(WIRETYPE_LENGTH_DELIMITED);
246     return input.readBytes();
247   }
248 
249   @Override
readUInt32()250   public int readUInt32() throws IOException {
251     requireWireType(WIRETYPE_VARINT);
252     return input.readUInt32();
253   }
254 
255   @Override
readEnum()256   public int readEnum() throws IOException {
257     requireWireType(WIRETYPE_VARINT);
258     return input.readEnum();
259   }
260 
261   @Override
readSFixed32()262   public int readSFixed32() throws IOException {
263     requireWireType(WIRETYPE_FIXED32);
264     return input.readSFixed32();
265   }
266 
267   @Override
readSFixed64()268   public long readSFixed64() throws IOException {
269     requireWireType(WIRETYPE_FIXED64);
270     return input.readSFixed64();
271   }
272 
273   @Override
readSInt32()274   public int readSInt32() throws IOException {
275     requireWireType(WIRETYPE_VARINT);
276     return input.readSInt32();
277   }
278 
279   @Override
readSInt64()280   public long readSInt64() throws IOException {
281     requireWireType(WIRETYPE_VARINT);
282     return input.readSInt64();
283   }
284 
285   @Override
readDoubleList(List<Double> target)286   public void readDoubleList(List<Double> target) throws IOException {
287     if (target instanceof DoubleArrayList) {
288       DoubleArrayList plist = (DoubleArrayList) target;
289       switch (WireFormat.getTagWireType(tag)) {
290         case WIRETYPE_LENGTH_DELIMITED:
291           final int bytes = input.readUInt32();
292           verifyPackedFixed64Length(bytes);
293           int endPos = input.getTotalBytesRead() + bytes;
294           do {
295             plist.addDouble(input.readDouble());
296           } while (input.getTotalBytesRead() < endPos);
297           break;
298         case WIRETYPE_FIXED64:
299           while (true) {
300             plist.addDouble(input.readDouble());
301             if (input.isAtEnd()) {
302               return;
303             }
304             int nextTag = input.readTag();
305             if (nextTag != tag) {
306               // We've reached the end of the repeated field. Save the next tag value.
307               this.nextTag = nextTag;
308               return;
309             }
310           }
311         default:
312           throw InvalidProtocolBufferException.invalidWireType();
313       }
314     } else {
315       switch (WireFormat.getTagWireType(tag)) {
316         case WIRETYPE_LENGTH_DELIMITED:
317           final int bytes = input.readUInt32();
318           verifyPackedFixed64Length(bytes);
319           int endPos = input.getTotalBytesRead() + bytes;
320           do {
321             target.add(input.readDouble());
322           } while (input.getTotalBytesRead() < endPos);
323           break;
324         case WIRETYPE_FIXED64:
325           while (true) {
326             target.add(input.readDouble());
327             if (input.isAtEnd()) {
328               return;
329             }
330             int nextTag = input.readTag();
331             if (nextTag != tag) {
332               // We've reached the end of the repeated field. Save the next tag value.
333               this.nextTag = nextTag;
334               return;
335             }
336           }
337         default:
338           throw InvalidProtocolBufferException.invalidWireType();
339       }
340     }
341   }
342 
343   @Override
readFloatList(List<Float> target)344   public void readFloatList(List<Float> target) throws IOException {
345     if (target instanceof FloatArrayList) {
346       FloatArrayList plist = (FloatArrayList) target;
347       switch (WireFormat.getTagWireType(tag)) {
348         case WIRETYPE_LENGTH_DELIMITED:
349           final int bytes = input.readUInt32();
350           verifyPackedFixed32Length(bytes);
351           int endPos = input.getTotalBytesRead() + bytes;
352           do {
353             plist.addFloat(input.readFloat());
354           } while (input.getTotalBytesRead() < endPos);
355           break;
356         case WIRETYPE_FIXED32:
357           while (true) {
358             plist.addFloat(input.readFloat());
359             if (input.isAtEnd()) {
360               return;
361             }
362             int nextTag = input.readTag();
363             if (nextTag != tag) {
364               // We've reached the end of the repeated field. Save the next tag value.
365               this.nextTag = nextTag;
366               return;
367             }
368           }
369         default:
370           throw InvalidProtocolBufferException.invalidWireType();
371       }
372     } else {
373       switch (WireFormat.getTagWireType(tag)) {
374         case WIRETYPE_LENGTH_DELIMITED:
375           final int bytes = input.readUInt32();
376           verifyPackedFixed32Length(bytes);
377           int endPos = input.getTotalBytesRead() + bytes;
378           do {
379             target.add(input.readFloat());
380           } while (input.getTotalBytesRead() < endPos);
381           break;
382         case WIRETYPE_FIXED32:
383           while (true) {
384             target.add(input.readFloat());
385             if (input.isAtEnd()) {
386               return;
387             }
388             int nextTag = input.readTag();
389             if (nextTag != tag) {
390               // We've reached the end of the repeated field. Save the next tag value.
391               this.nextTag = nextTag;
392               return;
393             }
394           }
395         default:
396           throw InvalidProtocolBufferException.invalidWireType();
397       }
398     }
399   }
400 
401   @Override
readUInt64List(List<Long> target)402   public void readUInt64List(List<Long> target) throws IOException {
403     if (target instanceof LongArrayList) {
404       LongArrayList plist = (LongArrayList) target;
405       switch (WireFormat.getTagWireType(tag)) {
406         case WIRETYPE_LENGTH_DELIMITED:
407           final int bytes = input.readUInt32();
408           int endPos = input.getTotalBytesRead() + bytes;
409           do {
410             plist.addLong(input.readUInt64());
411           } while (input.getTotalBytesRead() < endPos);
412           requirePosition(endPos);
413           break;
414         case WIRETYPE_VARINT:
415           while (true) {
416             plist.addLong(input.readUInt64());
417             if (input.isAtEnd()) {
418               return;
419             }
420             int nextTag = input.readTag();
421             if (nextTag != tag) {
422               // We've reached the end of the repeated field. Save the next tag value.
423               this.nextTag = nextTag;
424               return;
425             }
426           }
427         default:
428           throw InvalidProtocolBufferException.invalidWireType();
429       }
430     } else {
431       switch (WireFormat.getTagWireType(tag)) {
432         case WIRETYPE_LENGTH_DELIMITED:
433           final int bytes = input.readUInt32();
434           int endPos = input.getTotalBytesRead() + bytes;
435           do {
436             target.add(input.readUInt64());
437           } while (input.getTotalBytesRead() < endPos);
438           requirePosition(endPos);
439           break;
440         case WIRETYPE_VARINT:
441           while (true) {
442             target.add(input.readUInt64());
443             if (input.isAtEnd()) {
444               return;
445             }
446             int nextTag = input.readTag();
447             if (nextTag != tag) {
448               // We've reached the end of the repeated field. Save the next tag value.
449               this.nextTag = nextTag;
450               return;
451             }
452           }
453         default:
454           throw InvalidProtocolBufferException.invalidWireType();
455       }
456     }
457   }
458 
459   @Override
readInt64List(List<Long> target)460   public void readInt64List(List<Long> target) throws IOException {
461     if (target instanceof LongArrayList) {
462       LongArrayList plist = (LongArrayList) target;
463       switch (WireFormat.getTagWireType(tag)) {
464         case WIRETYPE_LENGTH_DELIMITED:
465           final int bytes = input.readUInt32();
466           int endPos = input.getTotalBytesRead() + bytes;
467           do {
468             plist.addLong(input.readInt64());
469           } while (input.getTotalBytesRead() < endPos);
470           requirePosition(endPos);
471           break;
472         case WIRETYPE_VARINT:
473           while (true) {
474             plist.addLong(input.readInt64());
475             if (input.isAtEnd()) {
476               return;
477             }
478             int nextTag = input.readTag();
479             if (nextTag != tag) {
480               // We've reached the end of the repeated field. Save the next tag value.
481               this.nextTag = nextTag;
482               return;
483             }
484           }
485         default:
486           throw InvalidProtocolBufferException.invalidWireType();
487       }
488     } else {
489       switch (WireFormat.getTagWireType(tag)) {
490         case WIRETYPE_LENGTH_DELIMITED:
491           final int bytes = input.readUInt32();
492           int endPos = input.getTotalBytesRead() + bytes;
493           do {
494             target.add(input.readInt64());
495           } while (input.getTotalBytesRead() < endPos);
496           requirePosition(endPos);
497           break;
498         case WIRETYPE_VARINT:
499           while (true) {
500             target.add(input.readInt64());
501             if (input.isAtEnd()) {
502               return;
503             }
504             int nextTag = input.readTag();
505             if (nextTag != tag) {
506               // We've reached the end of the repeated field. Save the next tag value.
507               this.nextTag = nextTag;
508               return;
509             }
510           }
511         default:
512           throw InvalidProtocolBufferException.invalidWireType();
513       }
514     }
515   }
516 
517   @Override
readInt32List(List<Integer> target)518   public void readInt32List(List<Integer> target) throws IOException {
519     if (target instanceof IntArrayList) {
520       IntArrayList plist = (IntArrayList) target;
521       switch (WireFormat.getTagWireType(tag)) {
522         case WIRETYPE_LENGTH_DELIMITED:
523           final int bytes = input.readUInt32();
524           int endPos = input.getTotalBytesRead() + bytes;
525           do {
526             plist.addInt(input.readInt32());
527           } while (input.getTotalBytesRead() < endPos);
528           requirePosition(endPos);
529           break;
530         case WIRETYPE_VARINT:
531           while (true) {
532             plist.addInt(input.readInt32());
533             if (input.isAtEnd()) {
534               return;
535             }
536             int nextTag = input.readTag();
537             if (nextTag != tag) {
538               // We've reached the end of the repeated field. Save the next tag value.
539               this.nextTag = nextTag;
540               return;
541             }
542           }
543         default:
544           throw InvalidProtocolBufferException.invalidWireType();
545       }
546     } else {
547       switch (WireFormat.getTagWireType(tag)) {
548         case WIRETYPE_LENGTH_DELIMITED:
549           final int bytes = input.readUInt32();
550           int endPos = input.getTotalBytesRead() + bytes;
551           do {
552             target.add(input.readInt32());
553           } while (input.getTotalBytesRead() < endPos);
554           requirePosition(endPos);
555           break;
556         case WIRETYPE_VARINT:
557           while (true) {
558             target.add(input.readInt32());
559             if (input.isAtEnd()) {
560               return;
561             }
562             int nextTag = input.readTag();
563             if (nextTag != tag) {
564               // We've reached the end of the repeated field. Save the next tag value.
565               this.nextTag = nextTag;
566               return;
567             }
568           }
569         default:
570           throw InvalidProtocolBufferException.invalidWireType();
571       }
572     }
573   }
574 
575   @Override
readFixed64List(List<Long> target)576   public void readFixed64List(List<Long> target) throws IOException {
577     if (target instanceof LongArrayList) {
578       LongArrayList plist = (LongArrayList) target;
579       switch (WireFormat.getTagWireType(tag)) {
580         case WIRETYPE_LENGTH_DELIMITED:
581           final int bytes = input.readUInt32();
582           verifyPackedFixed64Length(bytes);
583           int endPos = input.getTotalBytesRead() + bytes;
584           do {
585             plist.addLong(input.readFixed64());
586           } while (input.getTotalBytesRead() < endPos);
587           break;
588         case WIRETYPE_FIXED64:
589           while (true) {
590             plist.addLong(input.readFixed64());
591             if (input.isAtEnd()) {
592               return;
593             }
594             int nextTag = input.readTag();
595             if (nextTag != tag) {
596               // We've reached the end of the repeated field. Save the next tag value.
597               this.nextTag = nextTag;
598               return;
599             }
600           }
601         default:
602           throw InvalidProtocolBufferException.invalidWireType();
603       }
604     } else {
605       switch (WireFormat.getTagWireType(tag)) {
606         case WIRETYPE_LENGTH_DELIMITED:
607           final int bytes = input.readUInt32();
608           verifyPackedFixed64Length(bytes);
609           int endPos = input.getTotalBytesRead() + bytes;
610           do {
611             target.add(input.readFixed64());
612           } while (input.getTotalBytesRead() < endPos);
613           break;
614         case WIRETYPE_FIXED64:
615           while (true) {
616             target.add(input.readFixed64());
617             if (input.isAtEnd()) {
618               return;
619             }
620             int nextTag = input.readTag();
621             if (nextTag != tag) {
622               // We've reached the end of the repeated field. Save the next tag value.
623               this.nextTag = nextTag;
624               return;
625             }
626           }
627         default:
628           throw InvalidProtocolBufferException.invalidWireType();
629       }
630     }
631   }
632 
633   @Override
readFixed32List(List<Integer> target)634   public void readFixed32List(List<Integer> target) throws IOException {
635     if (target instanceof IntArrayList) {
636       IntArrayList plist = (IntArrayList) target;
637       switch (WireFormat.getTagWireType(tag)) {
638         case WIRETYPE_LENGTH_DELIMITED:
639           final int bytes = input.readUInt32();
640           verifyPackedFixed32Length(bytes);
641           int endPos = input.getTotalBytesRead() + bytes;
642           do {
643             plist.addInt(input.readFixed32());
644           } while (input.getTotalBytesRead() < endPos);
645           break;
646         case WIRETYPE_FIXED32:
647           while (true) {
648             plist.addInt(input.readFixed32());
649             if (input.isAtEnd()) {
650               return;
651             }
652             int nextTag = input.readTag();
653             if (nextTag != tag) {
654               // We've reached the end of the repeated field. Save the next tag value.
655               this.nextTag = nextTag;
656               return;
657             }
658           }
659         default:
660           throw InvalidProtocolBufferException.invalidWireType();
661       }
662     } else {
663       switch (WireFormat.getTagWireType(tag)) {
664         case WIRETYPE_LENGTH_DELIMITED:
665           final int bytes = input.readUInt32();
666           verifyPackedFixed32Length(bytes);
667           int endPos = input.getTotalBytesRead() + bytes;
668           do {
669             target.add(input.readFixed32());
670           } while (input.getTotalBytesRead() < endPos);
671           break;
672         case WIRETYPE_FIXED32:
673           while (true) {
674             target.add(input.readFixed32());
675             if (input.isAtEnd()) {
676               return;
677             }
678             int nextTag = input.readTag();
679             if (nextTag != tag) {
680               // We've reached the end of the repeated field. Save the next tag value.
681               this.nextTag = nextTag;
682               return;
683             }
684           }
685         default:
686           throw InvalidProtocolBufferException.invalidWireType();
687       }
688     }
689   }
690 
691   @Override
readBoolList(List<Boolean> target)692   public void readBoolList(List<Boolean> target) throws IOException {
693     if (target instanceof BooleanArrayList) {
694       BooleanArrayList plist = (BooleanArrayList) target;
695       switch (WireFormat.getTagWireType(tag)) {
696         case WIRETYPE_LENGTH_DELIMITED:
697           final int bytes = input.readUInt32();
698           int endPos = input.getTotalBytesRead() + bytes;
699           do {
700             plist.addBoolean(input.readBool());
701           } while (input.getTotalBytesRead() < endPos);
702           requirePosition(endPos);
703           break;
704         case WIRETYPE_VARINT:
705           while (true) {
706             plist.addBoolean(input.readBool());
707             if (input.isAtEnd()) {
708               return;
709             }
710             int nextTag = input.readTag();
711             if (nextTag != tag) {
712               // We've reached the end of the repeated field. Save the next tag value.
713               this.nextTag = nextTag;
714               return;
715             }
716           }
717         default:
718           throw InvalidProtocolBufferException.invalidWireType();
719       }
720     } else {
721       switch (WireFormat.getTagWireType(tag)) {
722         case WIRETYPE_LENGTH_DELIMITED:
723           final int bytes = input.readUInt32();
724           int endPos = input.getTotalBytesRead() + bytes;
725           do {
726             target.add(input.readBool());
727           } while (input.getTotalBytesRead() < endPos);
728           requirePosition(endPos);
729           break;
730         case WIRETYPE_VARINT:
731           while (true) {
732             target.add(input.readBool());
733             if (input.isAtEnd()) {
734               return;
735             }
736             int nextTag = input.readTag();
737             if (nextTag != tag) {
738               // We've reached the end of the repeated field. Save the next tag value.
739               this.nextTag = nextTag;
740               return;
741             }
742           }
743         default:
744           throw InvalidProtocolBufferException.invalidWireType();
745       }
746     }
747   }
748 
749   @Override
readStringList(List<String> target)750   public void readStringList(List<String> target) throws IOException {
751     readStringListInternal(target, false);
752   }
753 
754   @Override
readStringListRequireUtf8(List<String> target)755   public void readStringListRequireUtf8(List<String> target) throws IOException {
756     readStringListInternal(target, true);
757   }
758 
readStringListInternal(List<String> target, boolean requireUtf8)759   public void readStringListInternal(List<String> target, boolean requireUtf8) throws IOException {
760     if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
761       throw InvalidProtocolBufferException.invalidWireType();
762     }
763 
764     if (target instanceof LazyStringList && !requireUtf8) {
765       LazyStringList lazyList = (LazyStringList) target;
766       while (true) {
767         lazyList.add(readBytes());
768         if (input.isAtEnd()) {
769           return;
770         }
771         int nextTag = input.readTag();
772         if (nextTag != tag) {
773           // We've reached the end of the repeated field. Save the next tag value.
774           this.nextTag = nextTag;
775           return;
776         }
777       }
778     } else {
779       while (true) {
780         target.add(requireUtf8 ? readStringRequireUtf8() : readString());
781         if (input.isAtEnd()) {
782           return;
783         }
784         int nextTag = input.readTag();
785         if (nextTag != tag) {
786           // We've reached the end of the repeated field. Save the next tag value.
787           this.nextTag = nextTag;
788           return;
789         }
790       }
791     }
792   }
793 
794   @Override
readMessageList( List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)795   public <T> void readMessageList(
796       List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
797       throws IOException {
798     final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
799     readMessageList(target, schema, extensionRegistry);
800   }
801 
802   @Override
readMessageList( List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)803   public <T> void readMessageList(
804       List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
805       throws IOException {
806     if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
807       throw InvalidProtocolBufferException.invalidWireType();
808     }
809     final int listTag = tag;
810     while (true) {
811       target.add(readMessage(schema, extensionRegistry));
812       if (input.isAtEnd() || nextTag != NEXT_TAG_UNSET) {
813         return;
814       }
815       int nextTag = input.readTag();
816       if (nextTag != listTag) {
817         // We've reached the end of the repeated field. Save the next tag value.
818         this.nextTag = nextTag;
819         return;
820       }
821     }
822   }
823 
824   @Override
readGroupList( List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)825   public <T> void readGroupList(
826       List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
827       throws IOException {
828     final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
829     readGroupList(target, schema, extensionRegistry);
830   }
831 
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 RuntimeException("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