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