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