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