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