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.MessageSchema.getMutableUnknownFields; 34 35 import com.google.protobuf.Internal.ProtobufList; 36 import java.io.IOException; 37 38 /** 39 * Helper functions to decode protobuf wire format from a byte array. 40 * 41 * <p>Note that these functions don't do boundary check on the byte array but instead rely on Java 42 * VM to check it. That means parsing routines utilizing these functions must catch 43 * IndexOutOfBoundsException and convert it to protobuf's InvalidProtocolBufferException when 44 * crossing protobuf public API boundaries. 45 */ 46 final class ArrayDecoders { 47 /** 48 * A helper used to return multiple values in a Java function. Java doesn't natively support 49 * returning multiple values in a function. Creating a new Object to hold the return values will 50 * be too expensive. Instead, we pass a Registers instance to functions that want to return 51 * multiple values and let the function set the return value in this Registers instance instead. 52 * 53 * <p>TODO(xiaofeng): This could be merged into CodedInputStream or CodedInputStreamReader which 54 * is already being passed through all the parsing routines. 55 */ 56 static final class Registers { 57 public int int1; 58 public long long1; 59 public Object object1; 60 public final ExtensionRegistryLite extensionRegistry; 61 Registers()62 Registers() { 63 this.extensionRegistry = ExtensionRegistryLite.getEmptyRegistry(); 64 } 65 Registers(ExtensionRegistryLite extensionRegistry)66 Registers(ExtensionRegistryLite extensionRegistry) { 67 if (extensionRegistry == null) { 68 throw new NullPointerException(); 69 } 70 this.extensionRegistry = extensionRegistry; 71 } 72 } 73 74 /** 75 * Decodes a varint. Returns the position after the varint. The decoded varint is stored in 76 * registers.int1. 77 */ decodeVarint32(byte[] data, int position, Registers registers)78 static int decodeVarint32(byte[] data, int position, Registers registers) { 79 int value = data[position++]; 80 if (value >= 0) { 81 registers.int1 = value; 82 return position; 83 } 84 return decodeVarint32(value, data, position, registers); 85 } 86 87 /** Like decodeVarint32 except that the first byte is already read. */ decodeVarint32(int firstByte, byte[] data, int position, Registers registers)88 static int decodeVarint32(int firstByte, byte[] data, int position, Registers registers) { 89 int value = firstByte & 0x7F; 90 final byte b2 = data[position++]; 91 if (b2 >= 0) { 92 registers.int1 = value | ((int) b2 << 7); 93 return position; 94 } 95 value |= (b2 & 0x7F) << 7; 96 97 final byte b3 = data[position++]; 98 if (b3 >= 0) { 99 registers.int1 = value | ((int) b3 << 14); 100 return position; 101 } 102 value |= (b3 & 0x7F) << 14; 103 104 final byte b4 = data[position++]; 105 if (b4 >= 0) { 106 registers.int1 = value | ((int) b4 << 21); 107 return position; 108 } 109 value |= (b4 & 0x7F) << 21; 110 111 final byte b5 = data[position++]; 112 if (b5 >= 0) { 113 registers.int1 = value | ((int) b5 << 28); 114 return position; 115 } 116 value |= (b5 & 0x7F) << 28; 117 118 while (data[position++] < 0) {} 119 120 registers.int1 = value; 121 return position; 122 } 123 124 /** 125 * Decodes a varint. Returns the position after the varint. The decoded varint is stored in 126 * registers.long1. 127 */ decodeVarint64(byte[] data, int position, Registers registers)128 static int decodeVarint64(byte[] data, int position, Registers registers) { 129 long value = data[position++]; 130 if (value >= 0) { 131 registers.long1 = value; 132 return position; 133 } else { 134 return decodeVarint64(value, data, position, registers); 135 } 136 } 137 138 /** Like decodeVarint64 except that the first byte is already read. */ decodeVarint64(long firstByte, byte[] data, int position, Registers registers)139 static int decodeVarint64(long firstByte, byte[] data, int position, Registers registers) { 140 long value = firstByte & 0x7F; 141 byte next = data[position++]; 142 int shift = 7; 143 value |= (long) (next & 0x7F) << 7; 144 while (next < 0) { 145 next = data[position++]; 146 shift += 7; 147 value |= (long) (next & 0x7F) << shift; 148 } 149 registers.long1 = value; 150 return position; 151 } 152 153 /** Decodes and returns a fixed32 value. */ decodeFixed32(byte[] data, int position)154 static int decodeFixed32(byte[] data, int position) { 155 return (data[position] & 0xff) 156 | ((data[position + 1] & 0xff) << 8) 157 | ((data[position + 2] & 0xff) << 16) 158 | ((data[position + 3] & 0xff) << 24); 159 } 160 161 /** Decodes and returns a fixed64 value. */ decodeFixed64(byte[] data, int position)162 static long decodeFixed64(byte[] data, int position) { 163 return (data[position] & 0xffL) 164 | ((data[position + 1] & 0xffL) << 8) 165 | ((data[position + 2] & 0xffL) << 16) 166 | ((data[position + 3] & 0xffL) << 24) 167 | ((data[position + 4] & 0xffL) << 32) 168 | ((data[position + 5] & 0xffL) << 40) 169 | ((data[position + 6] & 0xffL) << 48) 170 | ((data[position + 7] & 0xffL) << 56); 171 } 172 173 /** Decodes and returns a double value. */ decodeDouble(byte[] data, int position)174 static double decodeDouble(byte[] data, int position) { 175 return Double.longBitsToDouble(decodeFixed64(data, position)); 176 } 177 178 /** Decodes and returns a float value. */ decodeFloat(byte[] data, int position)179 static float decodeFloat(byte[] data, int position) { 180 return Float.intBitsToFloat(decodeFixed32(data, position)); 181 } 182 183 /** Decodes a string value. */ decodeString(byte[] data, int position, Registers registers)184 static int decodeString(byte[] data, int position, Registers registers) 185 throws InvalidProtocolBufferException { 186 position = decodeVarint32(data, position, registers); 187 final int length = registers.int1; 188 if (length < 0) { 189 throw InvalidProtocolBufferException.negativeSize(); 190 } else if (length == 0) { 191 registers.object1 = ""; 192 return position; 193 } else { 194 registers.object1 = new String(data, position, length, Internal.UTF_8); 195 return position + length; 196 } 197 } 198 199 /** Decodes a string value with utf8 check. */ decodeStringRequireUtf8(byte[] data, int position, Registers registers)200 static int decodeStringRequireUtf8(byte[] data, int position, Registers registers) 201 throws InvalidProtocolBufferException { 202 position = decodeVarint32(data, position, registers); 203 final int length = registers.int1; 204 if (length < 0) { 205 throw InvalidProtocolBufferException.negativeSize(); 206 } else if (length == 0) { 207 registers.object1 = ""; 208 return position; 209 } else { 210 registers.object1 = Utf8.decodeUtf8(data, position, length); 211 return position + length; 212 } 213 } 214 215 /** Decodes a bytes value. */ decodeBytes(byte[] data, int position, Registers registers)216 static int decodeBytes(byte[] data, int position, Registers registers) 217 throws InvalidProtocolBufferException { 218 position = decodeVarint32(data, position, registers); 219 final int length = registers.int1; 220 if (length < 0) { 221 throw InvalidProtocolBufferException.negativeSize(); 222 } else if (length > data.length - position) { 223 throw InvalidProtocolBufferException.truncatedMessage(); 224 } else if (length == 0) { 225 registers.object1 = ByteString.EMPTY; 226 return position; 227 } else { 228 registers.object1 = ByteString.copyFrom(data, position, length); 229 return position + length; 230 } 231 } 232 233 /** Decodes a message value. */ 234 @SuppressWarnings({"unchecked", "rawtypes"}) decodeMessageField( Schema schema, byte[] data, int position, int limit, Registers registers)235 static int decodeMessageField( 236 Schema schema, byte[] data, int position, int limit, Registers registers) throws IOException { 237 Object msg = schema.newInstance(); 238 int offset = mergeMessageField(msg, schema, data, position, limit, registers); 239 schema.makeImmutable(msg); 240 registers.object1 = msg; 241 return offset; 242 } 243 244 /** Decodes a group value. */ 245 @SuppressWarnings({"unchecked", "rawtypes"}) decodeGroupField( Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers)246 static int decodeGroupField( 247 Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers) 248 throws IOException { 249 Object msg = schema.newInstance(); 250 int offset = mergeGroupField(msg, schema, data, position, limit, endGroup, registers); 251 schema.makeImmutable(msg); 252 registers.object1 = msg; 253 return offset; 254 } 255 256 @SuppressWarnings({"unchecked", "rawtypes"}) mergeMessageField( Object msg, Schema schema, byte[] data, int position, int limit, Registers registers)257 static int mergeMessageField( 258 Object msg, Schema schema, byte[] data, int position, int limit, Registers registers) 259 throws IOException { 260 int length = data[position++]; 261 if (length < 0) { 262 position = decodeVarint32(length, data, position, registers); 263 length = registers.int1; 264 } 265 if (length < 0 || length > limit - position) { 266 throw InvalidProtocolBufferException.truncatedMessage(); 267 } 268 schema.mergeFrom(msg, data, position, position + length, registers); 269 registers.object1 = msg; 270 return position + length; 271 } 272 273 @SuppressWarnings({"unchecked", "rawtypes"}) mergeGroupField( Object msg, Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers)274 static int mergeGroupField( 275 Object msg, 276 Schema schema, 277 byte[] data, 278 int position, 279 int limit, 280 int endGroup, 281 Registers registers) 282 throws IOException { 283 // A group field must has a MessageSchema (the only other subclass of Schema is MessageSetSchema 284 // and it can't be used in group fields). 285 final MessageSchema messageSchema = (MessageSchema) schema; 286 // It's OK to directly use parseProto2Message since proto3 doesn't have group. 287 final int endPosition = 288 messageSchema.parseProto2Message(msg, data, position, limit, endGroup, registers); 289 registers.object1 = msg; 290 return endPosition; 291 } 292 293 /** Decodes a repeated 32-bit varint field. Returns the position after all read values. */ decodeVarint32List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)294 static int decodeVarint32List( 295 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 296 final IntArrayList output = (IntArrayList) list; 297 position = decodeVarint32(data, position, registers); 298 output.addInt(registers.int1); 299 while (position < limit) { 300 int nextPosition = decodeVarint32(data, position, registers); 301 if (tag != registers.int1) { 302 break; 303 } 304 position = decodeVarint32(data, nextPosition, registers); 305 output.addInt(registers.int1); 306 } 307 return position; 308 } 309 310 /** Decodes a repeated 64-bit varint field. Returns the position after all read values. */ decodeVarint64List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)311 static int decodeVarint64List( 312 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 313 final LongArrayList output = (LongArrayList) list; 314 position = decodeVarint64(data, position, registers); 315 output.addLong(registers.long1); 316 while (position < limit) { 317 int nextPosition = decodeVarint32(data, position, registers); 318 if (tag != registers.int1) { 319 break; 320 } 321 position = decodeVarint64(data, nextPosition, registers); 322 output.addLong(registers.long1); 323 } 324 return position; 325 } 326 327 /** Decodes a repeated fixed32 field. Returns the position after all read values. */ decodeFixed32List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)328 static int decodeFixed32List( 329 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 330 final IntArrayList output = (IntArrayList) list; 331 output.addInt(decodeFixed32(data, position)); 332 position += 4; 333 while (position < limit) { 334 int nextPosition = decodeVarint32(data, position, registers); 335 if (tag != registers.int1) { 336 break; 337 } 338 output.addInt(decodeFixed32(data, nextPosition)); 339 position = nextPosition + 4; 340 } 341 return position; 342 } 343 344 /** Decodes a repeated fixed64 field. Returns the position after all read values. */ decodeFixed64List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)345 static int decodeFixed64List( 346 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 347 final LongArrayList output = (LongArrayList) list; 348 output.addLong(decodeFixed64(data, position)); 349 position += 8; 350 while (position < limit) { 351 int nextPosition = decodeVarint32(data, position, registers); 352 if (tag != registers.int1) { 353 break; 354 } 355 output.addLong(decodeFixed64(data, nextPosition)); 356 position = nextPosition + 8; 357 } 358 return position; 359 } 360 361 /** Decodes a repeated float field. Returns the position after all read values. */ decodeFloatList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)362 static int decodeFloatList( 363 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 364 final FloatArrayList output = (FloatArrayList) list; 365 output.addFloat(decodeFloat(data, position)); 366 position += 4; 367 while (position < limit) { 368 int nextPosition = decodeVarint32(data, position, registers); 369 if (tag != registers.int1) { 370 break; 371 } 372 output.addFloat(decodeFloat(data, nextPosition)); 373 position = nextPosition + 4; 374 } 375 return position; 376 } 377 378 /** Decodes a repeated double field. Returns the position after all read values. */ decodeDoubleList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)379 static int decodeDoubleList( 380 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 381 final DoubleArrayList output = (DoubleArrayList) list; 382 output.addDouble(decodeDouble(data, position)); 383 position += 8; 384 while (position < limit) { 385 int nextPosition = decodeVarint32(data, position, registers); 386 if (tag != registers.int1) { 387 break; 388 } 389 output.addDouble(decodeDouble(data, nextPosition)); 390 position = nextPosition + 8; 391 } 392 return position; 393 } 394 395 /** Decodes a repeated boolean field. Returns the position after all read values. */ decodeBoolList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)396 static int decodeBoolList( 397 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 398 final BooleanArrayList output = (BooleanArrayList) list; 399 position = decodeVarint64(data, position, registers); 400 output.addBoolean(registers.long1 != 0); 401 while (position < limit) { 402 int nextPosition = decodeVarint32(data, position, registers); 403 if (tag != registers.int1) { 404 break; 405 } 406 position = decodeVarint64(data, nextPosition, registers); 407 output.addBoolean(registers.long1 != 0); 408 } 409 return position; 410 } 411 412 /** Decodes a repeated sint32 field. Returns the position after all read values. */ decodeSInt32List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)413 static int decodeSInt32List( 414 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 415 final IntArrayList output = (IntArrayList) list; 416 position = decodeVarint32(data, position, registers); 417 output.addInt(CodedInputStream.decodeZigZag32(registers.int1)); 418 while (position < limit) { 419 int nextPosition = decodeVarint32(data, position, registers); 420 if (tag != registers.int1) { 421 break; 422 } 423 position = decodeVarint32(data, nextPosition, registers); 424 output.addInt(CodedInputStream.decodeZigZag32(registers.int1)); 425 } 426 return position; 427 } 428 429 /** Decodes a repeated sint64 field. Returns the position after all read values. */ decodeSInt64List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)430 static int decodeSInt64List( 431 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 432 final LongArrayList output = (LongArrayList) list; 433 position = decodeVarint64(data, position, registers); 434 output.addLong(CodedInputStream.decodeZigZag64(registers.long1)); 435 while (position < limit) { 436 int nextPosition = decodeVarint32(data, position, registers); 437 if (tag != registers.int1) { 438 break; 439 } 440 position = decodeVarint64(data, nextPosition, registers); 441 output.addLong(CodedInputStream.decodeZigZag64(registers.long1)); 442 } 443 return position; 444 } 445 446 /** Decodes a packed 32-bit varint field. Returns the position after all read values. */ decodePackedVarint32List( byte[] data, int position, ProtobufList<?> list, Registers registers)447 static int decodePackedVarint32List( 448 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 449 final IntArrayList output = (IntArrayList) list; 450 position = decodeVarint32(data, position, registers); 451 final int fieldLimit = position + registers.int1; 452 while (position < fieldLimit) { 453 position = decodeVarint32(data, position, registers); 454 output.addInt(registers.int1); 455 } 456 if (position != fieldLimit) { 457 throw InvalidProtocolBufferException.truncatedMessage(); 458 } 459 return position; 460 } 461 462 /** Decodes a packed 64-bit varint field. Returns the position after all read values. */ decodePackedVarint64List( byte[] data, int position, ProtobufList<?> list, Registers registers)463 static int decodePackedVarint64List( 464 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 465 final LongArrayList output = (LongArrayList) list; 466 position = decodeVarint32(data, position, registers); 467 final int fieldLimit = position + registers.int1; 468 while (position < fieldLimit) { 469 position = decodeVarint64(data, position, registers); 470 output.addLong(registers.long1); 471 } 472 if (position != fieldLimit) { 473 throw InvalidProtocolBufferException.truncatedMessage(); 474 } 475 return position; 476 } 477 478 /** Decodes a packed fixed32 field. Returns the position after all read values. */ decodePackedFixed32List( byte[] data, int position, ProtobufList<?> list, Registers registers)479 static int decodePackedFixed32List( 480 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 481 final IntArrayList output = (IntArrayList) list; 482 position = decodeVarint32(data, position, registers); 483 final int fieldLimit = position + registers.int1; 484 while (position < fieldLimit) { 485 output.addInt(decodeFixed32(data, position)); 486 position += 4; 487 } 488 if (position != fieldLimit) { 489 throw InvalidProtocolBufferException.truncatedMessage(); 490 } 491 return position; 492 } 493 494 /** Decodes a packed fixed64 field. Returns the position after all read values. */ decodePackedFixed64List( byte[] data, int position, ProtobufList<?> list, Registers registers)495 static int decodePackedFixed64List( 496 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 497 final LongArrayList output = (LongArrayList) list; 498 position = decodeVarint32(data, position, registers); 499 final int fieldLimit = position + registers.int1; 500 while (position < fieldLimit) { 501 output.addLong(decodeFixed64(data, position)); 502 position += 8; 503 } 504 if (position != fieldLimit) { 505 throw InvalidProtocolBufferException.truncatedMessage(); 506 } 507 return position; 508 } 509 510 /** Decodes a packed float field. Returns the position after all read values. */ decodePackedFloatList( byte[] data, int position, ProtobufList<?> list, Registers registers)511 static int decodePackedFloatList( 512 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 513 final FloatArrayList output = (FloatArrayList) list; 514 position = decodeVarint32(data, position, registers); 515 final int fieldLimit = position + registers.int1; 516 while (position < fieldLimit) { 517 output.addFloat(decodeFloat(data, position)); 518 position += 4; 519 } 520 if (position != fieldLimit) { 521 throw InvalidProtocolBufferException.truncatedMessage(); 522 } 523 return position; 524 } 525 526 /** Decodes a packed double field. Returns the position after all read values. */ decodePackedDoubleList( byte[] data, int position, ProtobufList<?> list, Registers registers)527 static int decodePackedDoubleList( 528 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 529 final DoubleArrayList output = (DoubleArrayList) list; 530 position = decodeVarint32(data, position, registers); 531 final int fieldLimit = position + registers.int1; 532 while (position < fieldLimit) { 533 output.addDouble(decodeDouble(data, position)); 534 position += 8; 535 } 536 if (position != fieldLimit) { 537 throw InvalidProtocolBufferException.truncatedMessage(); 538 } 539 return position; 540 } 541 542 /** Decodes a packed boolean field. Returns the position after all read values. */ decodePackedBoolList( byte[] data, int position, ProtobufList<?> list, Registers registers)543 static int decodePackedBoolList( 544 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 545 final BooleanArrayList output = (BooleanArrayList) list; 546 position = decodeVarint32(data, position, registers); 547 final int fieldLimit = position + registers.int1; 548 while (position < fieldLimit) { 549 position = decodeVarint64(data, position, registers); 550 output.addBoolean(registers.long1 != 0); 551 } 552 if (position != fieldLimit) { 553 throw InvalidProtocolBufferException.truncatedMessage(); 554 } 555 return position; 556 } 557 558 /** Decodes a packed sint32 field. Returns the position after all read values. */ decodePackedSInt32List( byte[] data, int position, ProtobufList<?> list, Registers registers)559 static int decodePackedSInt32List( 560 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 561 final IntArrayList output = (IntArrayList) list; 562 position = decodeVarint32(data, position, registers); 563 final int fieldLimit = position + registers.int1; 564 while (position < fieldLimit) { 565 position = decodeVarint32(data, position, registers); 566 output.addInt(CodedInputStream.decodeZigZag32(registers.int1)); 567 } 568 if (position != fieldLimit) { 569 throw InvalidProtocolBufferException.truncatedMessage(); 570 } 571 return position; 572 } 573 574 /** Decodes a packed sint64 field. Returns the position after all read values. */ 575 @SuppressWarnings("unchecked") decodePackedSInt64List( byte[] data, int position, ProtobufList<?> list, Registers registers)576 static int decodePackedSInt64List( 577 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 578 final LongArrayList output = (LongArrayList) list; 579 position = decodeVarint32(data, position, registers); 580 final int fieldLimit = position + registers.int1; 581 while (position < fieldLimit) { 582 position = decodeVarint64(data, position, registers); 583 output.addLong(CodedInputStream.decodeZigZag64(registers.long1)); 584 } 585 if (position != fieldLimit) { 586 throw InvalidProtocolBufferException.truncatedMessage(); 587 } 588 return position; 589 } 590 591 /** Decodes a repeated string field. Returns the position after all read values. */ 592 @SuppressWarnings("unchecked") decodeStringList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)593 static int decodeStringList( 594 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) 595 throws InvalidProtocolBufferException { 596 final ProtobufList<String> output = (ProtobufList<String>) list; 597 position = decodeVarint32(data, position, registers); 598 final int length = registers.int1; 599 if (length < 0) { 600 throw InvalidProtocolBufferException.negativeSize(); 601 } else if (length == 0) { 602 output.add(""); 603 } else { 604 String value = new String(data, position, length, Internal.UTF_8); 605 output.add(value); 606 position += length; 607 } 608 while (position < limit) { 609 int nextPosition = decodeVarint32(data, position, registers); 610 if (tag != registers.int1) { 611 break; 612 } 613 position = decodeVarint32(data, nextPosition, registers); 614 final int nextLength = registers.int1; 615 if (nextLength < 0) { 616 throw InvalidProtocolBufferException.negativeSize(); 617 } else if (nextLength == 0) { 618 output.add(""); 619 } else { 620 String value = new String(data, position, nextLength, Internal.UTF_8); 621 output.add(value); 622 position += nextLength; 623 } 624 } 625 return position; 626 } 627 628 /** 629 * Decodes a repeated string field with utf8 check. Returns the position after all read values. 630 */ 631 @SuppressWarnings("unchecked") decodeStringListRequireUtf8( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)632 static int decodeStringListRequireUtf8( 633 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) 634 throws InvalidProtocolBufferException { 635 final ProtobufList<String> output = (ProtobufList<String>) list; 636 position = decodeVarint32(data, position, registers); 637 final int length = registers.int1; 638 if (length < 0) { 639 throw InvalidProtocolBufferException.negativeSize(); 640 } else if (length == 0) { 641 output.add(""); 642 } else { 643 if (!Utf8.isValidUtf8(data, position, position + length)) { 644 throw InvalidProtocolBufferException.invalidUtf8(); 645 } 646 String value = new String(data, position, length, Internal.UTF_8); 647 output.add(value); 648 position += length; 649 } 650 while (position < limit) { 651 int nextPosition = decodeVarint32(data, position, registers); 652 if (tag != registers.int1) { 653 break; 654 } 655 position = decodeVarint32(data, nextPosition, registers); 656 final int nextLength = registers.int1; 657 if (nextLength < 0) { 658 throw InvalidProtocolBufferException.negativeSize(); 659 } else if (nextLength == 0) { 660 output.add(""); 661 } else { 662 if (!Utf8.isValidUtf8(data, position, position + nextLength)) { 663 throw InvalidProtocolBufferException.invalidUtf8(); 664 } 665 String value = new String(data, position, nextLength, Internal.UTF_8); 666 output.add(value); 667 position += nextLength; 668 } 669 } 670 return position; 671 } 672 673 /** Decodes a repeated bytes field. Returns the position after all read values. */ 674 @SuppressWarnings("unchecked") decodeBytesList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)675 static int decodeBytesList( 676 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) 677 throws InvalidProtocolBufferException { 678 final ProtobufList<ByteString> output = (ProtobufList<ByteString>) list; 679 position = decodeVarint32(data, position, registers); 680 final int length = registers.int1; 681 if (length < 0) { 682 throw InvalidProtocolBufferException.negativeSize(); 683 } else if (length > data.length - position) { 684 throw InvalidProtocolBufferException.truncatedMessage(); 685 } else if (length == 0) { 686 output.add(ByteString.EMPTY); 687 } else { 688 output.add(ByteString.copyFrom(data, position, length)); 689 position += length; 690 } 691 while (position < limit) { 692 int nextPosition = decodeVarint32(data, position, registers); 693 if (tag != registers.int1) { 694 break; 695 } 696 position = decodeVarint32(data, nextPosition, registers); 697 final int nextLength = registers.int1; 698 if (nextLength < 0) { 699 throw InvalidProtocolBufferException.negativeSize(); 700 } else if (nextLength > data.length - position) { 701 throw InvalidProtocolBufferException.truncatedMessage(); 702 } else if (nextLength == 0) { 703 output.add(ByteString.EMPTY); 704 } else { 705 output.add(ByteString.copyFrom(data, position, nextLength)); 706 position += nextLength; 707 } 708 } 709 return position; 710 } 711 712 /** 713 * Decodes a repeated message field 714 * 715 * @return The position of after read all messages 716 */ 717 @SuppressWarnings({"unchecked"}) decodeMessageList( Schema<?> schema, int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)718 static int decodeMessageList( 719 Schema<?> schema, 720 int tag, 721 byte[] data, 722 int position, 723 int limit, 724 ProtobufList<?> list, 725 Registers registers) 726 throws IOException { 727 final ProtobufList<Object> output = (ProtobufList<Object>) list; 728 position = decodeMessageField(schema, data, position, limit, registers); 729 output.add(registers.object1); 730 while (position < limit) { 731 int nextPosition = decodeVarint32(data, position, registers); 732 if (tag != registers.int1) { 733 break; 734 } 735 position = decodeMessageField(schema, data, nextPosition, limit, registers); 736 output.add(registers.object1); 737 } 738 return position; 739 } 740 741 /** 742 * Decodes a repeated group field 743 * 744 * @return The position of after read all groups 745 */ 746 @SuppressWarnings({"unchecked", "rawtypes"}) decodeGroupList( Schema schema, int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)747 static int decodeGroupList( 748 Schema schema, 749 int tag, 750 byte[] data, 751 int position, 752 int limit, 753 ProtobufList<?> list, 754 Registers registers) 755 throws IOException { 756 final ProtobufList<Object> output = (ProtobufList<Object>) list; 757 final int endgroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; 758 position = decodeGroupField(schema, data, position, limit, endgroup, registers); 759 output.add(registers.object1); 760 while (position < limit) { 761 int nextPosition = decodeVarint32(data, position, registers); 762 if (tag != registers.int1) { 763 break; 764 } 765 position = decodeGroupField(schema, data, nextPosition, limit, endgroup, registers); 766 output.add(registers.object1); 767 } 768 return position; 769 } 770 decodeExtensionOrUnknownField( int tag, byte[] data, int position, int limit, Object message, MessageLite defaultInstance, UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, Registers registers)771 static int decodeExtensionOrUnknownField( 772 int tag, byte[] data, int position, int limit, 773 Object message, 774 MessageLite defaultInstance, 775 UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, 776 Registers registers) 777 throws IOException { 778 final int number = tag >>> 3; 779 GeneratedMessageLite.GeneratedExtension extension = 780 registers.extensionRegistry.findLiteExtensionByNumber(defaultInstance, number); 781 if (extension == null) { 782 return decodeUnknownField( 783 tag, data, position, limit, getMutableUnknownFields(message), registers); 784 } else { 785 ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).ensureExtensionsAreMutable(); 786 return decodeExtension( 787 tag, data, position, limit, (GeneratedMessageLite.ExtendableMessage) message, 788 extension, unknownFieldSchema, registers); 789 } 790 } 791 decodeExtension( int tag, byte[] data, int position, int limit, GeneratedMessageLite.ExtendableMessage<?, ?> message, GeneratedMessageLite.GeneratedExtension<?, ?> extension, UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, Registers registers)792 static int decodeExtension( 793 int tag, 794 byte[] data, 795 int position, 796 int limit, 797 GeneratedMessageLite.ExtendableMessage<?, ?> message, 798 GeneratedMessageLite.GeneratedExtension<?, ?> extension, 799 UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, 800 Registers registers) 801 throws IOException { 802 final FieldSet<GeneratedMessageLite.ExtensionDescriptor> extensions = message.extensions; 803 final int fieldNumber = tag >>> 3; 804 if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) { 805 switch (extension.getLiteType()) { 806 case DOUBLE: 807 { 808 DoubleArrayList list = new DoubleArrayList(); 809 position = decodePackedDoubleList(data, position, list, registers); 810 extensions.setField(extension.descriptor, list); 811 break; 812 } 813 case FLOAT: 814 { 815 FloatArrayList list = new FloatArrayList(); 816 position = decodePackedFloatList(data, position, list, registers); 817 extensions.setField(extension.descriptor, list); 818 break; 819 } 820 case INT64: 821 case UINT64: 822 { 823 LongArrayList list = new LongArrayList(); 824 position = decodePackedVarint64List(data, position, list, registers); 825 extensions.setField(extension.descriptor, list); 826 break; 827 } 828 case INT32: 829 case UINT32: 830 { 831 IntArrayList list = new IntArrayList(); 832 position = decodePackedVarint32List(data, position, list, registers); 833 extensions.setField(extension.descriptor, list); 834 break; 835 } 836 case FIXED64: 837 case SFIXED64: 838 { 839 LongArrayList list = new LongArrayList(); 840 position = decodePackedFixed64List(data, position, list, registers); 841 extensions.setField(extension.descriptor, list); 842 break; 843 } 844 case FIXED32: 845 case SFIXED32: 846 { 847 IntArrayList list = new IntArrayList(); 848 position = decodePackedFixed32List(data, position, list, registers); 849 extensions.setField(extension.descriptor, list); 850 break; 851 } 852 case BOOL: 853 { 854 BooleanArrayList list = new BooleanArrayList(); 855 position = decodePackedBoolList(data, position, list, registers); 856 extensions.setField(extension.descriptor, list); 857 break; 858 } 859 case SINT32: 860 { 861 IntArrayList list = new IntArrayList(); 862 position = decodePackedSInt32List(data, position, list, registers); 863 extensions.setField(extension.descriptor, list); 864 break; 865 } 866 case SINT64: 867 { 868 LongArrayList list = new LongArrayList(); 869 position = decodePackedSInt64List(data, position, list, registers); 870 extensions.setField(extension.descriptor, list); 871 break; 872 } 873 case ENUM: 874 { 875 IntArrayList list = new IntArrayList(); 876 position = decodePackedVarint32List(data, position, list, registers); 877 SchemaUtil.filterUnknownEnumList( 878 message, 879 fieldNumber, 880 list, 881 extension.descriptor.getEnumType(), 882 null, 883 unknownFieldSchema); 884 extensions.setField(extension.descriptor, list); 885 break; 886 } 887 default: 888 throw new IllegalStateException( 889 "Type cannot be packed: " + extension.descriptor.getLiteType()); 890 } 891 } else { 892 Object value = null; 893 // Enum is a special case because unknown enum values will be put into UnknownFieldSetLite. 894 if (extension.getLiteType() == WireFormat.FieldType.ENUM) { 895 position = decodeVarint32(data, position, registers); 896 Object enumValue = extension.descriptor.getEnumType().findValueByNumber(registers.int1); 897 if (enumValue == null) { 898 SchemaUtil.storeUnknownEnum( 899 message, fieldNumber, registers.int1, null, unknownFieldSchema); 900 return position; 901 } 902 // Note, we store the integer value instead of the actual enum object in FieldSet. 903 // This is also different from full-runtime where we store EnumValueDescriptor. 904 value = registers.int1; 905 } else { 906 switch (extension.getLiteType()) { 907 case DOUBLE: 908 value = decodeDouble(data, position); 909 position += 8; 910 break; 911 case FLOAT: 912 value = decodeFloat(data, position); 913 position += 4; 914 break; 915 case INT64: 916 case UINT64: 917 position = decodeVarint64(data, position, registers); 918 value = registers.long1; 919 break; 920 case INT32: 921 case UINT32: 922 position = decodeVarint32(data, position, registers); 923 value = registers.int1; 924 break; 925 case FIXED64: 926 case SFIXED64: 927 value = decodeFixed64(data, position); 928 position += 8; 929 break; 930 case FIXED32: 931 case SFIXED32: 932 value = decodeFixed32(data, position); 933 position += 4; 934 break; 935 case BOOL: 936 position = decodeVarint64(data, position, registers); 937 value = (registers.long1 != 0); 938 break; 939 case BYTES: 940 position = decodeBytes(data, position, registers); 941 value = registers.object1; 942 break; 943 case SINT32: 944 position = decodeVarint32(data, position, registers); 945 value = CodedInputStream.decodeZigZag32(registers.int1); 946 break; 947 case SINT64: 948 position = decodeVarint64(data, position, registers); 949 value = CodedInputStream.decodeZigZag64(registers.long1); 950 break; 951 case STRING: 952 position = decodeString(data, position, registers); 953 value = registers.object1; 954 break; 955 case GROUP: 956 { 957 final int endTag = (fieldNumber << 3) | WireFormat.WIRETYPE_END_GROUP; 958 final Schema fieldSchema = 959 Protobuf.getInstance() 960 .schemaFor(extension.getMessageDefaultInstance().getClass()); 961 if (extension.isRepeated()) { 962 position = decodeGroupField(fieldSchema, data, position, limit, endTag, registers); 963 extensions.addRepeatedField(extension.descriptor, registers.object1); 964 } else { 965 Object oldValue = extensions.getField(extension.descriptor); 966 if (oldValue == null) { 967 oldValue = fieldSchema.newInstance(); 968 extensions.setField(extension.descriptor, oldValue); 969 } 970 position = 971 mergeGroupField( 972 oldValue, fieldSchema, data, position, limit, endTag, registers); 973 } 974 return position; 975 } 976 case MESSAGE: 977 { 978 final Schema fieldSchema = 979 Protobuf.getInstance() 980 .schemaFor(extension.getMessageDefaultInstance().getClass()); 981 if (extension.isRepeated()) { 982 position = decodeMessageField(fieldSchema, data, position, limit, registers); 983 extensions.addRepeatedField(extension.descriptor, registers.object1); 984 } else { 985 Object oldValue = extensions.getField(extension.descriptor); 986 if (oldValue == null) { 987 oldValue = fieldSchema.newInstance(); 988 extensions.setField(extension.descriptor, oldValue); 989 } 990 position = 991 mergeMessageField(oldValue, fieldSchema, data, position, limit, registers); 992 } 993 return position; 994 } 995 case ENUM: 996 throw new IllegalStateException("Shouldn't reach here."); 997 } 998 } 999 if (extension.isRepeated()) { 1000 extensions.addRepeatedField(extension.descriptor, value); 1001 } else { 1002 extensions.setField(extension.descriptor, value); 1003 } 1004 } 1005 return position; 1006 } 1007 1008 /** Decodes an unknown field. */ decodeUnknownField( int tag, byte[] data, int position, int limit, UnknownFieldSetLite unknownFields, Registers registers)1009 static int decodeUnknownField( 1010 int tag, 1011 byte[] data, 1012 int position, 1013 int limit, 1014 UnknownFieldSetLite unknownFields, 1015 Registers registers) 1016 throws InvalidProtocolBufferException { 1017 if (WireFormat.getTagFieldNumber(tag) == 0) { 1018 throw InvalidProtocolBufferException.invalidTag(); 1019 } 1020 switch (WireFormat.getTagWireType(tag)) { 1021 case WireFormat.WIRETYPE_VARINT: 1022 position = decodeVarint64(data, position, registers); 1023 unknownFields.storeField(tag, registers.long1); 1024 return position; 1025 case WireFormat.WIRETYPE_FIXED32: 1026 unknownFields.storeField(tag, decodeFixed32(data, position)); 1027 return position + 4; 1028 case WireFormat.WIRETYPE_FIXED64: 1029 unknownFields.storeField(tag, decodeFixed64(data, position)); 1030 return position + 8; 1031 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 1032 position = decodeVarint32(data, position, registers); 1033 final int length = registers.int1; 1034 if (length < 0) { 1035 throw InvalidProtocolBufferException.negativeSize(); 1036 } else if (length > data.length - position) { 1037 throw InvalidProtocolBufferException.truncatedMessage(); 1038 } else if (length == 0) { 1039 unknownFields.storeField(tag, ByteString.EMPTY); 1040 } else { 1041 unknownFields.storeField(tag, ByteString.copyFrom(data, position, length)); 1042 } 1043 return position + length; 1044 case WireFormat.WIRETYPE_START_GROUP: 1045 final UnknownFieldSetLite child = UnknownFieldSetLite.newInstance(); 1046 final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; 1047 int lastTag = 0; 1048 while (position < limit) { 1049 position = decodeVarint32(data, position, registers); 1050 lastTag = registers.int1; 1051 if (lastTag == endGroup) { 1052 break; 1053 } 1054 position = decodeUnknownField(lastTag, data, position, limit, child, registers); 1055 } 1056 if (position > limit || lastTag != endGroup) { 1057 throw InvalidProtocolBufferException.parseFailure(); 1058 } 1059 unknownFields.storeField(tag, child); 1060 return position; 1061 default: 1062 throw InvalidProtocolBufferException.invalidTag(); 1063 } 1064 } 1065 1066 /** Skips an unknown field. */ skipField(int tag, byte[] data, int position, int limit, Registers registers)1067 static int skipField(int tag, byte[] data, int position, int limit, Registers registers) 1068 throws InvalidProtocolBufferException { 1069 if (WireFormat.getTagFieldNumber(tag) == 0) { 1070 throw InvalidProtocolBufferException.invalidTag(); 1071 } 1072 switch (WireFormat.getTagWireType(tag)) { 1073 case WireFormat.WIRETYPE_VARINT: 1074 position = decodeVarint64(data, position, registers); 1075 return position; 1076 case WireFormat.WIRETYPE_FIXED32: 1077 return position + 4; 1078 case WireFormat.WIRETYPE_FIXED64: 1079 return position + 8; 1080 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 1081 position = decodeVarint32(data, position, registers); 1082 return position + registers.int1; 1083 case WireFormat.WIRETYPE_START_GROUP: 1084 final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; 1085 int lastTag = 0; 1086 while (position < limit) { 1087 position = decodeVarint32(data, position, registers); 1088 lastTag = registers.int1; 1089 if (lastTag == endGroup) { 1090 break; 1091 } 1092 position = skipField(lastTag, data, position, limit, registers); 1093 } 1094 if (position > limit || lastTag != endGroup) { 1095 throw InvalidProtocolBufferException.parseFailure(); 1096 } 1097 return position; 1098 default: 1099 throw InvalidProtocolBufferException.invalidTag(); 1100 } 1101 } 1102 } 1103