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