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