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.Internal.EMPTY_BYTE_ARRAY; 11 import static com.google.protobuf.Internal.EMPTY_BYTE_BUFFER; 12 import static com.google.protobuf.Internal.UTF_8; 13 import static com.google.protobuf.Internal.checkNotNull; 14 import static com.google.protobuf.WireFormat.FIXED32_SIZE; 15 import static com.google.protobuf.WireFormat.FIXED64_SIZE; 16 import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE; 17 18 import java.io.ByteArrayOutputStream; 19 import java.io.IOException; 20 import java.io.InputStream; 21 import java.nio.Buffer; 22 import java.nio.ByteBuffer; 23 import java.util.ArrayList; 24 import java.util.Arrays; 25 import java.util.Iterator; 26 import java.util.List; 27 28 /** 29 * Reads and decodes protocol message fields. 30 * 31 * <p>This class contains two kinds of methods: methods that read specific protocol message 32 * constructs and field types (e.g. {@link #readTag()} and {@link #readInt32()}) and methods that 33 * read low-level values (e.g. {@link #readRawVarint32()} and {@link #readRawBytes}). If you are 34 * reading encoded protocol messages, you should use the former methods, but if you are reading some 35 * other format of your own design, use the latter. 36 * 37 * @author kenton@google.com Kenton Varda 38 */ 39 public abstract class CodedInputStream { 40 private static final int DEFAULT_BUFFER_SIZE = 4096; 41 // Integer.MAX_VALUE == 0x7FFFFFF == INT_MAX from limits.h 42 private static final int DEFAULT_SIZE_LIMIT = Integer.MAX_VALUE; 43 private static volatile int defaultRecursionLimit = 100; 44 45 /** Visible for subclasses. See setRecursionLimit() */ 46 int recursionDepth; 47 48 int recursionLimit = defaultRecursionLimit; 49 50 /** Visible for subclasses. See setSizeLimit() */ 51 int sizeLimit = DEFAULT_SIZE_LIMIT; 52 53 /** Used to adapt to the experimental {@link Reader} interface. */ 54 CodedInputStreamReader wrapper; 55 56 /** Create a new CodedInputStream wrapping the given InputStream. */ newInstance(final InputStream input)57 public static CodedInputStream newInstance(final InputStream input) { 58 return newInstance(input, DEFAULT_BUFFER_SIZE); 59 } 60 61 /** Create a new CodedInputStream wrapping the given InputStream, with a specified buffer size. */ newInstance(final InputStream input, int bufferSize)62 public static CodedInputStream newInstance(final InputStream input, int bufferSize) { 63 if (bufferSize <= 0) { 64 throw new IllegalArgumentException("bufferSize must be > 0"); 65 } 66 if (input == null) { 67 // Ideally we would throw here. This is done for backward compatibility. 68 return newInstance(EMPTY_BYTE_ARRAY); 69 } 70 return new StreamDecoder(input, bufferSize); 71 } 72 73 /** Create a new CodedInputStream wrapping the given {@code Iterable <ByteBuffer>}. */ newInstance(final Iterable<ByteBuffer> input)74 public static CodedInputStream newInstance(final Iterable<ByteBuffer> input) { 75 if (!UnsafeDirectNioDecoder.isSupported()) { 76 return newInstance(new IterableByteBufferInputStream(input)); 77 } 78 return newInstance(input, false); 79 } 80 81 /** Create a new CodedInputStream wrapping the given {@code Iterable <ByteBuffer>}. */ newInstance( final Iterable<ByteBuffer> bufs, final boolean bufferIsImmutable)82 static CodedInputStream newInstance( 83 final Iterable<ByteBuffer> bufs, final boolean bufferIsImmutable) { 84 // flag is to check the type of input's ByteBuffers. 85 // flag equals 1: all ByteBuffers have array. 86 // flag equals 2: all ByteBuffers are direct ByteBuffers. 87 // flag equals 3: some ByteBuffers are direct and some have array. 88 // flag greater than 3: other cases. 89 int flag = 0; 90 // Total size of the input 91 int totalSize = 0; 92 for (ByteBuffer buf : bufs) { 93 totalSize += buf.remaining(); 94 if (buf.hasArray()) { 95 flag |= 1; 96 } else if (buf.isDirect()) { 97 flag |= 2; 98 } else { 99 flag |= 4; 100 } 101 } 102 if (flag == 2) { 103 return new IterableDirectByteBufferDecoder(bufs, totalSize, bufferIsImmutable); 104 } else { 105 // TODO: add another decoders to deal case 1 and 3. 106 return newInstance(new IterableByteBufferInputStream(bufs)); 107 } 108 } 109 110 /** Create a new CodedInputStream wrapping the given byte array. */ newInstance(final byte[] buf)111 public static CodedInputStream newInstance(final byte[] buf) { 112 return newInstance(buf, 0, buf.length); 113 } 114 115 /** Create a new CodedInputStream wrapping the given byte array slice. */ newInstance(final byte[] buf, final int off, final int len)116 public static CodedInputStream newInstance(final byte[] buf, final int off, final int len) { 117 return newInstance(buf, off, len, /* bufferIsImmutable= */ false); 118 } 119 120 /** Create a new CodedInputStream wrapping the given byte array slice. */ newInstance( final byte[] buf, final int off, final int len, final boolean bufferIsImmutable)121 static CodedInputStream newInstance( 122 final byte[] buf, final int off, final int len, final boolean bufferIsImmutable) { 123 ArrayDecoder result = new ArrayDecoder(buf, off, len, bufferIsImmutable); 124 try { 125 // Some uses of CodedInputStream can be more efficient if they know 126 // exactly how many bytes are available. By pushing the end point of the 127 // buffer as a limit, we allow them to get this information via 128 // getBytesUntilLimit(). Pushing a limit that we know is at the end of 129 // the stream can never hurt, since we can never past that point anyway. 130 result.pushLimit(len); 131 } catch (InvalidProtocolBufferException ex) { 132 // The only reason pushLimit() might throw an exception here is if len 133 // is negative. Normally pushLimit()'s parameter comes directly off the 134 // wire, so it's important to catch exceptions in case of corrupt or 135 // malicious data. However, in this case, we expect that len is not a 136 // user-supplied value, so we can assume that it being negative indicates 137 // a programming error. Therefore, throwing an unchecked exception is 138 // appropriate. 139 throw new IllegalArgumentException(ex); 140 } 141 return result; 142 } 143 144 /** 145 * Create a new CodedInputStream wrapping the given ByteBuffer. The data starting from the 146 * ByteBuffer's current position to its limit will be read. The returned CodedInputStream may or 147 * may not share the underlying data in the ByteBuffer, therefore the ByteBuffer cannot be changed 148 * while the CodedInputStream is in use. Note that the ByteBuffer's position won't be changed by 149 * this function. Concurrent calls with the same ByteBuffer object are safe if no other thread is 150 * trying to alter the ByteBuffer's status. 151 */ newInstance(ByteBuffer buf)152 public static CodedInputStream newInstance(ByteBuffer buf) { 153 return newInstance(buf, /* bufferIsImmutable= */ false); 154 } 155 156 /** Create a new CodedInputStream wrapping the given buffer. */ newInstance(ByteBuffer buf, boolean bufferIsImmutable)157 static CodedInputStream newInstance(ByteBuffer buf, boolean bufferIsImmutable) { 158 if (buf.hasArray()) { 159 return newInstance( 160 buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), bufferIsImmutable); 161 } 162 163 if (buf.isDirect() && UnsafeDirectNioDecoder.isSupported()) { 164 return new UnsafeDirectNioDecoder(buf, bufferIsImmutable); 165 } 166 167 // The buffer is non-direct and does not expose the underlying array. Using the ByteBuffer API 168 // to access individual bytes is very slow, so just copy the buffer to an array. 169 // TODO: Re-evaluate with Java 9 170 byte[] buffer = new byte[buf.remaining()]; 171 buf.duplicate().get(buffer); 172 return newInstance(buffer, 0, buffer.length, true); 173 } 174 checkRecursionLimit()175 public void checkRecursionLimit() throws InvalidProtocolBufferException { 176 if (recursionDepth >= recursionLimit) { 177 throw InvalidProtocolBufferException.recursionLimitExceeded(); 178 } 179 } 180 181 /** Disable construction/inheritance outside of this class. */ CodedInputStream()182 private CodedInputStream() {} 183 184 // ----------------------------------------------------------------- 185 186 /** 187 * Attempt to read a field tag, returning zero if we have reached EOF. Protocol message parsers 188 * use this to read tags, since a protocol message may legally end wherever a tag occurs, and zero 189 * is not a valid tag number. 190 */ readTag()191 public abstract int readTag() throws IOException; 192 193 /** 194 * Verifies that the last call to readTag() returned the given tag value. This is used to verify 195 * that a nested group ended with the correct end tag. 196 * 197 * @throws InvalidProtocolBufferException {@code value} does not match the last tag. 198 */ checkLastTagWas(final int value)199 public abstract void checkLastTagWas(final int value) throws InvalidProtocolBufferException; 200 getLastTag()201 public abstract int getLastTag(); 202 203 /** 204 * Reads and discards a single field, given its tag value. 205 * 206 * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped. 207 * Otherwise, returns {@code true}. 208 */ skipField(final int tag)209 public abstract boolean skipField(final int tag) throws IOException; 210 211 /** 212 * Reads a single field and writes it to output in wire format, given its tag value. 213 * 214 * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped. 215 * Otherwise, returns {@code true}. 216 * @deprecated use {@code UnknownFieldSet} or {@code UnknownFieldSetLite} to skip to an output 217 * stream. 218 */ 219 @Deprecated skipField(final int tag, final CodedOutputStream output)220 public abstract boolean skipField(final int tag, final CodedOutputStream output) 221 throws IOException; 222 223 /** 224 * Reads and discards an entire message. This will read either until EOF or until an endgroup tag, 225 * whichever comes first. 226 */ skipMessage()227 public void skipMessage() throws IOException { 228 while (true) { 229 final int tag = readTag(); 230 if (tag == 0) { 231 return; 232 } 233 checkRecursionLimit(); 234 ++recursionDepth; 235 boolean fieldSkipped = skipField(tag); 236 --recursionDepth; 237 if (!fieldSkipped) { 238 return; 239 } 240 } 241 } 242 243 /** 244 * Reads an entire message and writes it to output in wire format. This will read either until EOF 245 * or until an endgroup tag, whichever comes first. 246 */ skipMessage(CodedOutputStream output)247 public void skipMessage(CodedOutputStream output) throws IOException { 248 while (true) { 249 final int tag = readTag(); 250 if (tag == 0) { 251 return; 252 } 253 checkRecursionLimit(); 254 ++recursionDepth; 255 boolean fieldSkipped = skipField(tag, output); 256 --recursionDepth; 257 if (!fieldSkipped) { 258 return; 259 } 260 } 261 } 262 263 // ----------------------------------------------------------------- 264 265 /** Read a {@code double} field value from the stream. */ readDouble()266 public abstract double readDouble() throws IOException; 267 268 /** Read a {@code float} field value from the stream. */ readFloat()269 public abstract float readFloat() throws IOException; 270 271 /** Read a {@code uint64} field value from the stream. */ readUInt64()272 public abstract long readUInt64() throws IOException; 273 274 /** Read an {@code int64} field value from the stream. */ readInt64()275 public abstract long readInt64() throws IOException; 276 277 /** Read an {@code int32} field value from the stream. */ readInt32()278 public abstract int readInt32() throws IOException; 279 280 /** Read a {@code fixed64} field value from the stream. */ readFixed64()281 public abstract long readFixed64() throws IOException; 282 283 /** Read a {@code fixed32} field value from the stream. */ readFixed32()284 public abstract int readFixed32() throws IOException; 285 286 /** Read a {@code bool} field value from the stream. */ readBool()287 public abstract boolean readBool() throws IOException; 288 289 /** 290 * Read a {@code string} field value from the stream. If the stream contains malformed UTF-8, 291 * replace the offending bytes with the standard UTF-8 replacement character. 292 */ readString()293 public abstract String readString() throws IOException; 294 295 /** 296 * Read a {@code string} field value from the stream. If the stream contains malformed UTF-8, 297 * throw exception {@link InvalidProtocolBufferException}. 298 */ readStringRequireUtf8()299 public abstract String readStringRequireUtf8() throws IOException; 300 301 /** Read a {@code group} field value from the stream. */ readGroup( final int fieldNumber, final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)302 public abstract void readGroup( 303 final int fieldNumber, 304 final MessageLite.Builder builder, 305 final ExtensionRegistryLite extensionRegistry) 306 throws IOException; 307 308 /** Read a {@code group} field value from the stream. */ readGroup( final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)309 public abstract <T extends MessageLite> T readGroup( 310 final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) 311 throws IOException; 312 313 /** 314 * Reads a {@code group} field value from the stream and merges it into the given {@link 315 * UnknownFieldSet}. 316 * 317 * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so you can just call 318 * {@link #readGroup}. 319 */ 320 @Deprecated readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)321 public abstract void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder) 322 throws IOException; 323 324 /** Read an embedded message field value from the stream. */ readMessage( final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)325 public abstract void readMessage( 326 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry) 327 throws IOException; 328 329 /** Read an embedded message field value from the stream. */ readMessage( final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)330 public abstract <T extends MessageLite> T readMessage( 331 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException; 332 333 /** Read a {@code bytes} field value from the stream. */ readBytes()334 public abstract ByteString readBytes() throws IOException; 335 336 /** Read a {@code bytes} field value from the stream. */ readByteArray()337 public abstract byte[] readByteArray() throws IOException; 338 339 /** Read a {@code bytes} field value from the stream. */ readByteBuffer()340 public abstract ByteBuffer readByteBuffer() throws IOException; 341 342 /** Read a {@code uint32} field value from the stream. */ readUInt32()343 public abstract int readUInt32() throws IOException; 344 345 /** 346 * Read an enum field value from the stream. Caller is responsible for converting the numeric 347 * value to an actual enum. 348 */ readEnum()349 public abstract int readEnum() throws IOException; 350 351 /** Read an {@code sfixed32} field value from the stream. */ readSFixed32()352 public abstract int readSFixed32() throws IOException; 353 354 /** Read an {@code sfixed64} field value from the stream. */ readSFixed64()355 public abstract long readSFixed64() throws IOException; 356 357 /** Read an {@code sint32} field value from the stream. */ readSInt32()358 public abstract int readSInt32() throws IOException; 359 360 /** Read an {@code sint64} field value from the stream. */ readSInt64()361 public abstract long readSInt64() throws IOException; 362 363 // ================================================================= 364 365 /** Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits. */ readRawVarint32()366 public abstract int readRawVarint32() throws IOException; 367 368 /** Read a raw Varint from the stream. */ readRawVarint64()369 public abstract long readRawVarint64() throws IOException; 370 371 /** Variant of readRawVarint64 for when uncomfortably close to the limit. */ 372 /* Visible for testing */ readRawVarint64SlowPath()373 abstract long readRawVarint64SlowPath() throws IOException; 374 375 /** Read a 32-bit little-endian integer from the stream. */ readRawLittleEndian32()376 public abstract int readRawLittleEndian32() throws IOException; 377 378 /** Read a 64-bit little-endian integer from the stream. */ readRawLittleEndian64()379 public abstract long readRawLittleEndian64() throws IOException; 380 381 // ----------------------------------------------------------------- 382 383 /** 384 * Enables {@link ByteString} aliasing of the underlying buffer, trading off on buffer pinning for 385 * data copies. Only valid for buffer-backed streams. 386 */ enableAliasing(boolean enabled)387 public abstract void enableAliasing(boolean enabled); 388 389 /** 390 * Set the maximum message recursion depth. In order to prevent malicious messages from causing 391 * stack overflows, {@code CodedInputStream} limits how deeply messages may be nested. The default 392 * limit is 100. 393 * 394 * @return the old limit. 395 */ setRecursionLimit(final int limit)396 public final int setRecursionLimit(final int limit) { 397 if (limit < 0) { 398 throw new IllegalArgumentException("Recursion limit cannot be negative: " + limit); 399 } 400 final int oldLimit = recursionLimit; 401 recursionLimit = limit; 402 return oldLimit; 403 } 404 405 /** 406 * Only valid for {@link InputStream}-backed streams. 407 * 408 * <p>Set the maximum message size. In order to prevent malicious messages from exhausting memory 409 * or causing integer overflows, {@code CodedInputStream} limits how large a message may be. The 410 * default limit is {@code Integer.MAX_VALUE}. You should set this limit as small as you can 411 * without harming your app's functionality. Note that size limits only apply when reading from an 412 * {@code InputStream}, not when constructed around a raw byte array. 413 * 414 * <p>If you want to read several messages from a single CodedInputStream, you could call {@link 415 * #resetSizeCounter()} after each one to avoid hitting the size limit. 416 * 417 * @return the old limit. 418 */ setSizeLimit(final int limit)419 public final int setSizeLimit(final int limit) { 420 if (limit < 0) { 421 throw new IllegalArgumentException("Size limit cannot be negative: " + limit); 422 } 423 final int oldLimit = sizeLimit; 424 sizeLimit = limit; 425 return oldLimit; 426 } 427 428 private boolean shouldDiscardUnknownFields = false; 429 430 /** 431 * Sets this {@code CodedInputStream} to discard unknown fields. Only applies to full runtime 432 * messages; lite messages will always preserve unknowns. 433 * 434 * <p>Note calling this function alone will have NO immediate effect on the underlying input data. 435 * The unknown fields will be discarded during parsing. This affects both Proto2 and Proto3 full 436 * runtime. 437 */ discardUnknownFields()438 final void discardUnknownFields() { 439 shouldDiscardUnknownFields = true; 440 } 441 442 /** 443 * Reverts the unknown fields preservation behavior for Proto2 and Proto3 full runtime to their 444 * default. 445 */ unsetDiscardUnknownFields()446 final void unsetDiscardUnknownFields() { 447 shouldDiscardUnknownFields = false; 448 } 449 450 /** 451 * Whether unknown fields in this input stream should be discarded during parsing into full 452 * runtime messages. 453 */ shouldDiscardUnknownFields()454 final boolean shouldDiscardUnknownFields() { 455 return shouldDiscardUnknownFields; 456 } 457 458 /** 459 * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). Only valid for {@link 460 * InputStream}-backed streams. 461 */ resetSizeCounter()462 public abstract void resetSizeCounter(); 463 464 /** 465 * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This is called when 466 * descending into a length-delimited embedded message. 467 * 468 * <p>Note that {@code pushLimit()} does NOT affect how many bytes the {@code CodedInputStream} 469 * reads from an underlying {@code InputStream} when refreshing its buffer. If you need to prevent 470 * reading past a certain point in the underlying {@code InputStream} (e.g. because you expect it 471 * to contain more data after the end of the message which you need to handle differently) then 472 * you must place a wrapper around your {@code InputStream} which limits the amount of data that 473 * can be read from it. 474 * 475 * @return the old limit. 476 */ pushLimit(int byteLimit)477 public abstract int pushLimit(int byteLimit) throws InvalidProtocolBufferException; 478 479 /** 480 * Discards the current limit, returning to the previous limit. 481 * 482 * @param oldLimit The old limit, as returned by {@code pushLimit}. 483 */ popLimit(final int oldLimit)484 public abstract void popLimit(final int oldLimit); 485 486 /** 487 * Returns the number of bytes to be read before the current limit. If no limit is set, returns 488 * -1. 489 */ getBytesUntilLimit()490 public abstract int getBytesUntilLimit(); 491 492 /** 493 * Returns true if the stream has reached the end of the input. This is the case if either the end 494 * of the underlying input source has been reached or if the stream has reached a limit created 495 * using {@link #pushLimit(int)}. This function may get blocked when using StreamDecoder as it 496 * invokes {@link StreamDecoder#tryRefillBuffer(int)} in this function which will try to read 497 * bytes from input. 498 */ isAtEnd()499 public abstract boolean isAtEnd() throws IOException; 500 501 /** 502 * The total bytes read up to the current position. Calling {@link #resetSizeCounter()} resets 503 * this value to zero. 504 */ getTotalBytesRead()505 public abstract int getTotalBytesRead(); 506 507 /** 508 * Read one byte from the input. 509 * 510 * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached. 511 */ readRawByte()512 public abstract byte readRawByte() throws IOException; 513 514 /** 515 * Read a fixed size of bytes from the input. 516 * 517 * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached. 518 */ readRawBytes(final int size)519 public abstract byte[] readRawBytes(final int size) throws IOException; 520 521 /** 522 * Reads and discards {@code size} bytes. 523 * 524 * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached. 525 */ skipRawBytes(final int size)526 public abstract void skipRawBytes(final int size) throws IOException; 527 528 /** 529 * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers into values that can be 530 * efficiently encoded with varint. (Otherwise, negative values must be sign-extended to 64 bits 531 * to be varint encoded, thus always taking 10 bytes on the wire.) 532 * 533 * @param n An unsigned 32-bit integer, stored in a signed int because Java has no explicit 534 * unsigned support. 535 * @return A signed 32-bit integer. 536 */ decodeZigZag32(final int n)537 public static int decodeZigZag32(final int n) { 538 return (n >>> 1) ^ -(n & 1); 539 } 540 541 /** 542 * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers into values that can be 543 * efficiently encoded with varint. (Otherwise, negative values must be sign-extended to 64 bits 544 * to be varint encoded, thus always taking 10 bytes on the wire.) 545 * 546 * @param n An unsigned 64-bit integer, stored in a signed int because Java has no explicit 547 * unsigned support. 548 * @return A signed 64-bit integer. 549 */ decodeZigZag64(final long n)550 public static long decodeZigZag64(final long n) { 551 return (n >>> 1) ^ -(n & 1); 552 } 553 554 /** 555 * Like {@link #readRawVarint32(InputStream)}, but expects that the caller has already read one 556 * byte. This allows the caller to determine if EOF has been reached before attempting to read. 557 */ readRawVarint32(final int firstByte, final InputStream input)558 public static int readRawVarint32(final int firstByte, final InputStream input) 559 throws IOException { 560 if ((firstByte & 0x80) == 0) { 561 return firstByte; 562 } 563 564 int result = firstByte & 0x7f; 565 int offset = 7; 566 for (; offset < 32; offset += 7) { 567 final int b = input.read(); 568 if (b == -1) { 569 throw InvalidProtocolBufferException.truncatedMessage(); 570 } 571 result |= (b & 0x7f) << offset; 572 if ((b & 0x80) == 0) { 573 return result; 574 } 575 } 576 // Keep reading up to 64 bits. 577 for (; offset < 64; offset += 7) { 578 final int b = input.read(); 579 if (b == -1) { 580 throw InvalidProtocolBufferException.truncatedMessage(); 581 } 582 if ((b & 0x80) == 0) { 583 return result; 584 } 585 } 586 throw InvalidProtocolBufferException.malformedVarint(); 587 } 588 589 /** 590 * Reads a varint from the input one byte at a time, so that it does not read any bytes after the 591 * end of the varint. If you simply wrapped the stream in a CodedInputStream and used {@link 592 * #readRawVarint32(InputStream)} then you would probably end up reading past the end of the 593 * varint since CodedInputStream buffers its input. 594 */ readRawVarint32(final InputStream input)595 static int readRawVarint32(final InputStream input) throws IOException { 596 final int firstByte = input.read(); 597 if (firstByte == -1) { 598 throw InvalidProtocolBufferException.truncatedMessage(); 599 } 600 return readRawVarint32(firstByte, input); 601 } 602 603 /** A {@link CodedInputStream} implementation that uses a backing array as the input. */ 604 private static final class ArrayDecoder extends CodedInputStream { 605 private final byte[] buffer; 606 private final boolean immutable; 607 private int limit; 608 private int bufferSizeAfterLimit; 609 private int pos; 610 private int startPos; 611 private int lastTag; 612 private boolean enableAliasing; 613 614 /** The absolute position of the end of the current message. */ 615 private int currentLimit = Integer.MAX_VALUE; 616 ArrayDecoder(final byte[] buffer, final int offset, final int len, boolean immutable)617 private ArrayDecoder(final byte[] buffer, final int offset, final int len, boolean immutable) { 618 this.buffer = buffer; 619 limit = offset + len; 620 pos = offset; 621 startPos = pos; 622 this.immutable = immutable; 623 } 624 625 @Override readTag()626 public int readTag() throws IOException { 627 if (isAtEnd()) { 628 lastTag = 0; 629 return 0; 630 } 631 632 lastTag = readRawVarint32(); 633 if (WireFormat.getTagFieldNumber(lastTag) == 0) { 634 // If we actually read zero (or any tag number corresponding to field 635 // number zero), that's not a valid tag. 636 throw InvalidProtocolBufferException.invalidTag(); 637 } 638 return lastTag; 639 } 640 641 @Override checkLastTagWas(final int value)642 public void checkLastTagWas(final int value) throws InvalidProtocolBufferException { 643 if (lastTag != value) { 644 throw InvalidProtocolBufferException.invalidEndTag(); 645 } 646 } 647 648 @Override getLastTag()649 public int getLastTag() { 650 return lastTag; 651 } 652 653 @Override skipField(final int tag)654 public boolean skipField(final int tag) throws IOException { 655 switch (WireFormat.getTagWireType(tag)) { 656 case WireFormat.WIRETYPE_VARINT: 657 skipRawVarint(); 658 return true; 659 case WireFormat.WIRETYPE_FIXED64: 660 skipRawBytes(FIXED64_SIZE); 661 return true; 662 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 663 skipRawBytes(readRawVarint32()); 664 return true; 665 case WireFormat.WIRETYPE_START_GROUP: 666 skipMessage(); 667 checkLastTagWas( 668 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP)); 669 return true; 670 case WireFormat.WIRETYPE_END_GROUP: 671 return false; 672 case WireFormat.WIRETYPE_FIXED32: 673 skipRawBytes(FIXED32_SIZE); 674 return true; 675 default: 676 throw InvalidProtocolBufferException.invalidWireType(); 677 } 678 } 679 680 @Override skipField(final int tag, final CodedOutputStream output)681 public boolean skipField(final int tag, final CodedOutputStream output) throws IOException { 682 switch (WireFormat.getTagWireType(tag)) { 683 case WireFormat.WIRETYPE_VARINT: 684 { 685 long value = readInt64(); 686 output.writeUInt32NoTag(tag); 687 output.writeUInt64NoTag(value); 688 return true; 689 } 690 case WireFormat.WIRETYPE_FIXED64: 691 { 692 long value = readRawLittleEndian64(); 693 output.writeUInt32NoTag(tag); 694 output.writeFixed64NoTag(value); 695 return true; 696 } 697 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 698 { 699 ByteString value = readBytes(); 700 output.writeUInt32NoTag(tag); 701 output.writeBytesNoTag(value); 702 return true; 703 } 704 case WireFormat.WIRETYPE_START_GROUP: 705 { 706 output.writeUInt32NoTag(tag); 707 skipMessage(output); 708 int endtag = 709 WireFormat.makeTag( 710 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP); 711 checkLastTagWas(endtag); 712 output.writeUInt32NoTag(endtag); 713 return true; 714 } 715 case WireFormat.WIRETYPE_END_GROUP: 716 { 717 return false; 718 } 719 case WireFormat.WIRETYPE_FIXED32: 720 { 721 int value = readRawLittleEndian32(); 722 output.writeUInt32NoTag(tag); 723 output.writeFixed32NoTag(value); 724 return true; 725 } 726 default: 727 throw InvalidProtocolBufferException.invalidWireType(); 728 } 729 } 730 731 // ----------------------------------------------------------------- 732 733 @Override readDouble()734 public double readDouble() throws IOException { 735 return Double.longBitsToDouble(readRawLittleEndian64()); 736 } 737 738 @Override readFloat()739 public float readFloat() throws IOException { 740 return Float.intBitsToFloat(readRawLittleEndian32()); 741 } 742 743 @Override readUInt64()744 public long readUInt64() throws IOException { 745 return readRawVarint64(); 746 } 747 748 @Override readInt64()749 public long readInt64() throws IOException { 750 return readRawVarint64(); 751 } 752 753 @Override readInt32()754 public int readInt32() throws IOException { 755 return readRawVarint32(); 756 } 757 758 @Override readFixed64()759 public long readFixed64() throws IOException { 760 return readRawLittleEndian64(); 761 } 762 763 @Override readFixed32()764 public int readFixed32() throws IOException { 765 return readRawLittleEndian32(); 766 } 767 768 @Override readBool()769 public boolean readBool() throws IOException { 770 return readRawVarint64() != 0; 771 } 772 773 @Override readString()774 public String readString() throws IOException { 775 final int size = readRawVarint32(); 776 if (size > 0 && size <= (limit - pos)) { 777 // Fast path: We already have the bytes in a contiguous buffer, so 778 // just copy directly from it. 779 final String result = new String(buffer, pos, size, UTF_8); 780 pos += size; 781 return result; 782 } 783 784 if (size == 0) { 785 return ""; 786 } 787 if (size < 0) { 788 throw InvalidProtocolBufferException.negativeSize(); 789 } 790 throw InvalidProtocolBufferException.truncatedMessage(); 791 } 792 793 @Override readStringRequireUtf8()794 public String readStringRequireUtf8() throws IOException { 795 final int size = readRawVarint32(); 796 if (size > 0 && size <= (limit - pos)) { 797 String result = Utf8.decodeUtf8(buffer, pos, size); 798 pos += size; 799 return result; 800 } 801 802 if (size == 0) { 803 return ""; 804 } 805 if (size <= 0) { 806 throw InvalidProtocolBufferException.negativeSize(); 807 } 808 throw InvalidProtocolBufferException.truncatedMessage(); 809 } 810 811 @Override readGroup( final int fieldNumber, final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)812 public void readGroup( 813 final int fieldNumber, 814 final MessageLite.Builder builder, 815 final ExtensionRegistryLite extensionRegistry) 816 throws IOException { 817 checkRecursionLimit(); 818 ++recursionDepth; 819 builder.mergeFrom(this, extensionRegistry); 820 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); 821 --recursionDepth; 822 } 823 824 @Override readGroup( final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)825 public <T extends MessageLite> T readGroup( 826 final int fieldNumber, 827 final Parser<T> parser, 828 final ExtensionRegistryLite extensionRegistry) 829 throws IOException { 830 checkRecursionLimit(); 831 ++recursionDepth; 832 T result = parser.parsePartialFrom(this, extensionRegistry); 833 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); 834 --recursionDepth; 835 return result; 836 } 837 838 @Deprecated 839 @Override readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)840 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder) 841 throws IOException { 842 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry()); 843 } 844 845 @Override readMessage( final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)846 public void readMessage( 847 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry) 848 throws IOException { 849 final int length = readRawVarint32(); 850 checkRecursionLimit(); 851 final int oldLimit = pushLimit(length); 852 ++recursionDepth; 853 builder.mergeFrom(this, extensionRegistry); 854 checkLastTagWas(0); 855 --recursionDepth; 856 if (getBytesUntilLimit() != 0) { 857 throw InvalidProtocolBufferException.truncatedMessage(); 858 } 859 popLimit(oldLimit); 860 } 861 862 @Override readMessage( final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)863 public <T extends MessageLite> T readMessage( 864 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException { 865 int length = readRawVarint32(); 866 checkRecursionLimit(); 867 final int oldLimit = pushLimit(length); 868 ++recursionDepth; 869 T result = parser.parsePartialFrom(this, extensionRegistry); 870 checkLastTagWas(0); 871 --recursionDepth; 872 if (getBytesUntilLimit() != 0) { 873 throw InvalidProtocolBufferException.truncatedMessage(); 874 } 875 popLimit(oldLimit); 876 return result; 877 } 878 879 @Override readBytes()880 public ByteString readBytes() throws IOException { 881 final int size = readRawVarint32(); 882 if (size > 0 && size <= (limit - pos)) { 883 // Fast path: We already have the bytes in a contiguous buffer, so 884 // just copy directly from it. 885 final ByteString result = 886 immutable && enableAliasing 887 ? ByteString.wrap(buffer, pos, size) 888 : ByteString.copyFrom(buffer, pos, size); 889 pos += size; 890 return result; 891 } 892 if (size == 0) { 893 return ByteString.EMPTY; 894 } 895 // Slow path: Build a byte array first then copy it. 896 return ByteString.wrap(readRawBytes(size)); 897 } 898 899 @Override readByteArray()900 public byte[] readByteArray() throws IOException { 901 final int size = readRawVarint32(); 902 return readRawBytes(size); 903 } 904 905 @Override readByteBuffer()906 public ByteBuffer readByteBuffer() throws IOException { 907 final int size = readRawVarint32(); 908 if (size > 0 && size <= (limit - pos)) { 909 // Fast path: We already have the bytes in a contiguous buffer. 910 // When aliasing is enabled, we can return a ByteBuffer pointing directly 911 // into the underlying byte array without copy if the CodedInputStream is 912 // constructed from a byte array. If aliasing is disabled or the input is 913 // from an InputStream or ByteString, we have to make a copy of the bytes. 914 ByteBuffer result = 915 !immutable && enableAliasing 916 ? ByteBuffer.wrap(buffer, pos, size).slice() 917 : ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size)); 918 pos += size; 919 // TODO: Investigate making the ByteBuffer be made read-only 920 return result; 921 } 922 923 if (size == 0) { 924 return EMPTY_BYTE_BUFFER; 925 } 926 if (size < 0) { 927 throw InvalidProtocolBufferException.negativeSize(); 928 } 929 throw InvalidProtocolBufferException.truncatedMessage(); 930 } 931 932 @Override readUInt32()933 public int readUInt32() throws IOException { 934 return readRawVarint32(); 935 } 936 937 @Override readEnum()938 public int readEnum() throws IOException { 939 return readRawVarint32(); 940 } 941 942 @Override readSFixed32()943 public int readSFixed32() throws IOException { 944 return readRawLittleEndian32(); 945 } 946 947 @Override readSFixed64()948 public long readSFixed64() throws IOException { 949 return readRawLittleEndian64(); 950 } 951 952 @Override readSInt32()953 public int readSInt32() throws IOException { 954 return decodeZigZag32(readRawVarint32()); 955 } 956 957 @Override readSInt64()958 public long readSInt64() throws IOException { 959 return decodeZigZag64(readRawVarint64()); 960 } 961 962 // ================================================================= 963 964 @Override readRawVarint32()965 public int readRawVarint32() throws IOException { 966 // See implementation notes for readRawVarint64 967 fastpath: 968 { 969 int tempPos = pos; 970 971 if (limit == tempPos) { 972 break fastpath; 973 } 974 975 final byte[] buffer = this.buffer; 976 int x; 977 if ((x = buffer[tempPos++]) >= 0) { 978 pos = tempPos; 979 return x; 980 } else if (limit - tempPos < 9) { 981 break fastpath; 982 } else if ((x ^= (buffer[tempPos++] << 7)) < 0) { 983 x ^= (~0 << 7); 984 } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) { 985 x ^= (~0 << 7) ^ (~0 << 14); 986 } else if ((x ^= (buffer[tempPos++] << 21)) < 0) { 987 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21); 988 } else { 989 int y = buffer[tempPos++]; 990 x ^= y << 28; 991 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28); 992 if (y < 0 993 && buffer[tempPos++] < 0 994 && buffer[tempPos++] < 0 995 && buffer[tempPos++] < 0 996 && buffer[tempPos++] < 0 997 && buffer[tempPos++] < 0) { 998 break fastpath; // Will throw malformedVarint() 999 } 1000 } 1001 pos = tempPos; 1002 return x; 1003 } 1004 return (int) readRawVarint64SlowPath(); 1005 } 1006 skipRawVarint()1007 private void skipRawVarint() throws IOException { 1008 if (limit - pos >= MAX_VARINT_SIZE) { 1009 skipRawVarintFastPath(); 1010 } else { 1011 skipRawVarintSlowPath(); 1012 } 1013 } 1014 skipRawVarintFastPath()1015 private void skipRawVarintFastPath() throws IOException { 1016 for (int i = 0; i < MAX_VARINT_SIZE; i++) { 1017 if (buffer[pos++] >= 0) { 1018 return; 1019 } 1020 } 1021 throw InvalidProtocolBufferException.malformedVarint(); 1022 } 1023 skipRawVarintSlowPath()1024 private void skipRawVarintSlowPath() throws IOException { 1025 for (int i = 0; i < MAX_VARINT_SIZE; i++) { 1026 if (readRawByte() >= 0) { 1027 return; 1028 } 1029 } 1030 throw InvalidProtocolBufferException.malformedVarint(); 1031 } 1032 1033 @Override readRawVarint64()1034 public long readRawVarint64() throws IOException { 1035 // Implementation notes: 1036 // 1037 // Optimized for one-byte values, expected to be common. 1038 // The particular code below was selected from various candidates 1039 // empirically, by winning VarintBenchmark. 1040 // 1041 // Sign extension of (signed) Java bytes is usually a nuisance, but 1042 // we exploit it here to more easily obtain the sign of bytes read. 1043 // Instead of cleaning up the sign extension bits by masking eagerly, 1044 // we delay until we find the final (positive) byte, when we clear all 1045 // accumulated bits with one xor. We depend on javac to constant fold. 1046 fastpath: 1047 { 1048 int tempPos = pos; 1049 1050 if (limit == tempPos) { 1051 break fastpath; 1052 } 1053 1054 final byte[] buffer = this.buffer; 1055 long x; 1056 int y; 1057 if ((y = buffer[tempPos++]) >= 0) { 1058 pos = tempPos; 1059 return y; 1060 } else if (limit - tempPos < 9) { 1061 break fastpath; 1062 } else if ((y ^= (buffer[tempPos++] << 7)) < 0) { 1063 x = y ^ (~0 << 7); 1064 } else if ((y ^= (buffer[tempPos++] << 14)) >= 0) { 1065 x = y ^ ((~0 << 7) ^ (~0 << 14)); 1066 } else if ((y ^= (buffer[tempPos++] << 21)) < 0) { 1067 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21)); 1068 } else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) { 1069 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28); 1070 } else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) { 1071 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35); 1072 } else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) { 1073 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42); 1074 } else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) { 1075 x ^= 1076 (~0L << 7) 1077 ^ (~0L << 14) 1078 ^ (~0L << 21) 1079 ^ (~0L << 28) 1080 ^ (~0L << 35) 1081 ^ (~0L << 42) 1082 ^ (~0L << 49); 1083 } else { 1084 x ^= ((long) buffer[tempPos++] << 56); 1085 x ^= 1086 (~0L << 7) 1087 ^ (~0L << 14) 1088 ^ (~0L << 21) 1089 ^ (~0L << 28) 1090 ^ (~0L << 35) 1091 ^ (~0L << 42) 1092 ^ (~0L << 49) 1093 ^ (~0L << 56); 1094 if (x < 0L) { 1095 if (buffer[tempPos++] < 0L) { 1096 break fastpath; // Will throw malformedVarint() 1097 } 1098 } 1099 } 1100 pos = tempPos; 1101 return x; 1102 } 1103 return readRawVarint64SlowPath(); 1104 } 1105 1106 @Override readRawVarint64SlowPath()1107 long readRawVarint64SlowPath() throws IOException { 1108 long result = 0; 1109 for (int shift = 0; shift < 64; shift += 7) { 1110 final byte b = readRawByte(); 1111 result |= (long) (b & 0x7F) << shift; 1112 if ((b & 0x80) == 0) { 1113 return result; 1114 } 1115 } 1116 throw InvalidProtocolBufferException.malformedVarint(); 1117 } 1118 1119 @Override readRawLittleEndian32()1120 public int readRawLittleEndian32() throws IOException { 1121 int tempPos = pos; 1122 1123 if (limit - tempPos < FIXED32_SIZE) { 1124 throw InvalidProtocolBufferException.truncatedMessage(); 1125 } 1126 1127 final byte[] buffer = this.buffer; 1128 pos = tempPos + FIXED32_SIZE; 1129 return ((buffer[tempPos] & 0xff) 1130 | ((buffer[tempPos + 1] & 0xff) << 8) 1131 | ((buffer[tempPos + 2] & 0xff) << 16) 1132 | ((buffer[tempPos + 3] & 0xff) << 24)); 1133 } 1134 1135 @Override readRawLittleEndian64()1136 public long readRawLittleEndian64() throws IOException { 1137 int tempPos = pos; 1138 1139 if (limit - tempPos < FIXED64_SIZE) { 1140 throw InvalidProtocolBufferException.truncatedMessage(); 1141 } 1142 1143 final byte[] buffer = this.buffer; 1144 pos = tempPos + FIXED64_SIZE; 1145 return ((buffer[tempPos] & 0xffL) 1146 | ((buffer[tempPos + 1] & 0xffL) << 8) 1147 | ((buffer[tempPos + 2] & 0xffL) << 16) 1148 | ((buffer[tempPos + 3] & 0xffL) << 24) 1149 | ((buffer[tempPos + 4] & 0xffL) << 32) 1150 | ((buffer[tempPos + 5] & 0xffL) << 40) 1151 | ((buffer[tempPos + 6] & 0xffL) << 48) 1152 | ((buffer[tempPos + 7] & 0xffL) << 56)); 1153 } 1154 1155 @Override enableAliasing(boolean enabled)1156 public void enableAliasing(boolean enabled) { 1157 this.enableAliasing = enabled; 1158 } 1159 1160 @Override resetSizeCounter()1161 public void resetSizeCounter() { 1162 startPos = pos; 1163 } 1164 1165 @Override pushLimit(int byteLimit)1166 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { 1167 if (byteLimit < 0) { 1168 throw InvalidProtocolBufferException.negativeSize(); 1169 } 1170 byteLimit += getTotalBytesRead(); 1171 if (byteLimit < 0) { 1172 throw InvalidProtocolBufferException.parseFailure(); 1173 } 1174 final int oldLimit = currentLimit; 1175 if (byteLimit > oldLimit) { 1176 throw InvalidProtocolBufferException.truncatedMessage(); 1177 } 1178 currentLimit = byteLimit; 1179 1180 recomputeBufferSizeAfterLimit(); 1181 1182 return oldLimit; 1183 } 1184 recomputeBufferSizeAfterLimit()1185 private void recomputeBufferSizeAfterLimit() { 1186 limit += bufferSizeAfterLimit; 1187 final int bufferEnd = limit - startPos; 1188 if (bufferEnd > currentLimit) { 1189 // Limit is in current buffer. 1190 bufferSizeAfterLimit = bufferEnd - currentLimit; 1191 limit -= bufferSizeAfterLimit; 1192 } else { 1193 bufferSizeAfterLimit = 0; 1194 } 1195 } 1196 1197 @Override popLimit(final int oldLimit)1198 public void popLimit(final int oldLimit) { 1199 currentLimit = oldLimit; 1200 recomputeBufferSizeAfterLimit(); 1201 } 1202 1203 @Override getBytesUntilLimit()1204 public int getBytesUntilLimit() { 1205 if (currentLimit == Integer.MAX_VALUE) { 1206 return -1; 1207 } 1208 1209 return currentLimit - getTotalBytesRead(); 1210 } 1211 1212 @Override isAtEnd()1213 public boolean isAtEnd() throws IOException { 1214 return pos == limit; 1215 } 1216 1217 @Override getTotalBytesRead()1218 public int getTotalBytesRead() { 1219 return pos - startPos; 1220 } 1221 1222 @Override readRawByte()1223 public byte readRawByte() throws IOException { 1224 if (pos == limit) { 1225 throw InvalidProtocolBufferException.truncatedMessage(); 1226 } 1227 return buffer[pos++]; 1228 } 1229 1230 @Override readRawBytes(final int length)1231 public byte[] readRawBytes(final int length) throws IOException { 1232 if (length > 0 && length <= (limit - pos)) { 1233 final int tempPos = pos; 1234 pos += length; 1235 return Arrays.copyOfRange(buffer, tempPos, pos); 1236 } 1237 1238 if (length <= 0) { 1239 if (length == 0) { 1240 return Internal.EMPTY_BYTE_ARRAY; 1241 } else { 1242 throw InvalidProtocolBufferException.negativeSize(); 1243 } 1244 } 1245 throw InvalidProtocolBufferException.truncatedMessage(); 1246 } 1247 1248 @Override skipRawBytes(final int length)1249 public void skipRawBytes(final int length) throws IOException { 1250 if (length >= 0 && length <= (limit - pos)) { 1251 // We have all the bytes we need already. 1252 pos += length; 1253 return; 1254 } 1255 1256 if (length < 0) { 1257 throw InvalidProtocolBufferException.negativeSize(); 1258 } 1259 throw InvalidProtocolBufferException.truncatedMessage(); 1260 } 1261 } 1262 1263 /** 1264 * A {@link CodedInputStream} implementation that uses a backing direct ByteBuffer as the input. 1265 * Requires the use of {@code sun.misc.Unsafe} to perform fast reads on the buffer. 1266 */ 1267 private static final class UnsafeDirectNioDecoder extends CodedInputStream { 1268 /** The direct buffer that is backing this stream. */ 1269 private final ByteBuffer buffer; 1270 1271 /** 1272 * If {@code true}, indicates that the buffer is backing a {@link ByteString} and is therefore 1273 * considered to be an immutable input source. 1274 */ 1275 private final boolean immutable; 1276 1277 /** The unsafe address of the content of {@link #buffer}. */ 1278 private final long address; 1279 1280 /** The unsafe address of the current read limit of the buffer. */ 1281 private long limit; 1282 1283 /** The unsafe address of the current read position of the buffer. */ 1284 private long pos; 1285 1286 /** The unsafe address of the starting read position. */ 1287 private long startPos; 1288 1289 /** The amount of available data in the buffer beyond {@link #limit}. */ 1290 private int bufferSizeAfterLimit; 1291 1292 /** The last tag that was read from this stream. */ 1293 private int lastTag; 1294 1295 /** 1296 * If {@code true}, indicates that calls to read {@link ByteString} or {@code byte[]} 1297 * <strong>may</strong> return slices of the underlying buffer, rather than copies. 1298 */ 1299 private boolean enableAliasing; 1300 1301 /** The absolute position of the end of the current message. */ 1302 private int currentLimit = Integer.MAX_VALUE; 1303 isSupported()1304 static boolean isSupported() { 1305 return UnsafeUtil.hasUnsafeByteBufferOperations(); 1306 } 1307 UnsafeDirectNioDecoder(ByteBuffer buffer, boolean immutable)1308 private UnsafeDirectNioDecoder(ByteBuffer buffer, boolean immutable) { 1309 this.buffer = buffer; 1310 address = UnsafeUtil.addressOffset(buffer); 1311 limit = address + buffer.limit(); 1312 pos = address + buffer.position(); 1313 startPos = pos; 1314 this.immutable = immutable; 1315 } 1316 1317 @Override readTag()1318 public int readTag() throws IOException { 1319 if (isAtEnd()) { 1320 lastTag = 0; 1321 return 0; 1322 } 1323 1324 lastTag = readRawVarint32(); 1325 if (WireFormat.getTagFieldNumber(lastTag) == 0) { 1326 // If we actually read zero (or any tag number corresponding to field 1327 // number zero), that's not a valid tag. 1328 throw InvalidProtocolBufferException.invalidTag(); 1329 } 1330 return lastTag; 1331 } 1332 1333 @Override checkLastTagWas(final int value)1334 public void checkLastTagWas(final int value) throws InvalidProtocolBufferException { 1335 if (lastTag != value) { 1336 throw InvalidProtocolBufferException.invalidEndTag(); 1337 } 1338 } 1339 1340 @Override getLastTag()1341 public int getLastTag() { 1342 return lastTag; 1343 } 1344 1345 @Override skipField(final int tag)1346 public boolean skipField(final int tag) throws IOException { 1347 switch (WireFormat.getTagWireType(tag)) { 1348 case WireFormat.WIRETYPE_VARINT: 1349 skipRawVarint(); 1350 return true; 1351 case WireFormat.WIRETYPE_FIXED64: 1352 skipRawBytes(FIXED64_SIZE); 1353 return true; 1354 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 1355 skipRawBytes(readRawVarint32()); 1356 return true; 1357 case WireFormat.WIRETYPE_START_GROUP: 1358 skipMessage(); 1359 checkLastTagWas( 1360 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP)); 1361 return true; 1362 case WireFormat.WIRETYPE_END_GROUP: 1363 return false; 1364 case WireFormat.WIRETYPE_FIXED32: 1365 skipRawBytes(FIXED32_SIZE); 1366 return true; 1367 default: 1368 throw InvalidProtocolBufferException.invalidWireType(); 1369 } 1370 } 1371 1372 @Override skipField(final int tag, final CodedOutputStream output)1373 public boolean skipField(final int tag, final CodedOutputStream output) throws IOException { 1374 switch (WireFormat.getTagWireType(tag)) { 1375 case WireFormat.WIRETYPE_VARINT: 1376 { 1377 long value = readInt64(); 1378 output.writeUInt32NoTag(tag); 1379 output.writeUInt64NoTag(value); 1380 return true; 1381 } 1382 case WireFormat.WIRETYPE_FIXED64: 1383 { 1384 long value = readRawLittleEndian64(); 1385 output.writeUInt32NoTag(tag); 1386 output.writeFixed64NoTag(value); 1387 return true; 1388 } 1389 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 1390 { 1391 ByteString value = readBytes(); 1392 output.writeUInt32NoTag(tag); 1393 output.writeBytesNoTag(value); 1394 return true; 1395 } 1396 case WireFormat.WIRETYPE_START_GROUP: 1397 { 1398 output.writeUInt32NoTag(tag); 1399 skipMessage(output); 1400 int endtag = 1401 WireFormat.makeTag( 1402 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP); 1403 checkLastTagWas(endtag); 1404 output.writeUInt32NoTag(endtag); 1405 return true; 1406 } 1407 case WireFormat.WIRETYPE_END_GROUP: 1408 { 1409 return false; 1410 } 1411 case WireFormat.WIRETYPE_FIXED32: 1412 { 1413 int value = readRawLittleEndian32(); 1414 output.writeUInt32NoTag(tag); 1415 output.writeFixed32NoTag(value); 1416 return true; 1417 } 1418 default: 1419 throw InvalidProtocolBufferException.invalidWireType(); 1420 } 1421 } 1422 1423 // ----------------------------------------------------------------- 1424 1425 @Override readDouble()1426 public double readDouble() throws IOException { 1427 return Double.longBitsToDouble(readRawLittleEndian64()); 1428 } 1429 1430 @Override readFloat()1431 public float readFloat() throws IOException { 1432 return Float.intBitsToFloat(readRawLittleEndian32()); 1433 } 1434 1435 @Override readUInt64()1436 public long readUInt64() throws IOException { 1437 return readRawVarint64(); 1438 } 1439 1440 @Override readInt64()1441 public long readInt64() throws IOException { 1442 return readRawVarint64(); 1443 } 1444 1445 @Override readInt32()1446 public int readInt32() throws IOException { 1447 return readRawVarint32(); 1448 } 1449 1450 @Override readFixed64()1451 public long readFixed64() throws IOException { 1452 return readRawLittleEndian64(); 1453 } 1454 1455 @Override readFixed32()1456 public int readFixed32() throws IOException { 1457 return readRawLittleEndian32(); 1458 } 1459 1460 @Override readBool()1461 public boolean readBool() throws IOException { 1462 return readRawVarint64() != 0; 1463 } 1464 1465 @Override readString()1466 public String readString() throws IOException { 1467 final int size = readRawVarint32(); 1468 if (size > 0 && size <= remaining()) { 1469 // TODO: Is there a way to avoid this copy? 1470 // TODO: It might be possible to share the optimized loop with 1471 // readStringRequireUtf8 by implementing Java replacement logic there. 1472 // The same as readBytes' logic 1473 byte[] bytes = new byte[size]; 1474 UnsafeUtil.copyMemory(pos, bytes, 0, size); 1475 String result = new String(bytes, UTF_8); 1476 pos += size; 1477 return result; 1478 } 1479 1480 if (size == 0) { 1481 return ""; 1482 } 1483 if (size < 0) { 1484 throw InvalidProtocolBufferException.negativeSize(); 1485 } 1486 throw InvalidProtocolBufferException.truncatedMessage(); 1487 } 1488 1489 @Override readStringRequireUtf8()1490 public String readStringRequireUtf8() throws IOException { 1491 final int size = readRawVarint32(); 1492 if (size > 0 && size <= remaining()) { 1493 final int bufferPos = bufferPos(pos); 1494 String result = Utf8.decodeUtf8(buffer, bufferPos, size); 1495 pos += size; 1496 return result; 1497 } 1498 1499 if (size == 0) { 1500 return ""; 1501 } 1502 if (size <= 0) { 1503 throw InvalidProtocolBufferException.negativeSize(); 1504 } 1505 throw InvalidProtocolBufferException.truncatedMessage(); 1506 } 1507 1508 @Override readGroup( final int fieldNumber, final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)1509 public void readGroup( 1510 final int fieldNumber, 1511 final MessageLite.Builder builder, 1512 final ExtensionRegistryLite extensionRegistry) 1513 throws IOException { 1514 checkRecursionLimit(); 1515 ++recursionDepth; 1516 builder.mergeFrom(this, extensionRegistry); 1517 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); 1518 --recursionDepth; 1519 } 1520 1521 @Override readGroup( final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)1522 public <T extends MessageLite> T readGroup( 1523 final int fieldNumber, 1524 final Parser<T> parser, 1525 final ExtensionRegistryLite extensionRegistry) 1526 throws IOException { 1527 checkRecursionLimit(); 1528 ++recursionDepth; 1529 T result = parser.parsePartialFrom(this, extensionRegistry); 1530 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); 1531 --recursionDepth; 1532 return result; 1533 } 1534 1535 @Deprecated 1536 @Override readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)1537 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder) 1538 throws IOException { 1539 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry()); 1540 } 1541 1542 @Override readMessage( final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)1543 public void readMessage( 1544 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry) 1545 throws IOException { 1546 final int length = readRawVarint32(); 1547 checkRecursionLimit(); 1548 final int oldLimit = pushLimit(length); 1549 ++recursionDepth; 1550 builder.mergeFrom(this, extensionRegistry); 1551 checkLastTagWas(0); 1552 --recursionDepth; 1553 if (getBytesUntilLimit() != 0) { 1554 throw InvalidProtocolBufferException.truncatedMessage(); 1555 } 1556 popLimit(oldLimit); 1557 } 1558 1559 @Override readMessage( final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)1560 public <T extends MessageLite> T readMessage( 1561 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException { 1562 int length = readRawVarint32(); 1563 checkRecursionLimit(); 1564 final int oldLimit = pushLimit(length); 1565 ++recursionDepth; 1566 T result = parser.parsePartialFrom(this, extensionRegistry); 1567 checkLastTagWas(0); 1568 --recursionDepth; 1569 if (getBytesUntilLimit() != 0) { 1570 throw InvalidProtocolBufferException.truncatedMessage(); 1571 } 1572 popLimit(oldLimit); 1573 return result; 1574 } 1575 1576 @Override readBytes()1577 public ByteString readBytes() throws IOException { 1578 final int size = readRawVarint32(); 1579 if (size > 0 && size <= remaining()) { 1580 if (immutable && enableAliasing) { 1581 final ByteBuffer result = slice(pos, pos + size); 1582 pos += size; 1583 return ByteString.wrap(result); 1584 } else { 1585 // Use UnsafeUtil to copy the memory to bytes instead of using ByteBuffer ways. 1586 byte[] bytes = new byte[size]; 1587 UnsafeUtil.copyMemory(pos, bytes, 0, size); 1588 pos += size; 1589 return ByteString.wrap(bytes); 1590 } 1591 } 1592 1593 if (size == 0) { 1594 return ByteString.EMPTY; 1595 } 1596 if (size < 0) { 1597 throw InvalidProtocolBufferException.negativeSize(); 1598 } 1599 throw InvalidProtocolBufferException.truncatedMessage(); 1600 } 1601 1602 @Override readByteArray()1603 public byte[] readByteArray() throws IOException { 1604 return readRawBytes(readRawVarint32()); 1605 } 1606 1607 @Override readByteBuffer()1608 public ByteBuffer readByteBuffer() throws IOException { 1609 final int size = readRawVarint32(); 1610 if (size > 0 && size <= remaining()) { 1611 // "Immutable" implies that buffer is backing a ByteString. 1612 // Disallow slicing in this case to prevent the caller from modifying the contents 1613 // of the ByteString. 1614 if (!immutable && enableAliasing) { 1615 final ByteBuffer result = slice(pos, pos + size); 1616 pos += size; 1617 return result; 1618 } else { 1619 // The same as readBytes' logic 1620 byte[] bytes = new byte[size]; 1621 UnsafeUtil.copyMemory(pos, bytes, 0, size); 1622 pos += size; 1623 return ByteBuffer.wrap(bytes); 1624 } 1625 // TODO: Investigate making the ByteBuffer be made read-only 1626 } 1627 1628 if (size == 0) { 1629 return EMPTY_BYTE_BUFFER; 1630 } 1631 if (size < 0) { 1632 throw InvalidProtocolBufferException.negativeSize(); 1633 } 1634 throw InvalidProtocolBufferException.truncatedMessage(); 1635 } 1636 1637 @Override readUInt32()1638 public int readUInt32() throws IOException { 1639 return readRawVarint32(); 1640 } 1641 1642 @Override readEnum()1643 public int readEnum() throws IOException { 1644 return readRawVarint32(); 1645 } 1646 1647 @Override readSFixed32()1648 public int readSFixed32() throws IOException { 1649 return readRawLittleEndian32(); 1650 } 1651 1652 @Override readSFixed64()1653 public long readSFixed64() throws IOException { 1654 return readRawLittleEndian64(); 1655 } 1656 1657 @Override readSInt32()1658 public int readSInt32() throws IOException { 1659 return decodeZigZag32(readRawVarint32()); 1660 } 1661 1662 @Override readSInt64()1663 public long readSInt64() throws IOException { 1664 return decodeZigZag64(readRawVarint64()); 1665 } 1666 1667 // ================================================================= 1668 1669 @Override readRawVarint32()1670 public int readRawVarint32() throws IOException { 1671 // See implementation notes for readRawVarint64 1672 fastpath: 1673 { 1674 long tempPos = pos; 1675 1676 if (limit == tempPos) { 1677 break fastpath; 1678 } 1679 1680 int x; 1681 if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) { 1682 pos = tempPos; 1683 return x; 1684 } else if (limit - tempPos < 9) { 1685 break fastpath; 1686 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) { 1687 x ^= (~0 << 7); 1688 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) { 1689 x ^= (~0 << 7) ^ (~0 << 14); 1690 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) { 1691 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21); 1692 } else { 1693 int y = UnsafeUtil.getByte(tempPos++); 1694 x ^= y << 28; 1695 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28); 1696 if (y < 0 1697 && UnsafeUtil.getByte(tempPos++) < 0 1698 && UnsafeUtil.getByte(tempPos++) < 0 1699 && UnsafeUtil.getByte(tempPos++) < 0 1700 && UnsafeUtil.getByte(tempPos++) < 0 1701 && UnsafeUtil.getByte(tempPos++) < 0) { 1702 break fastpath; // Will throw malformedVarint() 1703 } 1704 } 1705 pos = tempPos; 1706 return x; 1707 } 1708 return (int) readRawVarint64SlowPath(); 1709 } 1710 skipRawVarint()1711 private void skipRawVarint() throws IOException { 1712 if (remaining() >= MAX_VARINT_SIZE) { 1713 skipRawVarintFastPath(); 1714 } else { 1715 skipRawVarintSlowPath(); 1716 } 1717 } 1718 skipRawVarintFastPath()1719 private void skipRawVarintFastPath() throws IOException { 1720 for (int i = 0; i < MAX_VARINT_SIZE; i++) { 1721 if (UnsafeUtil.getByte(pos++) >= 0) { 1722 return; 1723 } 1724 } 1725 throw InvalidProtocolBufferException.malformedVarint(); 1726 } 1727 skipRawVarintSlowPath()1728 private void skipRawVarintSlowPath() throws IOException { 1729 for (int i = 0; i < MAX_VARINT_SIZE; i++) { 1730 if (readRawByte() >= 0) { 1731 return; 1732 } 1733 } 1734 throw InvalidProtocolBufferException.malformedVarint(); 1735 } 1736 1737 @Override readRawVarint64()1738 public long readRawVarint64() throws IOException { 1739 // Implementation notes: 1740 // 1741 // Optimized for one-byte values, expected to be common. 1742 // The particular code below was selected from various candidates 1743 // empirically, by winning VarintBenchmark. 1744 // 1745 // Sign extension of (signed) Java bytes is usually a nuisance, but 1746 // we exploit it here to more easily obtain the sign of bytes read. 1747 // Instead of cleaning up the sign extension bits by masking eagerly, 1748 // we delay until we find the final (positive) byte, when we clear all 1749 // accumulated bits with one xor. We depend on javac to constant fold. 1750 fastpath: 1751 { 1752 long tempPos = pos; 1753 1754 if (limit == tempPos) { 1755 break fastpath; 1756 } 1757 1758 long x; 1759 int y; 1760 if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) { 1761 pos = tempPos; 1762 return y; 1763 } else if (limit - tempPos < 9) { 1764 break fastpath; 1765 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) { 1766 x = y ^ (~0 << 7); 1767 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) { 1768 x = y ^ ((~0 << 7) ^ (~0 << 14)); 1769 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) { 1770 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21)); 1771 } else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) { 1772 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28); 1773 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) { 1774 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35); 1775 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) { 1776 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42); 1777 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) { 1778 x ^= 1779 (~0L << 7) 1780 ^ (~0L << 14) 1781 ^ (~0L << 21) 1782 ^ (~0L << 28) 1783 ^ (~0L << 35) 1784 ^ (~0L << 42) 1785 ^ (~0L << 49); 1786 } else { 1787 x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56); 1788 x ^= 1789 (~0L << 7) 1790 ^ (~0L << 14) 1791 ^ (~0L << 21) 1792 ^ (~0L << 28) 1793 ^ (~0L << 35) 1794 ^ (~0L << 42) 1795 ^ (~0L << 49) 1796 ^ (~0L << 56); 1797 if (x < 0L) { 1798 if (UnsafeUtil.getByte(tempPos++) < 0L) { 1799 break fastpath; // Will throw malformedVarint() 1800 } 1801 } 1802 } 1803 pos = tempPos; 1804 return x; 1805 } 1806 return readRawVarint64SlowPath(); 1807 } 1808 1809 @Override readRawVarint64SlowPath()1810 long readRawVarint64SlowPath() throws IOException { 1811 long result = 0; 1812 for (int shift = 0; shift < 64; shift += 7) { 1813 final byte b = readRawByte(); 1814 result |= (long) (b & 0x7F) << shift; 1815 if ((b & 0x80) == 0) { 1816 return result; 1817 } 1818 } 1819 throw InvalidProtocolBufferException.malformedVarint(); 1820 } 1821 1822 @Override readRawLittleEndian32()1823 public int readRawLittleEndian32() throws IOException { 1824 long tempPos = pos; 1825 1826 if (limit - tempPos < FIXED32_SIZE) { 1827 throw InvalidProtocolBufferException.truncatedMessage(); 1828 } 1829 1830 pos = tempPos + FIXED32_SIZE; 1831 return ((UnsafeUtil.getByte(tempPos) & 0xff) 1832 | ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8) 1833 | ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16) 1834 | ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24)); 1835 } 1836 1837 @Override readRawLittleEndian64()1838 public long readRawLittleEndian64() throws IOException { 1839 long tempPos = pos; 1840 1841 if (limit - tempPos < FIXED64_SIZE) { 1842 throw InvalidProtocolBufferException.truncatedMessage(); 1843 } 1844 1845 pos = tempPos + FIXED64_SIZE; 1846 return ((UnsafeUtil.getByte(tempPos) & 0xffL) 1847 | ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8) 1848 | ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16) 1849 | ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24) 1850 | ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32) 1851 | ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40) 1852 | ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48) 1853 | ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56)); 1854 } 1855 1856 @Override enableAliasing(boolean enabled)1857 public void enableAliasing(boolean enabled) { 1858 this.enableAliasing = enabled; 1859 } 1860 1861 @Override resetSizeCounter()1862 public void resetSizeCounter() { 1863 startPos = pos; 1864 } 1865 1866 @Override pushLimit(int byteLimit)1867 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { 1868 if (byteLimit < 0) { 1869 throw InvalidProtocolBufferException.negativeSize(); 1870 } 1871 byteLimit += getTotalBytesRead(); 1872 final int oldLimit = currentLimit; 1873 if (byteLimit > oldLimit) { 1874 throw InvalidProtocolBufferException.truncatedMessage(); 1875 } 1876 currentLimit = byteLimit; 1877 1878 recomputeBufferSizeAfterLimit(); 1879 1880 return oldLimit; 1881 } 1882 1883 @Override popLimit(final int oldLimit)1884 public void popLimit(final int oldLimit) { 1885 currentLimit = oldLimit; 1886 recomputeBufferSizeAfterLimit(); 1887 } 1888 1889 @Override getBytesUntilLimit()1890 public int getBytesUntilLimit() { 1891 if (currentLimit == Integer.MAX_VALUE) { 1892 return -1; 1893 } 1894 1895 return currentLimit - getTotalBytesRead(); 1896 } 1897 1898 @Override isAtEnd()1899 public boolean isAtEnd() throws IOException { 1900 return pos == limit; 1901 } 1902 1903 @Override getTotalBytesRead()1904 public int getTotalBytesRead() { 1905 return (int) (pos - startPos); 1906 } 1907 1908 @Override readRawByte()1909 public byte readRawByte() throws IOException { 1910 if (pos == limit) { 1911 throw InvalidProtocolBufferException.truncatedMessage(); 1912 } 1913 return UnsafeUtil.getByte(pos++); 1914 } 1915 1916 @Override readRawBytes(final int length)1917 public byte[] readRawBytes(final int length) throws IOException { 1918 if (length >= 0 && length <= remaining()) { 1919 byte[] bytes = new byte[length]; 1920 slice(pos, pos + length).get(bytes); 1921 pos += length; 1922 return bytes; 1923 } 1924 1925 if (length <= 0) { 1926 if (length == 0) { 1927 return EMPTY_BYTE_ARRAY; 1928 } else { 1929 throw InvalidProtocolBufferException.negativeSize(); 1930 } 1931 } 1932 1933 throw InvalidProtocolBufferException.truncatedMessage(); 1934 } 1935 1936 @Override skipRawBytes(final int length)1937 public void skipRawBytes(final int length) throws IOException { 1938 if (length >= 0 && length <= remaining()) { 1939 // We have all the bytes we need already. 1940 pos += length; 1941 return; 1942 } 1943 1944 if (length < 0) { 1945 throw InvalidProtocolBufferException.negativeSize(); 1946 } 1947 throw InvalidProtocolBufferException.truncatedMessage(); 1948 } 1949 recomputeBufferSizeAfterLimit()1950 private void recomputeBufferSizeAfterLimit() { 1951 limit += bufferSizeAfterLimit; 1952 final int bufferEnd = (int) (limit - startPos); 1953 if (bufferEnd > currentLimit) { 1954 // Limit is in current buffer. 1955 bufferSizeAfterLimit = bufferEnd - currentLimit; 1956 limit -= bufferSizeAfterLimit; 1957 } else { 1958 bufferSizeAfterLimit = 0; 1959 } 1960 } 1961 remaining()1962 private int remaining() { 1963 return (int) (limit - pos); 1964 } 1965 bufferPos(long pos)1966 private int bufferPos(long pos) { 1967 return (int) (pos - address); 1968 } 1969 slice(long begin, long end)1970 private ByteBuffer slice(long begin, long end) throws IOException { 1971 int prevPos = buffer.position(); 1972 int prevLimit = buffer.limit(); 1973 // View ByteBuffer as Buffer to avoid cross-Java version issues. 1974 // See https://issues.apache.org/jira/browse/MRESOLVER-85 1975 Buffer asBuffer = buffer; 1976 try { 1977 asBuffer.position(bufferPos(begin)); 1978 asBuffer.limit(bufferPos(end)); 1979 return buffer.slice(); 1980 } catch (IllegalArgumentException e) { 1981 InvalidProtocolBufferException ex = InvalidProtocolBufferException.truncatedMessage(); 1982 ex.initCause(e); 1983 throw ex; 1984 } finally { 1985 asBuffer.position(prevPos); 1986 asBuffer.limit(prevLimit); 1987 } 1988 } 1989 } 1990 1991 /** 1992 * Implementation of {@link CodedInputStream} that uses an {@link InputStream} as the data source. 1993 */ 1994 private static final class StreamDecoder extends CodedInputStream { 1995 private final InputStream input; 1996 private final byte[] buffer; 1997 1998 /** bufferSize represents how many bytes are currently filled in the buffer */ 1999 private int bufferSize; 2000 2001 private int bufferSizeAfterLimit; 2002 private int pos; 2003 private int lastTag; 2004 2005 /** 2006 * The total number of bytes read before the current buffer. The total bytes read up to the 2007 * current position can be computed as {@code totalBytesRetired + pos}. This value may be 2008 * negative if reading started in the middle of the current buffer (e.g. if the constructor that 2009 * takes a byte array and an offset was used). 2010 */ 2011 private int totalBytesRetired; 2012 2013 /** The absolute position of the end of the current message. */ 2014 private int currentLimit = Integer.MAX_VALUE; 2015 StreamDecoder(final InputStream input, int bufferSize)2016 private StreamDecoder(final InputStream input, int bufferSize) { 2017 checkNotNull(input, "input"); 2018 this.input = input; 2019 this.buffer = new byte[bufferSize]; 2020 this.bufferSize = 0; 2021 pos = 0; 2022 totalBytesRetired = 0; 2023 } 2024 2025 /* 2026 * The following wrapper methods exist so that InvalidProtocolBufferExceptions thrown by the 2027 * InputStream can be differentiated from ones thrown by CodedInputStream itself. Each call to 2028 * an InputStream method that can throw IOException must be wrapped like this. We do this 2029 * because we sometimes need to modify IPBE instances after they are thrown far away from where 2030 * they are thrown (ex. to add unfinished messages) and we use this signal elsewhere in the 2031 * exception catch chain to know when to perform these operations directly or to wrap the 2032 * exception in their own IPBE so the extra information can be communicated without trampling 2033 * downstream information. 2034 */ read(InputStream input, byte[] data, int offset, int length)2035 private static int read(InputStream input, byte[] data, int offset, int length) 2036 throws IOException { 2037 try { 2038 return input.read(data, offset, length); 2039 } catch (InvalidProtocolBufferException e) { 2040 e.setThrownFromInputStream(); 2041 throw e; 2042 } 2043 } 2044 skip(InputStream input, long length)2045 private static long skip(InputStream input, long length) throws IOException { 2046 try { 2047 return input.skip(length); 2048 } catch (InvalidProtocolBufferException e) { 2049 e.setThrownFromInputStream(); 2050 throw e; 2051 } 2052 } 2053 available(InputStream input)2054 private static int available(InputStream input) throws IOException { 2055 try { 2056 return input.available(); 2057 } catch (InvalidProtocolBufferException e) { 2058 e.setThrownFromInputStream(); 2059 throw e; 2060 } 2061 } 2062 2063 @Override readTag()2064 public int readTag() throws IOException { 2065 if (isAtEnd()) { 2066 lastTag = 0; 2067 return 0; 2068 } 2069 2070 lastTag = readRawVarint32(); 2071 if (WireFormat.getTagFieldNumber(lastTag) == 0) { 2072 // If we actually read zero (or any tag number corresponding to field 2073 // number zero), that's not a valid tag. 2074 throw InvalidProtocolBufferException.invalidTag(); 2075 } 2076 return lastTag; 2077 } 2078 2079 @Override checkLastTagWas(final int value)2080 public void checkLastTagWas(final int value) throws InvalidProtocolBufferException { 2081 if (lastTag != value) { 2082 throw InvalidProtocolBufferException.invalidEndTag(); 2083 } 2084 } 2085 2086 @Override getLastTag()2087 public int getLastTag() { 2088 return lastTag; 2089 } 2090 2091 @Override skipField(final int tag)2092 public boolean skipField(final int tag) throws IOException { 2093 switch (WireFormat.getTagWireType(tag)) { 2094 case WireFormat.WIRETYPE_VARINT: 2095 skipRawVarint(); 2096 return true; 2097 case WireFormat.WIRETYPE_FIXED64: 2098 skipRawBytes(FIXED64_SIZE); 2099 return true; 2100 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 2101 skipRawBytes(readRawVarint32()); 2102 return true; 2103 case WireFormat.WIRETYPE_START_GROUP: 2104 skipMessage(); 2105 checkLastTagWas( 2106 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP)); 2107 return true; 2108 case WireFormat.WIRETYPE_END_GROUP: 2109 return false; 2110 case WireFormat.WIRETYPE_FIXED32: 2111 skipRawBytes(FIXED32_SIZE); 2112 return true; 2113 default: 2114 throw InvalidProtocolBufferException.invalidWireType(); 2115 } 2116 } 2117 2118 @Override skipField(final int tag, final CodedOutputStream output)2119 public boolean skipField(final int tag, final CodedOutputStream output) throws IOException { 2120 switch (WireFormat.getTagWireType(tag)) { 2121 case WireFormat.WIRETYPE_VARINT: 2122 { 2123 long value = readInt64(); 2124 output.writeUInt32NoTag(tag); 2125 output.writeUInt64NoTag(value); 2126 return true; 2127 } 2128 case WireFormat.WIRETYPE_FIXED64: 2129 { 2130 long value = readRawLittleEndian64(); 2131 output.writeUInt32NoTag(tag); 2132 output.writeFixed64NoTag(value); 2133 return true; 2134 } 2135 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 2136 { 2137 ByteString value = readBytes(); 2138 output.writeUInt32NoTag(tag); 2139 output.writeBytesNoTag(value); 2140 return true; 2141 } 2142 case WireFormat.WIRETYPE_START_GROUP: 2143 { 2144 output.writeUInt32NoTag(tag); 2145 skipMessage(output); 2146 int endtag = 2147 WireFormat.makeTag( 2148 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP); 2149 checkLastTagWas(endtag); 2150 output.writeUInt32NoTag(endtag); 2151 return true; 2152 } 2153 case WireFormat.WIRETYPE_END_GROUP: 2154 { 2155 return false; 2156 } 2157 case WireFormat.WIRETYPE_FIXED32: 2158 { 2159 int value = readRawLittleEndian32(); 2160 output.writeUInt32NoTag(tag); 2161 output.writeFixed32NoTag(value); 2162 return true; 2163 } 2164 default: 2165 throw InvalidProtocolBufferException.invalidWireType(); 2166 } 2167 } 2168 2169 /** Collects the bytes skipped and returns the data in a ByteBuffer. */ 2170 private class SkippedDataSink implements RefillCallback { 2171 private int lastPos = pos; 2172 private ByteArrayOutputStream byteArrayStream; 2173 2174 @Override onRefill()2175 public void onRefill() { 2176 if (byteArrayStream == null) { 2177 byteArrayStream = new ByteArrayOutputStream(); 2178 } 2179 byteArrayStream.write(buffer, lastPos, pos - lastPos); 2180 lastPos = 0; 2181 } 2182 2183 /** Gets skipped data in a ByteBuffer. This method should only be called once. */ getSkippedData()2184 ByteBuffer getSkippedData() { 2185 if (byteArrayStream == null) { 2186 return ByteBuffer.wrap(buffer, lastPos, pos - lastPos); 2187 } else { 2188 byteArrayStream.write(buffer, lastPos, pos); 2189 return ByteBuffer.wrap(byteArrayStream.toByteArray()); 2190 } 2191 } 2192 } 2193 2194 // ----------------------------------------------------------------- 2195 2196 @Override readDouble()2197 public double readDouble() throws IOException { 2198 return Double.longBitsToDouble(readRawLittleEndian64()); 2199 } 2200 2201 @Override readFloat()2202 public float readFloat() throws IOException { 2203 return Float.intBitsToFloat(readRawLittleEndian32()); 2204 } 2205 2206 @Override readUInt64()2207 public long readUInt64() throws IOException { 2208 return readRawVarint64(); 2209 } 2210 2211 @Override readInt64()2212 public long readInt64() throws IOException { 2213 return readRawVarint64(); 2214 } 2215 2216 @Override readInt32()2217 public int readInt32() throws IOException { 2218 return readRawVarint32(); 2219 } 2220 2221 @Override readFixed64()2222 public long readFixed64() throws IOException { 2223 return readRawLittleEndian64(); 2224 } 2225 2226 @Override readFixed32()2227 public int readFixed32() throws IOException { 2228 return readRawLittleEndian32(); 2229 } 2230 2231 @Override readBool()2232 public boolean readBool() throws IOException { 2233 return readRawVarint64() != 0; 2234 } 2235 2236 @Override readString()2237 public String readString() throws IOException { 2238 final int size = readRawVarint32(); 2239 if (size > 0 && size <= (bufferSize - pos)) { 2240 // Fast path: We already have the bytes in a contiguous buffer, so 2241 // just copy directly from it. 2242 final String result = new String(buffer, pos, size, UTF_8); 2243 pos += size; 2244 return result; 2245 } 2246 if (size == 0) { 2247 return ""; 2248 } 2249 if (size < 0) { 2250 throw InvalidProtocolBufferException.negativeSize(); 2251 } 2252 if (size <= bufferSize) { 2253 refillBuffer(size); 2254 String result = new String(buffer, pos, size, UTF_8); 2255 pos += size; 2256 return result; 2257 } 2258 // Slow path: Build a byte array first then copy it. 2259 return new String(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false), UTF_8); 2260 } 2261 2262 @Override readStringRequireUtf8()2263 public String readStringRequireUtf8() throws IOException { 2264 final int size = readRawVarint32(); 2265 final byte[] bytes; 2266 final int oldPos = pos; 2267 final int tempPos; 2268 if (size <= (bufferSize - oldPos) && size > 0) { 2269 // Fast path: We already have the bytes in a contiguous buffer, so 2270 // just copy directly from it. 2271 bytes = buffer; 2272 pos = oldPos + size; 2273 tempPos = oldPos; 2274 } else if (size == 0) { 2275 return ""; 2276 } else if (size < 0) { 2277 throw InvalidProtocolBufferException.negativeSize(); 2278 } else if (size <= bufferSize) { 2279 refillBuffer(size); 2280 bytes = buffer; 2281 tempPos = 0; 2282 pos = tempPos + size; 2283 } else { 2284 // Slow path: Build a byte array first then copy it. 2285 bytes = readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false); 2286 tempPos = 0; 2287 } 2288 return Utf8.decodeUtf8(bytes, tempPos, size); 2289 } 2290 2291 @Override readGroup( final int fieldNumber, final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)2292 public void readGroup( 2293 final int fieldNumber, 2294 final MessageLite.Builder builder, 2295 final ExtensionRegistryLite extensionRegistry) 2296 throws IOException { 2297 checkRecursionLimit(); 2298 ++recursionDepth; 2299 builder.mergeFrom(this, extensionRegistry); 2300 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); 2301 --recursionDepth; 2302 } 2303 2304 @Override readGroup( final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)2305 public <T extends MessageLite> T readGroup( 2306 final int fieldNumber, 2307 final Parser<T> parser, 2308 final ExtensionRegistryLite extensionRegistry) 2309 throws IOException { 2310 checkRecursionLimit(); 2311 ++recursionDepth; 2312 T result = parser.parsePartialFrom(this, extensionRegistry); 2313 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); 2314 --recursionDepth; 2315 return result; 2316 } 2317 2318 @Deprecated 2319 @Override readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)2320 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder) 2321 throws IOException { 2322 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry()); 2323 } 2324 2325 @Override readMessage( final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)2326 public void readMessage( 2327 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry) 2328 throws IOException { 2329 final int length = readRawVarint32(); 2330 checkRecursionLimit(); 2331 final int oldLimit = pushLimit(length); 2332 ++recursionDepth; 2333 builder.mergeFrom(this, extensionRegistry); 2334 checkLastTagWas(0); 2335 --recursionDepth; 2336 if (getBytesUntilLimit() != 0) { 2337 throw InvalidProtocolBufferException.truncatedMessage(); 2338 } 2339 popLimit(oldLimit); 2340 } 2341 2342 @Override readMessage( final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)2343 public <T extends MessageLite> T readMessage( 2344 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException { 2345 int length = readRawVarint32(); 2346 checkRecursionLimit(); 2347 final int oldLimit = pushLimit(length); 2348 ++recursionDepth; 2349 T result = parser.parsePartialFrom(this, extensionRegistry); 2350 checkLastTagWas(0); 2351 --recursionDepth; 2352 if (getBytesUntilLimit() != 0) { 2353 throw InvalidProtocolBufferException.truncatedMessage(); 2354 } 2355 popLimit(oldLimit); 2356 return result; 2357 } 2358 2359 @Override readBytes()2360 public ByteString readBytes() throws IOException { 2361 final int size = readRawVarint32(); 2362 if (size <= (bufferSize - pos) && size > 0) { 2363 // Fast path: We already have the bytes in a contiguous buffer, so 2364 // just copy directly from it. 2365 final ByteString result = ByteString.copyFrom(buffer, pos, size); 2366 pos += size; 2367 return result; 2368 } 2369 if (size == 0) { 2370 return ByteString.EMPTY; 2371 } 2372 if (size < 0) { 2373 throw InvalidProtocolBufferException.negativeSize(); 2374 } 2375 return readBytesSlowPath(size); 2376 } 2377 2378 @Override readByteArray()2379 public byte[] readByteArray() throws IOException { 2380 final int size = readRawVarint32(); 2381 if (size <= (bufferSize - pos) && size > 0) { 2382 // Fast path: We already have the bytes in a contiguous buffer, so 2383 // just copy directly from it. 2384 final byte[] result = Arrays.copyOfRange(buffer, pos, pos + size); 2385 pos += size; 2386 return result; 2387 } else if (size < 0) { 2388 throw InvalidProtocolBufferException.negativeSize(); 2389 } else { 2390 // Slow path: Build a byte array first then copy it. 2391 // TODO: Do we want to protect from malicious input streams here? 2392 return readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false); 2393 } 2394 } 2395 2396 @Override readByteBuffer()2397 public ByteBuffer readByteBuffer() throws IOException { 2398 final int size = readRawVarint32(); 2399 if (size <= (bufferSize - pos) && size > 0) { 2400 // Fast path: We already have the bytes in a contiguous buffer. 2401 ByteBuffer result = ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size)); 2402 pos += size; 2403 return result; 2404 } 2405 if (size == 0) { 2406 return Internal.EMPTY_BYTE_BUFFER; 2407 } 2408 if (size < 0) { 2409 throw InvalidProtocolBufferException.negativeSize(); 2410 } 2411 // Slow path: Build a byte array first then copy it. 2412 2413 // We must copy as the byte array was handed off to the InputStream and a malicious 2414 // implementation could retain a reference. 2415 return ByteBuffer.wrap(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ true)); 2416 } 2417 2418 @Override readUInt32()2419 public int readUInt32() throws IOException { 2420 return readRawVarint32(); 2421 } 2422 2423 @Override readEnum()2424 public int readEnum() throws IOException { 2425 return readRawVarint32(); 2426 } 2427 2428 @Override readSFixed32()2429 public int readSFixed32() throws IOException { 2430 return readRawLittleEndian32(); 2431 } 2432 2433 @Override readSFixed64()2434 public long readSFixed64() throws IOException { 2435 return readRawLittleEndian64(); 2436 } 2437 2438 @Override readSInt32()2439 public int readSInt32() throws IOException { 2440 return decodeZigZag32(readRawVarint32()); 2441 } 2442 2443 @Override readSInt64()2444 public long readSInt64() throws IOException { 2445 return decodeZigZag64(readRawVarint64()); 2446 } 2447 2448 // ================================================================= 2449 2450 @Override readRawVarint32()2451 public int readRawVarint32() throws IOException { 2452 // See implementation notes for readRawVarint64 2453 fastpath: 2454 { 2455 int tempPos = pos; 2456 2457 if (bufferSize == tempPos) { 2458 break fastpath; 2459 } 2460 2461 final byte[] buffer = this.buffer; 2462 int x; 2463 if ((x = buffer[tempPos++]) >= 0) { 2464 pos = tempPos; 2465 return x; 2466 } else if (bufferSize - tempPos < 9) { 2467 break fastpath; 2468 } else if ((x ^= (buffer[tempPos++] << 7)) < 0) { 2469 x ^= (~0 << 7); 2470 } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) { 2471 x ^= (~0 << 7) ^ (~0 << 14); 2472 } else if ((x ^= (buffer[tempPos++] << 21)) < 0) { 2473 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21); 2474 } else { 2475 int y = buffer[tempPos++]; 2476 x ^= y << 28; 2477 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28); 2478 if (y < 0 2479 && buffer[tempPos++] < 0 2480 && buffer[tempPos++] < 0 2481 && buffer[tempPos++] < 0 2482 && buffer[tempPos++] < 0 2483 && buffer[tempPos++] < 0) { 2484 break fastpath; // Will throw malformedVarint() 2485 } 2486 } 2487 pos = tempPos; 2488 return x; 2489 } 2490 return (int) readRawVarint64SlowPath(); 2491 } 2492 skipRawVarint()2493 private void skipRawVarint() throws IOException { 2494 if (bufferSize - pos >= MAX_VARINT_SIZE) { 2495 skipRawVarintFastPath(); 2496 } else { 2497 skipRawVarintSlowPath(); 2498 } 2499 } 2500 skipRawVarintFastPath()2501 private void skipRawVarintFastPath() throws IOException { 2502 for (int i = 0; i < MAX_VARINT_SIZE; i++) { 2503 if (buffer[pos++] >= 0) { 2504 return; 2505 } 2506 } 2507 throw InvalidProtocolBufferException.malformedVarint(); 2508 } 2509 skipRawVarintSlowPath()2510 private void skipRawVarintSlowPath() throws IOException { 2511 for (int i = 0; i < MAX_VARINT_SIZE; i++) { 2512 if (readRawByte() >= 0) { 2513 return; 2514 } 2515 } 2516 throw InvalidProtocolBufferException.malformedVarint(); 2517 } 2518 2519 @Override readRawVarint64()2520 public long readRawVarint64() throws IOException { 2521 // Implementation notes: 2522 // 2523 // Optimized for one-byte values, expected to be common. 2524 // The particular code below was selected from various candidates 2525 // empirically, by winning VarintBenchmark. 2526 // 2527 // Sign extension of (signed) Java bytes is usually a nuisance, but 2528 // we exploit it here to more easily obtain the sign of bytes read. 2529 // Instead of cleaning up the sign extension bits by masking eagerly, 2530 // we delay until we find the final (positive) byte, when we clear all 2531 // accumulated bits with one xor. We depend on javac to constant fold. 2532 fastpath: 2533 { 2534 int tempPos = pos; 2535 2536 if (bufferSize == tempPos) { 2537 break fastpath; 2538 } 2539 2540 final byte[] buffer = this.buffer; 2541 long x; 2542 int y; 2543 if ((y = buffer[tempPos++]) >= 0) { 2544 pos = tempPos; 2545 return y; 2546 } else if (bufferSize - tempPos < 9) { 2547 break fastpath; 2548 } else if ((y ^= (buffer[tempPos++] << 7)) < 0) { 2549 x = y ^ (~0 << 7); 2550 } else if ((y ^= (buffer[tempPos++] << 14)) >= 0) { 2551 x = y ^ ((~0 << 7) ^ (~0 << 14)); 2552 } else if ((y ^= (buffer[tempPos++] << 21)) < 0) { 2553 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21)); 2554 } else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) { 2555 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28); 2556 } else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) { 2557 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35); 2558 } else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) { 2559 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42); 2560 } else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) { 2561 x ^= 2562 (~0L << 7) 2563 ^ (~0L << 14) 2564 ^ (~0L << 21) 2565 ^ (~0L << 28) 2566 ^ (~0L << 35) 2567 ^ (~0L << 42) 2568 ^ (~0L << 49); 2569 } else { 2570 x ^= ((long) buffer[tempPos++] << 56); 2571 x ^= 2572 (~0L << 7) 2573 ^ (~0L << 14) 2574 ^ (~0L << 21) 2575 ^ (~0L << 28) 2576 ^ (~0L << 35) 2577 ^ (~0L << 42) 2578 ^ (~0L << 49) 2579 ^ (~0L << 56); 2580 if (x < 0L) { 2581 if (buffer[tempPos++] < 0L) { 2582 break fastpath; // Will throw malformedVarint() 2583 } 2584 } 2585 } 2586 pos = tempPos; 2587 return x; 2588 } 2589 return readRawVarint64SlowPath(); 2590 } 2591 2592 @Override readRawVarint64SlowPath()2593 long readRawVarint64SlowPath() throws IOException { 2594 long result = 0; 2595 for (int shift = 0; shift < 64; shift += 7) { 2596 final byte b = readRawByte(); 2597 result |= (long) (b & 0x7F) << shift; 2598 if ((b & 0x80) == 0) { 2599 return result; 2600 } 2601 } 2602 throw InvalidProtocolBufferException.malformedVarint(); 2603 } 2604 2605 @Override readRawLittleEndian32()2606 public int readRawLittleEndian32() throws IOException { 2607 int tempPos = pos; 2608 2609 if (bufferSize - tempPos < FIXED32_SIZE) { 2610 refillBuffer(FIXED32_SIZE); 2611 tempPos = pos; 2612 } 2613 2614 final byte[] buffer = this.buffer; 2615 pos = tempPos + FIXED32_SIZE; 2616 return ((buffer[tempPos] & 0xff) 2617 | ((buffer[tempPos + 1] & 0xff) << 8) 2618 | ((buffer[tempPos + 2] & 0xff) << 16) 2619 | ((buffer[tempPos + 3] & 0xff) << 24)); 2620 } 2621 2622 @Override readRawLittleEndian64()2623 public long readRawLittleEndian64() throws IOException { 2624 int tempPos = pos; 2625 2626 if (bufferSize - tempPos < FIXED64_SIZE) { 2627 refillBuffer(FIXED64_SIZE); 2628 tempPos = pos; 2629 } 2630 2631 final byte[] buffer = this.buffer; 2632 pos = tempPos + FIXED64_SIZE; 2633 return (((buffer[tempPos] & 0xffL)) 2634 | ((buffer[tempPos + 1] & 0xffL) << 8) 2635 | ((buffer[tempPos + 2] & 0xffL) << 16) 2636 | ((buffer[tempPos + 3] & 0xffL) << 24) 2637 | ((buffer[tempPos + 4] & 0xffL) << 32) 2638 | ((buffer[tempPos + 5] & 0xffL) << 40) 2639 | ((buffer[tempPos + 6] & 0xffL) << 48) 2640 | ((buffer[tempPos + 7] & 0xffL) << 56)); 2641 } 2642 2643 // ----------------------------------------------------------------- 2644 2645 @Override enableAliasing(boolean enabled)2646 public void enableAliasing(boolean enabled) { 2647 // TODO: Ideally we should throw here. Do nothing for backward compatibility. 2648 } 2649 2650 @Override resetSizeCounter()2651 public void resetSizeCounter() { 2652 totalBytesRetired = -pos; 2653 } 2654 2655 @Override pushLimit(int byteLimit)2656 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { 2657 if (byteLimit < 0) { 2658 throw InvalidProtocolBufferException.negativeSize(); 2659 } 2660 byteLimit += totalBytesRetired + pos; 2661 if (byteLimit < 0) { 2662 throw InvalidProtocolBufferException.parseFailure(); 2663 } 2664 final int oldLimit = currentLimit; 2665 if (byteLimit > oldLimit) { 2666 throw InvalidProtocolBufferException.truncatedMessage(); 2667 } 2668 currentLimit = byteLimit; 2669 2670 recomputeBufferSizeAfterLimit(); 2671 2672 return oldLimit; 2673 } 2674 recomputeBufferSizeAfterLimit()2675 private void recomputeBufferSizeAfterLimit() { 2676 bufferSize += bufferSizeAfterLimit; 2677 final int bufferEnd = totalBytesRetired + bufferSize; 2678 if (bufferEnd > currentLimit) { 2679 // Limit is in current buffer. 2680 bufferSizeAfterLimit = bufferEnd - currentLimit; 2681 bufferSize -= bufferSizeAfterLimit; 2682 } else { 2683 bufferSizeAfterLimit = 0; 2684 } 2685 } 2686 2687 @Override popLimit(final int oldLimit)2688 public void popLimit(final int oldLimit) { 2689 currentLimit = oldLimit; 2690 recomputeBufferSizeAfterLimit(); 2691 } 2692 2693 @Override getBytesUntilLimit()2694 public int getBytesUntilLimit() { 2695 if (currentLimit == Integer.MAX_VALUE) { 2696 return -1; 2697 } 2698 2699 final int currentAbsolutePosition = totalBytesRetired + pos; 2700 return currentLimit - currentAbsolutePosition; 2701 } 2702 2703 @Override isAtEnd()2704 public boolean isAtEnd() throws IOException { 2705 return pos == bufferSize && !tryRefillBuffer(1); 2706 } 2707 2708 @Override getTotalBytesRead()2709 public int getTotalBytesRead() { 2710 return totalBytesRetired + pos; 2711 } 2712 2713 private interface RefillCallback { onRefill()2714 void onRefill(); 2715 } 2716 2717 private RefillCallback refillCallback = null; 2718 2719 /** 2720 * Reads more bytes from the input, making at least {@code n} bytes available in the buffer. 2721 * Caller must ensure that the requested space is not yet available, and that the requested 2722 * space is less than BUFFER_SIZE. 2723 * 2724 * @throws InvalidProtocolBufferException The end of the stream or the current limit was 2725 * reached. 2726 */ refillBuffer(int n)2727 private void refillBuffer(int n) throws IOException { 2728 if (!tryRefillBuffer(n)) { 2729 // We have to distinguish the exception between sizeLimitExceeded and truncatedMessage. So 2730 // we just throw an sizeLimitExceeded exception here if it exceeds the sizeLimit 2731 if (n > sizeLimit - totalBytesRetired - pos) { 2732 throw InvalidProtocolBufferException.sizeLimitExceeded(); 2733 } else { 2734 throw InvalidProtocolBufferException.truncatedMessage(); 2735 } 2736 } 2737 } 2738 2739 /** 2740 * Tries to read more bytes from the input, making at least {@code n} bytes available in the 2741 * buffer. Caller must ensure that the requested space is not yet available, and that the 2742 * requested space is less than BUFFER_SIZE. 2743 * 2744 * @return {@code true} If the bytes could be made available; {@code false} 1. Current at the 2745 * end of the stream 2. The current limit was reached 3. The total size limit was reached 2746 */ tryRefillBuffer(int n)2747 private boolean tryRefillBuffer(int n) throws IOException { 2748 if (pos + n <= bufferSize) { 2749 throw new IllegalStateException( 2750 "refillBuffer() called when " + n + " bytes were already available in buffer"); 2751 } 2752 2753 // Check whether the size of total message needs to read is bigger than the size limit. 2754 // We shouldn't throw an exception here as isAtEnd() function needs to get this function's 2755 // return as the result. 2756 if (n > sizeLimit - totalBytesRetired - pos) { 2757 return false; 2758 } 2759 2760 // Shouldn't throw the exception here either. 2761 if (totalBytesRetired + pos + n > currentLimit) { 2762 // Oops, we hit a limit. 2763 return false; 2764 } 2765 2766 if (refillCallback != null) { 2767 refillCallback.onRefill(); 2768 } 2769 2770 int tempPos = pos; 2771 if (tempPos > 0) { 2772 if (bufferSize > tempPos) { 2773 System.arraycopy(buffer, tempPos, buffer, 0, bufferSize - tempPos); 2774 } 2775 totalBytesRetired += tempPos; 2776 bufferSize -= tempPos; 2777 pos = 0; 2778 } 2779 2780 // Here we should refill the buffer as many bytes as possible. 2781 int bytesRead = 2782 read( 2783 input, 2784 buffer, 2785 bufferSize, 2786 Math.min( 2787 // the size of allocated but unused bytes in the buffer 2788 buffer.length - bufferSize, 2789 // do not exceed the total bytes limit 2790 sizeLimit - totalBytesRetired - bufferSize)); 2791 if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) { 2792 throw new IllegalStateException( 2793 input.getClass() 2794 + "#read(byte[]) returned invalid result: " 2795 + bytesRead 2796 + "\nThe InputStream implementation is buggy."); 2797 } 2798 if (bytesRead > 0) { 2799 bufferSize += bytesRead; 2800 recomputeBufferSizeAfterLimit(); 2801 return (bufferSize >= n) ? true : tryRefillBuffer(n); 2802 } 2803 2804 return false; 2805 } 2806 2807 @Override readRawByte()2808 public byte readRawByte() throws IOException { 2809 if (pos == bufferSize) { 2810 refillBuffer(1); 2811 } 2812 return buffer[pos++]; 2813 } 2814 2815 @Override readRawBytes(final int size)2816 public byte[] readRawBytes(final int size) throws IOException { 2817 final int tempPos = pos; 2818 if (size <= (bufferSize - tempPos) && size > 0) { 2819 pos = tempPos + size; 2820 return Arrays.copyOfRange(buffer, tempPos, tempPos + size); 2821 } else { 2822 // TODO: Do we want to protect from malicious input streams here? 2823 return readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false); 2824 } 2825 } 2826 2827 /** 2828 * Exactly like readRawBytes, but caller must have already checked the fast path: (size <= 2829 * (bufferSize - pos) && size > 0) 2830 * 2831 * <p>If ensureNoLeakedReferences is true, the value is guaranteed to have not escaped to 2832 * untrusted code. 2833 */ readRawBytesSlowPath(final int size, boolean ensureNoLeakedReferences)2834 private byte[] readRawBytesSlowPath(final int size, boolean ensureNoLeakedReferences) 2835 throws IOException { 2836 // Attempt to read the data in one byte array when it's safe to do. 2837 byte[] result = readRawBytesSlowPathOneChunk(size); 2838 if (result != null) { 2839 return ensureNoLeakedReferences ? result.clone() : result; 2840 } 2841 2842 final int originalBufferPos = pos; 2843 final int bufferedBytes = bufferSize - pos; 2844 2845 // Mark the current buffer consumed. 2846 totalBytesRetired += bufferSize; 2847 pos = 0; 2848 bufferSize = 0; 2849 2850 // Determine the number of bytes we need to read from the input stream. 2851 int sizeLeft = size - bufferedBytes; 2852 2853 // The size is very large. For security reasons we read them in small 2854 // chunks. 2855 List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft); 2856 2857 // OK, got everything. Now concatenate it all into one buffer. 2858 final byte[] bytes = new byte[size]; 2859 2860 // Start by copying the leftover bytes from this.buffer. 2861 System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes); 2862 2863 // And now all the chunks. 2864 int tempPos = bufferedBytes; 2865 for (final byte[] chunk : chunks) { 2866 System.arraycopy(chunk, 0, bytes, tempPos, chunk.length); 2867 tempPos += chunk.length; 2868 } 2869 2870 // Done. 2871 return bytes; 2872 } 2873 2874 /** 2875 * Attempts to read the data in one byte array when it's safe to do. Returns null if the size to 2876 * read is too large and needs to be allocated in smaller chunks for security reasons. 2877 * 2878 * <p>Returns a byte[] that may have escaped to user code via InputStream APIs. 2879 */ readRawBytesSlowPathOneChunk(final int size)2880 private byte[] readRawBytesSlowPathOneChunk(final int size) throws IOException { 2881 if (size == 0) { 2882 return Internal.EMPTY_BYTE_ARRAY; 2883 } 2884 if (size < 0) { 2885 throw InvalidProtocolBufferException.negativeSize(); 2886 } 2887 2888 // Integer-overflow-conscious check that the message size so far has not exceeded sizeLimit. 2889 int currentMessageSize = totalBytesRetired + pos + size; 2890 if (currentMessageSize - sizeLimit > 0) { 2891 throw InvalidProtocolBufferException.sizeLimitExceeded(); 2892 } 2893 2894 // Verify that the message size so far has not exceeded currentLimit. 2895 if (currentMessageSize > currentLimit) { 2896 // Read to the end of the stream anyway. 2897 skipRawBytes(currentLimit - totalBytesRetired - pos); 2898 throw InvalidProtocolBufferException.truncatedMessage(); 2899 } 2900 2901 final int bufferedBytes = bufferSize - pos; 2902 // Determine the number of bytes we need to read from the input stream. 2903 int sizeLeft = size - bufferedBytes; 2904 // TODO: Consider using a value larger than DEFAULT_BUFFER_SIZE. 2905 if (sizeLeft < DEFAULT_BUFFER_SIZE || sizeLeft <= available(input)) { 2906 // Either the bytes we need are known to be available, or the required buffer is 2907 // within an allowed threshold - go ahead and allocate the buffer now. 2908 final byte[] bytes = new byte[size]; 2909 2910 // Copy all of the buffered bytes to the result buffer. 2911 System.arraycopy(buffer, pos, bytes, 0, bufferedBytes); 2912 totalBytesRetired += bufferSize; 2913 pos = 0; 2914 bufferSize = 0; 2915 2916 // Fill the remaining bytes from the input stream. 2917 int tempPos = bufferedBytes; 2918 while (tempPos < bytes.length) { 2919 int n = read(input, bytes, tempPos, size - tempPos); 2920 if (n == -1) { 2921 throw InvalidProtocolBufferException.truncatedMessage(); 2922 } 2923 totalBytesRetired += n; 2924 tempPos += n; 2925 } 2926 2927 return bytes; 2928 } 2929 2930 return null; 2931 } 2932 2933 /** 2934 * Reads the remaining data in small chunks from the input stream. 2935 * 2936 * <p>Returns a byte[] that may have escaped to user code via InputStream APIs. 2937 */ readRawBytesSlowPathRemainingChunks(int sizeLeft)2938 private List<byte[]> readRawBytesSlowPathRemainingChunks(int sizeLeft) throws IOException { 2939 // The size is very large. For security reasons, we can't allocate the 2940 // entire byte array yet. The size comes directly from the input, so a 2941 // maliciously-crafted message could provide a bogus very large size in 2942 // order to trick the app into allocating a lot of memory. We avoid this 2943 // by allocating and reading only a small chunk at a time, so that the 2944 // malicious message must actually *be* extremely large to cause 2945 // problems. Meanwhile, we limit the allowed size of a message elsewhere. 2946 final List<byte[]> chunks = new ArrayList<>(); 2947 2948 while (sizeLeft > 0) { 2949 // TODO: Consider using a value larger than DEFAULT_BUFFER_SIZE. 2950 final byte[] chunk = new byte[Math.min(sizeLeft, DEFAULT_BUFFER_SIZE)]; 2951 int tempPos = 0; 2952 while (tempPos < chunk.length) { 2953 final int n = input.read(chunk, tempPos, chunk.length - tempPos); 2954 if (n == -1) { 2955 throw InvalidProtocolBufferException.truncatedMessage(); 2956 } 2957 totalBytesRetired += n; 2958 tempPos += n; 2959 } 2960 sizeLeft -= chunk.length; 2961 chunks.add(chunk); 2962 } 2963 2964 return chunks; 2965 } 2966 2967 /** 2968 * Like readBytes, but caller must have already checked the fast path: (size <= (bufferSize - 2969 * pos) && size > 0 || size == 0) 2970 */ readBytesSlowPath(final int size)2971 private ByteString readBytesSlowPath(final int size) throws IOException { 2972 final byte[] result = readRawBytesSlowPathOneChunk(size); 2973 if (result != null) { 2974 // We must copy as the byte array was handed off to the InputStream and a malicious 2975 // implementation could retain a reference. 2976 return ByteString.copyFrom(result); 2977 } 2978 2979 final int originalBufferPos = pos; 2980 final int bufferedBytes = bufferSize - pos; 2981 2982 // Mark the current buffer consumed. 2983 totalBytesRetired += bufferSize; 2984 pos = 0; 2985 bufferSize = 0; 2986 2987 // Determine the number of bytes we need to read from the input stream. 2988 int sizeLeft = size - bufferedBytes; 2989 2990 // The size is very large. For security reasons we read them in small 2991 // chunks. 2992 List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft); 2993 2994 // OK, got everything. Now concatenate it all into one buffer. 2995 final byte[] bytes = new byte[size]; 2996 2997 // Start by copying the leftover bytes from this.buffer. 2998 System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes); 2999 3000 // And now all the chunks. 3001 int tempPos = bufferedBytes; 3002 for (final byte[] chunk : chunks) { 3003 System.arraycopy(chunk, 0, bytes, tempPos, chunk.length); 3004 tempPos += chunk.length; 3005 } 3006 3007 return ByteString.wrap(bytes); 3008 } 3009 3010 @Override skipRawBytes(final int size)3011 public void skipRawBytes(final int size) throws IOException { 3012 if (size <= (bufferSize - pos) && size >= 0) { 3013 // We have all the bytes we need already. 3014 pos += size; 3015 } else { 3016 skipRawBytesSlowPath(size); 3017 } 3018 } 3019 3020 /** 3021 * Exactly like skipRawBytes, but caller must have already checked the fast path: (size <= 3022 * (bufferSize - pos) && size >= 0) 3023 */ skipRawBytesSlowPath(final int size)3024 private void skipRawBytesSlowPath(final int size) throws IOException { 3025 if (size < 0) { 3026 throw InvalidProtocolBufferException.negativeSize(); 3027 } 3028 3029 if (totalBytesRetired + pos + size > currentLimit) { 3030 // Read to the end of the stream anyway. 3031 skipRawBytes(currentLimit - totalBytesRetired - pos); 3032 // Then fail. 3033 throw InvalidProtocolBufferException.truncatedMessage(); 3034 } 3035 3036 int totalSkipped = 0; 3037 if (refillCallback == null) { 3038 // Skipping more bytes than are in the buffer. First skip what we have. 3039 totalBytesRetired += pos; 3040 totalSkipped = bufferSize - pos; 3041 bufferSize = 0; 3042 pos = 0; 3043 3044 try { 3045 while (totalSkipped < size) { 3046 int toSkip = size - totalSkipped; 3047 long skipped = skip(input, toSkip); 3048 if (skipped < 0 || skipped > toSkip) { 3049 throw new IllegalStateException( 3050 input.getClass() 3051 + "#skip returned invalid result: " 3052 + skipped 3053 + "\nThe InputStream implementation is buggy."); 3054 } else if (skipped == 0) { 3055 // The API contract of skip() permits an inputstream to skip zero bytes for any reason 3056 // it wants. In particular, ByteArrayInputStream will just return zero over and over 3057 // when it's at the end of its input. In order to actually confirm that we've hit the 3058 // end of input, we need to issue a read call via the other path. 3059 break; 3060 } 3061 totalSkipped += (int) skipped; 3062 } 3063 } finally { 3064 totalBytesRetired += totalSkipped; 3065 recomputeBufferSizeAfterLimit(); 3066 } 3067 } 3068 if (totalSkipped < size) { 3069 // Skipping more bytes than are in the buffer. First skip what we have. 3070 int tempPos = bufferSize - pos; 3071 pos = bufferSize; 3072 3073 // Keep refilling the buffer until we get to the point we wanted to skip to. 3074 // This has the side effect of ensuring the limits are updated correctly. 3075 refillBuffer(1); 3076 while (size - tempPos > bufferSize) { 3077 tempPos += bufferSize; 3078 pos = bufferSize; 3079 refillBuffer(1); 3080 } 3081 3082 pos = size - tempPos; 3083 } 3084 } 3085 } 3086 3087 /** 3088 * Implementation of {@link CodedInputStream} that uses an {@link Iterable <ByteBuffer>} as the 3089 * data source. Requires the use of {@code sun.misc.Unsafe} to perform fast reads on the buffer. 3090 */ 3091 private static final class IterableDirectByteBufferDecoder extends CodedInputStream { 3092 /** The object that need to decode. */ 3093 private final Iterable<ByteBuffer> input; 3094 3095 /** The {@link Iterator} with type {@link ByteBuffer} of {@code input} */ 3096 private final Iterator<ByteBuffer> iterator; 3097 3098 /** The current ByteBuffer; */ 3099 private ByteBuffer currentByteBuffer; 3100 3101 /** 3102 * If {@code true}, indicates that all the buffers are backing a {@link ByteString} and are 3103 * therefore considered to be an immutable input source. 3104 */ 3105 private final boolean immutable; 3106 3107 /** 3108 * If {@code true}, indicates that calls to read {@link ByteString} or {@code byte[]} 3109 * <strong>may</strong> return slices of the underlying buffer, rather than copies. 3110 */ 3111 private boolean enableAliasing; 3112 3113 /** The global total message length limit */ 3114 private int totalBufferSize; 3115 3116 /** The amount of available data in the input beyond {@link #currentLimit}. */ 3117 private int bufferSizeAfterCurrentLimit; 3118 3119 /** The absolute position of the end of the current message. */ 3120 private int currentLimit = Integer.MAX_VALUE; 3121 3122 /** The last tag that was read from this stream. */ 3123 private int lastTag; 3124 3125 /** Total Bytes have been Read from the {@link Iterable} {@link ByteBuffer} */ 3126 private int totalBytesRead; 3127 3128 /** The start position offset of the whole message, used as to reset the totalBytesRead */ 3129 private int startOffset; 3130 3131 /** The current position for current ByteBuffer */ 3132 private long currentByteBufferPos; 3133 3134 private long currentByteBufferStartPos; 3135 3136 /** 3137 * If the current ByteBuffer is unsafe-direct based, currentAddress is the start address of this 3138 * ByteBuffer; otherwise should be zero. 3139 */ 3140 private long currentAddress; 3141 3142 /** The limit position for current ByteBuffer */ 3143 private long currentByteBufferLimit; 3144 3145 /** 3146 * The constructor of {@code Iterable<ByteBuffer>} decoder. 3147 * 3148 * @param inputBufs The input data. 3149 * @param size The total size of the input data. 3150 * @param immutableFlag whether the input data is immutable. 3151 */ IterableDirectByteBufferDecoder( Iterable<ByteBuffer> inputBufs, int size, boolean immutableFlag)3152 private IterableDirectByteBufferDecoder( 3153 Iterable<ByteBuffer> inputBufs, int size, boolean immutableFlag) { 3154 totalBufferSize = size; 3155 input = inputBufs; 3156 iterator = input.iterator(); 3157 immutable = immutableFlag; 3158 startOffset = totalBytesRead = 0; 3159 if (size == 0) { 3160 currentByteBuffer = EMPTY_BYTE_BUFFER; 3161 currentByteBufferPos = 0; 3162 currentByteBufferStartPos = 0; 3163 currentByteBufferLimit = 0; 3164 currentAddress = 0; 3165 } else { 3166 tryGetNextByteBuffer(); 3167 } 3168 } 3169 3170 /** To get the next ByteBuffer from {@code input}, and then update the parameters */ getNextByteBuffer()3171 private void getNextByteBuffer() throws InvalidProtocolBufferException { 3172 if (!iterator.hasNext()) { 3173 throw InvalidProtocolBufferException.truncatedMessage(); 3174 } 3175 tryGetNextByteBuffer(); 3176 } 3177 tryGetNextByteBuffer()3178 private void tryGetNextByteBuffer() { 3179 currentByteBuffer = iterator.next(); 3180 totalBytesRead += (int) (currentByteBufferPos - currentByteBufferStartPos); 3181 currentByteBufferPos = currentByteBuffer.position(); 3182 currentByteBufferStartPos = currentByteBufferPos; 3183 currentByteBufferLimit = currentByteBuffer.limit(); 3184 currentAddress = UnsafeUtil.addressOffset(currentByteBuffer); 3185 currentByteBufferPos += currentAddress; 3186 currentByteBufferStartPos += currentAddress; 3187 currentByteBufferLimit += currentAddress; 3188 } 3189 3190 @Override readTag()3191 public int readTag() throws IOException { 3192 if (isAtEnd()) { 3193 lastTag = 0; 3194 return 0; 3195 } 3196 3197 lastTag = readRawVarint32(); 3198 if (WireFormat.getTagFieldNumber(lastTag) == 0) { 3199 // If we actually read zero (or any tag number corresponding to field 3200 // number zero), that's not a valid tag. 3201 throw InvalidProtocolBufferException.invalidTag(); 3202 } 3203 return lastTag; 3204 } 3205 3206 @Override checkLastTagWas(final int value)3207 public void checkLastTagWas(final int value) throws InvalidProtocolBufferException { 3208 if (lastTag != value) { 3209 throw InvalidProtocolBufferException.invalidEndTag(); 3210 } 3211 } 3212 3213 @Override getLastTag()3214 public int getLastTag() { 3215 return lastTag; 3216 } 3217 3218 @Override skipField(final int tag)3219 public boolean skipField(final int tag) throws IOException { 3220 switch (WireFormat.getTagWireType(tag)) { 3221 case WireFormat.WIRETYPE_VARINT: 3222 skipRawVarint(); 3223 return true; 3224 case WireFormat.WIRETYPE_FIXED64: 3225 skipRawBytes(FIXED64_SIZE); 3226 return true; 3227 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 3228 skipRawBytes(readRawVarint32()); 3229 return true; 3230 case WireFormat.WIRETYPE_START_GROUP: 3231 skipMessage(); 3232 checkLastTagWas( 3233 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP)); 3234 return true; 3235 case WireFormat.WIRETYPE_END_GROUP: 3236 return false; 3237 case WireFormat.WIRETYPE_FIXED32: 3238 skipRawBytes(FIXED32_SIZE); 3239 return true; 3240 default: 3241 throw InvalidProtocolBufferException.invalidWireType(); 3242 } 3243 } 3244 3245 @Override skipField(final int tag, final CodedOutputStream output)3246 public boolean skipField(final int tag, final CodedOutputStream output) throws IOException { 3247 switch (WireFormat.getTagWireType(tag)) { 3248 case WireFormat.WIRETYPE_VARINT: 3249 { 3250 long value = readInt64(); 3251 output.writeUInt32NoTag(tag); 3252 output.writeUInt64NoTag(value); 3253 return true; 3254 } 3255 case WireFormat.WIRETYPE_FIXED64: 3256 { 3257 long value = readRawLittleEndian64(); 3258 output.writeUInt32NoTag(tag); 3259 output.writeFixed64NoTag(value); 3260 return true; 3261 } 3262 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 3263 { 3264 ByteString value = readBytes(); 3265 output.writeUInt32NoTag(tag); 3266 output.writeBytesNoTag(value); 3267 return true; 3268 } 3269 case WireFormat.WIRETYPE_START_GROUP: 3270 { 3271 output.writeUInt32NoTag(tag); 3272 skipMessage(output); 3273 int endtag = 3274 WireFormat.makeTag( 3275 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP); 3276 checkLastTagWas(endtag); 3277 output.writeUInt32NoTag(endtag); 3278 return true; 3279 } 3280 case WireFormat.WIRETYPE_END_GROUP: 3281 { 3282 return false; 3283 } 3284 case WireFormat.WIRETYPE_FIXED32: 3285 { 3286 int value = readRawLittleEndian32(); 3287 output.writeUInt32NoTag(tag); 3288 output.writeFixed32NoTag(value); 3289 return true; 3290 } 3291 default: 3292 throw InvalidProtocolBufferException.invalidWireType(); 3293 } 3294 } 3295 3296 // ----------------------------------------------------------------- 3297 3298 @Override readDouble()3299 public double readDouble() throws IOException { 3300 return Double.longBitsToDouble(readRawLittleEndian64()); 3301 } 3302 3303 @Override readFloat()3304 public float readFloat() throws IOException { 3305 return Float.intBitsToFloat(readRawLittleEndian32()); 3306 } 3307 3308 @Override readUInt64()3309 public long readUInt64() throws IOException { 3310 return readRawVarint64(); 3311 } 3312 3313 @Override readInt64()3314 public long readInt64() throws IOException { 3315 return readRawVarint64(); 3316 } 3317 3318 @Override readInt32()3319 public int readInt32() throws IOException { 3320 return readRawVarint32(); 3321 } 3322 3323 @Override readFixed64()3324 public long readFixed64() throws IOException { 3325 return readRawLittleEndian64(); 3326 } 3327 3328 @Override readFixed32()3329 public int readFixed32() throws IOException { 3330 return readRawLittleEndian32(); 3331 } 3332 3333 @Override readBool()3334 public boolean readBool() throws IOException { 3335 return readRawVarint64() != 0; 3336 } 3337 3338 @Override readString()3339 public String readString() throws IOException { 3340 final int size = readRawVarint32(); 3341 if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) { 3342 byte[] bytes = new byte[size]; 3343 UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size); 3344 String result = new String(bytes, UTF_8); 3345 currentByteBufferPos += size; 3346 return result; 3347 } else if (size > 0 && size <= remaining()) { 3348 // TODO: To use an underlying bytes[] instead of allocating a new bytes[] 3349 byte[] bytes = new byte[size]; 3350 readRawBytesTo(bytes, 0, size); 3351 String result = new String(bytes, UTF_8); 3352 return result; 3353 } 3354 3355 if (size == 0) { 3356 return ""; 3357 } 3358 if (size < 0) { 3359 throw InvalidProtocolBufferException.negativeSize(); 3360 } 3361 throw InvalidProtocolBufferException.truncatedMessage(); 3362 } 3363 3364 @Override readStringRequireUtf8()3365 public String readStringRequireUtf8() throws IOException { 3366 final int size = readRawVarint32(); 3367 if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) { 3368 final int bufferPos = (int) (currentByteBufferPos - currentByteBufferStartPos); 3369 String result = Utf8.decodeUtf8(currentByteBuffer, bufferPos, size); 3370 currentByteBufferPos += size; 3371 return result; 3372 } 3373 if (size >= 0 && size <= remaining()) { 3374 byte[] bytes = new byte[size]; 3375 readRawBytesTo(bytes, 0, size); 3376 return Utf8.decodeUtf8(bytes, 0, size); 3377 } 3378 3379 if (size == 0) { 3380 return ""; 3381 } 3382 if (size <= 0) { 3383 throw InvalidProtocolBufferException.negativeSize(); 3384 } 3385 throw InvalidProtocolBufferException.truncatedMessage(); 3386 } 3387 3388 @Override readGroup( final int fieldNumber, final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)3389 public void readGroup( 3390 final int fieldNumber, 3391 final MessageLite.Builder builder, 3392 final ExtensionRegistryLite extensionRegistry) 3393 throws IOException { 3394 checkRecursionLimit(); 3395 ++recursionDepth; 3396 builder.mergeFrom(this, extensionRegistry); 3397 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); 3398 --recursionDepth; 3399 } 3400 3401 @Override readGroup( final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)3402 public <T extends MessageLite> T readGroup( 3403 final int fieldNumber, 3404 final Parser<T> parser, 3405 final ExtensionRegistryLite extensionRegistry) 3406 throws IOException { 3407 checkRecursionLimit(); 3408 ++recursionDepth; 3409 T result = parser.parsePartialFrom(this, extensionRegistry); 3410 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); 3411 --recursionDepth; 3412 return result; 3413 } 3414 3415 @Deprecated 3416 @Override readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)3417 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder) 3418 throws IOException { 3419 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry()); 3420 } 3421 3422 @Override readMessage( final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)3423 public void readMessage( 3424 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry) 3425 throws IOException { 3426 final int length = readRawVarint32(); 3427 checkRecursionLimit(); 3428 final int oldLimit = pushLimit(length); 3429 ++recursionDepth; 3430 builder.mergeFrom(this, extensionRegistry); 3431 checkLastTagWas(0); 3432 --recursionDepth; 3433 if (getBytesUntilLimit() != 0) { 3434 throw InvalidProtocolBufferException.truncatedMessage(); 3435 } 3436 popLimit(oldLimit); 3437 } 3438 3439 @Override readMessage( final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)3440 public <T extends MessageLite> T readMessage( 3441 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException { 3442 int length = readRawVarint32(); 3443 checkRecursionLimit(); 3444 final int oldLimit = pushLimit(length); 3445 ++recursionDepth; 3446 T result = parser.parsePartialFrom(this, extensionRegistry); 3447 checkLastTagWas(0); 3448 --recursionDepth; 3449 if (getBytesUntilLimit() != 0) { 3450 throw InvalidProtocolBufferException.truncatedMessage(); 3451 } 3452 popLimit(oldLimit); 3453 return result; 3454 } 3455 3456 @Override readBytes()3457 public ByteString readBytes() throws IOException { 3458 final int size = readRawVarint32(); 3459 if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) { 3460 if (immutable && enableAliasing) { 3461 final int idx = (int) (currentByteBufferPos - currentAddress); 3462 final ByteString result = ByteString.wrap(slice(idx, idx + size)); 3463 currentByteBufferPos += size; 3464 return result; 3465 } else { 3466 byte[] bytes = new byte[size]; 3467 UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size); 3468 currentByteBufferPos += size; 3469 return ByteString.wrap(bytes); 3470 } 3471 } else if (size > 0 && size <= remaining()) { 3472 if (immutable && enableAliasing) { 3473 ArrayList<ByteString> byteStrings = new ArrayList<>(); 3474 int l = size; 3475 while (l > 0) { 3476 if (currentRemaining() == 0) { 3477 getNextByteBuffer(); 3478 } 3479 int bytesToCopy = Math.min(l, (int) currentRemaining()); 3480 int idx = (int) (currentByteBufferPos - currentAddress); 3481 byteStrings.add(ByteString.wrap(slice(idx, idx + bytesToCopy))); 3482 l -= bytesToCopy; 3483 currentByteBufferPos += bytesToCopy; 3484 } 3485 return ByteString.copyFrom(byteStrings); 3486 } else { 3487 byte[] temp = new byte[size]; 3488 readRawBytesTo(temp, 0, size); 3489 return ByteString.wrap(temp); 3490 } 3491 } 3492 3493 if (size == 0) { 3494 return ByteString.EMPTY; 3495 } 3496 if (size < 0) { 3497 throw InvalidProtocolBufferException.negativeSize(); 3498 } 3499 throw InvalidProtocolBufferException.truncatedMessage(); 3500 } 3501 3502 @Override readByteArray()3503 public byte[] readByteArray() throws IOException { 3504 return readRawBytes(readRawVarint32()); 3505 } 3506 3507 @Override readByteBuffer()3508 public ByteBuffer readByteBuffer() throws IOException { 3509 final int size = readRawVarint32(); 3510 if (size > 0 && size <= currentRemaining()) { 3511 if (!immutable && enableAliasing) { 3512 currentByteBufferPos += size; 3513 return slice( 3514 (int) (currentByteBufferPos - currentAddress - size), 3515 (int) (currentByteBufferPos - currentAddress)); 3516 } else { 3517 byte[] bytes = new byte[size]; 3518 UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size); 3519 currentByteBufferPos += size; 3520 return ByteBuffer.wrap(bytes); 3521 } 3522 } else if (size > 0 && size <= remaining()) { 3523 byte[] temp = new byte[size]; 3524 readRawBytesTo(temp, 0, size); 3525 return ByteBuffer.wrap(temp); 3526 } 3527 3528 if (size == 0) { 3529 return EMPTY_BYTE_BUFFER; 3530 } 3531 if (size < 0) { 3532 throw InvalidProtocolBufferException.negativeSize(); 3533 } 3534 throw InvalidProtocolBufferException.truncatedMessage(); 3535 } 3536 3537 @Override readUInt32()3538 public int readUInt32() throws IOException { 3539 return readRawVarint32(); 3540 } 3541 3542 @Override readEnum()3543 public int readEnum() throws IOException { 3544 return readRawVarint32(); 3545 } 3546 3547 @Override readSFixed32()3548 public int readSFixed32() throws IOException { 3549 return readRawLittleEndian32(); 3550 } 3551 3552 @Override readSFixed64()3553 public long readSFixed64() throws IOException { 3554 return readRawLittleEndian64(); 3555 } 3556 3557 @Override readSInt32()3558 public int readSInt32() throws IOException { 3559 return decodeZigZag32(readRawVarint32()); 3560 } 3561 3562 @Override readSInt64()3563 public long readSInt64() throws IOException { 3564 return decodeZigZag64(readRawVarint64()); 3565 } 3566 3567 @Override readRawVarint32()3568 public int readRawVarint32() throws IOException { 3569 fastpath: 3570 { 3571 long tempPos = currentByteBufferPos; 3572 3573 if (currentByteBufferLimit == currentByteBufferPos) { 3574 break fastpath; 3575 } 3576 3577 int x; 3578 if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) { 3579 currentByteBufferPos++; 3580 return x; 3581 } else if (currentByteBufferLimit - currentByteBufferPos < 10) { 3582 break fastpath; 3583 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) { 3584 x ^= (~0 << 7); 3585 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) { 3586 x ^= (~0 << 7) ^ (~0 << 14); 3587 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) { 3588 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21); 3589 } else { 3590 int y = UnsafeUtil.getByte(tempPos++); 3591 x ^= y << 28; 3592 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28); 3593 if (y < 0 3594 && UnsafeUtil.getByte(tempPos++) < 0 3595 && UnsafeUtil.getByte(tempPos++) < 0 3596 && UnsafeUtil.getByte(tempPos++) < 0 3597 && UnsafeUtil.getByte(tempPos++) < 0 3598 && UnsafeUtil.getByte(tempPos++) < 0) { 3599 break fastpath; // Will throw malformedVarint() 3600 } 3601 } 3602 currentByteBufferPos = tempPos; 3603 return x; 3604 } 3605 return (int) readRawVarint64SlowPath(); 3606 } 3607 3608 @Override readRawVarint64()3609 public long readRawVarint64() throws IOException { 3610 fastpath: 3611 { 3612 long tempPos = currentByteBufferPos; 3613 3614 if (currentByteBufferLimit == currentByteBufferPos) { 3615 break fastpath; 3616 } 3617 3618 long x; 3619 int y; 3620 if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) { 3621 currentByteBufferPos++; 3622 return y; 3623 } else if (currentByteBufferLimit - currentByteBufferPos < 10) { 3624 break fastpath; 3625 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) { 3626 x = y ^ (~0 << 7); 3627 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) { 3628 x = y ^ ((~0 << 7) ^ (~0 << 14)); 3629 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) { 3630 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21)); 3631 } else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) { 3632 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28); 3633 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) { 3634 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35); 3635 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) { 3636 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42); 3637 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) { 3638 x ^= 3639 (~0L << 7) 3640 ^ (~0L << 14) 3641 ^ (~0L << 21) 3642 ^ (~0L << 28) 3643 ^ (~0L << 35) 3644 ^ (~0L << 42) 3645 ^ (~0L << 49); 3646 } else { 3647 x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56); 3648 x ^= 3649 (~0L << 7) 3650 ^ (~0L << 14) 3651 ^ (~0L << 21) 3652 ^ (~0L << 28) 3653 ^ (~0L << 35) 3654 ^ (~0L << 42) 3655 ^ (~0L << 49) 3656 ^ (~0L << 56); 3657 if (x < 0L) { 3658 if (UnsafeUtil.getByte(tempPos++) < 0L) { 3659 break fastpath; // Will throw malformedVarint() 3660 } 3661 } 3662 } 3663 currentByteBufferPos = tempPos; 3664 return x; 3665 } 3666 return readRawVarint64SlowPath(); 3667 } 3668 3669 @Override readRawVarint64SlowPath()3670 long readRawVarint64SlowPath() throws IOException { 3671 long result = 0; 3672 for (int shift = 0; shift < 64; shift += 7) { 3673 final byte b = readRawByte(); 3674 result |= (long) (b & 0x7F) << shift; 3675 if ((b & 0x80) == 0) { 3676 return result; 3677 } 3678 } 3679 throw InvalidProtocolBufferException.malformedVarint(); 3680 } 3681 3682 @Override readRawLittleEndian32()3683 public int readRawLittleEndian32() throws IOException { 3684 if (currentRemaining() >= FIXED32_SIZE) { 3685 long tempPos = currentByteBufferPos; 3686 currentByteBufferPos += FIXED32_SIZE; 3687 return ((UnsafeUtil.getByte(tempPos) & 0xff) 3688 | ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8) 3689 | ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16) 3690 | ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24)); 3691 } 3692 return ((readRawByte() & 0xff) 3693 | ((readRawByte() & 0xff) << 8) 3694 | ((readRawByte() & 0xff) << 16) 3695 | ((readRawByte() & 0xff) << 24)); 3696 } 3697 3698 @Override readRawLittleEndian64()3699 public long readRawLittleEndian64() throws IOException { 3700 if (currentRemaining() >= FIXED64_SIZE) { 3701 long tempPos = currentByteBufferPos; 3702 currentByteBufferPos += FIXED64_SIZE; 3703 return ((UnsafeUtil.getByte(tempPos) & 0xffL) 3704 | ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8) 3705 | ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16) 3706 | ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24) 3707 | ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32) 3708 | ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40) 3709 | ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48) 3710 | ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56)); 3711 } 3712 return ((readRawByte() & 0xffL) 3713 | ((readRawByte() & 0xffL) << 8) 3714 | ((readRawByte() & 0xffL) << 16) 3715 | ((readRawByte() & 0xffL) << 24) 3716 | ((readRawByte() & 0xffL) << 32) 3717 | ((readRawByte() & 0xffL) << 40) 3718 | ((readRawByte() & 0xffL) << 48) 3719 | ((readRawByte() & 0xffL) << 56)); 3720 } 3721 3722 @Override enableAliasing(boolean enabled)3723 public void enableAliasing(boolean enabled) { 3724 this.enableAliasing = enabled; 3725 } 3726 3727 @Override resetSizeCounter()3728 public void resetSizeCounter() { 3729 startOffset = (int) (totalBytesRead + currentByteBufferPos - currentByteBufferStartPos); 3730 } 3731 3732 @Override pushLimit(int byteLimit)3733 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { 3734 if (byteLimit < 0) { 3735 throw InvalidProtocolBufferException.negativeSize(); 3736 } 3737 byteLimit += getTotalBytesRead(); 3738 final int oldLimit = currentLimit; 3739 if (byteLimit > oldLimit) { 3740 throw InvalidProtocolBufferException.truncatedMessage(); 3741 } 3742 currentLimit = byteLimit; 3743 3744 recomputeBufferSizeAfterLimit(); 3745 3746 return oldLimit; 3747 } 3748 recomputeBufferSizeAfterLimit()3749 private void recomputeBufferSizeAfterLimit() { 3750 totalBufferSize += bufferSizeAfterCurrentLimit; 3751 final int bufferEnd = totalBufferSize - startOffset; 3752 if (bufferEnd > currentLimit) { 3753 // Limit is in current buffer. 3754 bufferSizeAfterCurrentLimit = bufferEnd - currentLimit; 3755 totalBufferSize -= bufferSizeAfterCurrentLimit; 3756 } else { 3757 bufferSizeAfterCurrentLimit = 0; 3758 } 3759 } 3760 3761 @Override popLimit(final int oldLimit)3762 public void popLimit(final int oldLimit) { 3763 currentLimit = oldLimit; 3764 recomputeBufferSizeAfterLimit(); 3765 } 3766 3767 @Override getBytesUntilLimit()3768 public int getBytesUntilLimit() { 3769 if (currentLimit == Integer.MAX_VALUE) { 3770 return -1; 3771 } 3772 3773 return currentLimit - getTotalBytesRead(); 3774 } 3775 3776 @Override isAtEnd()3777 public boolean isAtEnd() throws IOException { 3778 return totalBytesRead + currentByteBufferPos - currentByteBufferStartPos == totalBufferSize; 3779 } 3780 3781 @Override getTotalBytesRead()3782 public int getTotalBytesRead() { 3783 return (int) 3784 (totalBytesRead - startOffset + currentByteBufferPos - currentByteBufferStartPos); 3785 } 3786 3787 @Override readRawByte()3788 public byte readRawByte() throws IOException { 3789 if (currentRemaining() == 0) { 3790 getNextByteBuffer(); 3791 } 3792 return UnsafeUtil.getByte(currentByteBufferPos++); 3793 } 3794 3795 @Override readRawBytes(final int length)3796 public byte[] readRawBytes(final int length) throws IOException { 3797 if (length >= 0 && length <= currentRemaining()) { 3798 byte[] bytes = new byte[length]; 3799 UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, length); 3800 currentByteBufferPos += length; 3801 return bytes; 3802 } 3803 if (length >= 0 && length <= remaining()) { 3804 byte[] bytes = new byte[length]; 3805 readRawBytesTo(bytes, 0, length); 3806 return bytes; 3807 } 3808 3809 if (length <= 0) { 3810 if (length == 0) { 3811 return EMPTY_BYTE_ARRAY; 3812 } else { 3813 throw InvalidProtocolBufferException.negativeSize(); 3814 } 3815 } 3816 3817 throw InvalidProtocolBufferException.truncatedMessage(); 3818 } 3819 3820 /** 3821 * Try to get raw bytes from {@code input} with the size of {@code length} and copy to {@code 3822 * bytes} array. If the size is bigger than the number of remaining bytes in the input, then 3823 * throw {@code truncatedMessage} exception. 3824 */ readRawBytesTo(byte[] bytes, int offset, final int length)3825 private void readRawBytesTo(byte[] bytes, int offset, final int length) throws IOException { 3826 if (length >= 0 && length <= remaining()) { 3827 int l = length; 3828 while (l > 0) { 3829 if (currentRemaining() == 0) { 3830 getNextByteBuffer(); 3831 } 3832 int bytesToCopy = Math.min(l, (int) currentRemaining()); 3833 UnsafeUtil.copyMemory(currentByteBufferPos, bytes, length - l + offset, bytesToCopy); 3834 l -= bytesToCopy; 3835 currentByteBufferPos += bytesToCopy; 3836 } 3837 return; 3838 } 3839 3840 if (length <= 0) { 3841 if (length == 0) { 3842 return; 3843 } else { 3844 throw InvalidProtocolBufferException.negativeSize(); 3845 } 3846 } 3847 throw InvalidProtocolBufferException.truncatedMessage(); 3848 } 3849 3850 @Override skipRawBytes(final int length)3851 public void skipRawBytes(final int length) throws IOException { 3852 if (length >= 0 3853 && length 3854 <= (totalBufferSize 3855 - totalBytesRead 3856 - currentByteBufferPos 3857 + currentByteBufferStartPos)) { 3858 // We have all the bytes we need already. 3859 int l = length; 3860 while (l > 0) { 3861 if (currentRemaining() == 0) { 3862 getNextByteBuffer(); 3863 } 3864 int rl = Math.min(l, (int) currentRemaining()); 3865 l -= rl; 3866 currentByteBufferPos += rl; 3867 } 3868 return; 3869 } 3870 3871 if (length < 0) { 3872 throw InvalidProtocolBufferException.negativeSize(); 3873 } 3874 throw InvalidProtocolBufferException.truncatedMessage(); 3875 } 3876 3877 // TODO: optimize to fastpath skipRawVarint()3878 private void skipRawVarint() throws IOException { 3879 for (int i = 0; i < MAX_VARINT_SIZE; i++) { 3880 if (readRawByte() >= 0) { 3881 return; 3882 } 3883 } 3884 throw InvalidProtocolBufferException.malformedVarint(); 3885 } 3886 3887 /** 3888 * Try to get the number of remaining bytes in {@code input}. 3889 * 3890 * @return the number of remaining bytes in {@code input}. 3891 */ remaining()3892 private int remaining() { 3893 return (int) 3894 (totalBufferSize - totalBytesRead - currentByteBufferPos + currentByteBufferStartPos); 3895 } 3896 3897 /** 3898 * Try to get the number of remaining bytes in {@code currentByteBuffer}. 3899 * 3900 * @return the number of remaining bytes in {@code currentByteBuffer} 3901 */ currentRemaining()3902 private long currentRemaining() { 3903 return (currentByteBufferLimit - currentByteBufferPos); 3904 } 3905 slice(int begin, int end)3906 private ByteBuffer slice(int begin, int end) throws IOException { 3907 int prevPos = currentByteBuffer.position(); 3908 int prevLimit = currentByteBuffer.limit(); 3909 // View ByteBuffer as Buffer to avoid cross-Java version issues. 3910 // See https://issues.apache.org/jira/browse/MRESOLVER-85 3911 Buffer asBuffer = currentByteBuffer; 3912 try { 3913 asBuffer.position(begin); 3914 asBuffer.limit(end); 3915 return currentByteBuffer.slice(); 3916 } catch (IllegalArgumentException e) { 3917 throw InvalidProtocolBufferException.truncatedMessage(); 3918 } finally { 3919 asBuffer.position(prevPos); 3920 asBuffer.limit(prevLimit); 3921 } 3922 } 3923 } 3924 } 3925