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 com.google.protobuf.FieldSet.FieldDescriptorLite; 34 import com.google.protobuf.Internal.EnumLiteMap; 35 import com.google.protobuf.Internal.EnumVerifier; 36 import java.io.IOException; 37 import java.lang.reflect.Field; 38 import java.util.Iterator; 39 import java.util.List; 40 import java.util.RandomAccess; 41 42 /** Helper methods used by schemas. */ 43 @ExperimentalApi 44 final class SchemaUtil { 45 private static final Class<?> GENERATED_MESSAGE_CLASS = getGeneratedMessageClass(); 46 private static final UnknownFieldSchema<?, ?> PROTO2_UNKNOWN_FIELD_SET_SCHEMA = 47 getUnknownFieldSetSchema(false); 48 private static final UnknownFieldSchema<?, ?> PROTO3_UNKNOWN_FIELD_SET_SCHEMA = 49 getUnknownFieldSetSchema(true); 50 private static final UnknownFieldSchema<?, ?> UNKNOWN_FIELD_SET_LITE_SCHEMA = 51 new UnknownFieldSetLiteSchema(); 52 53 private static final int DEFAULT_LOOK_UP_START_NUMBER = 40; 54 SchemaUtil()55 private SchemaUtil() {} 56 57 /** 58 * Requires that the given message extend {@link com.google.protobuf.GeneratedMessageV3} or {@link 59 * GeneratedMessageLite}. 60 */ requireGeneratedMessage(Class<?> messageType)61 public static void requireGeneratedMessage(Class<?> messageType) { 62 if (!GeneratedMessageLite.class.isAssignableFrom(messageType) 63 && GENERATED_MESSAGE_CLASS != null 64 && !GENERATED_MESSAGE_CLASS.isAssignableFrom(messageType)) { 65 throw new IllegalArgumentException( 66 "Message classes must extend GeneratedMessage or GeneratedMessageLite"); 67 } 68 } 69 writeDouble(int fieldNumber, double value, Writer writer)70 public static void writeDouble(int fieldNumber, double value, Writer writer) throws IOException { 71 if (Double.compare(value, 0.0) != 0) { 72 writer.writeDouble(fieldNumber, value); 73 } 74 } 75 writeFloat(int fieldNumber, float value, Writer writer)76 public static void writeFloat(int fieldNumber, float value, Writer writer) throws IOException { 77 if (Float.compare(value, 0.0f) != 0) { 78 writer.writeFloat(fieldNumber, value); 79 } 80 } 81 writeInt64(int fieldNumber, long value, Writer writer)82 public static void writeInt64(int fieldNumber, long value, Writer writer) throws IOException { 83 if (value != 0) { 84 writer.writeInt64(fieldNumber, value); 85 } 86 } 87 writeUInt64(int fieldNumber, long value, Writer writer)88 public static void writeUInt64(int fieldNumber, long value, Writer writer) throws IOException { 89 if (value != 0) { 90 writer.writeUInt64(fieldNumber, value); 91 } 92 } 93 writeSInt64(int fieldNumber, long value, Writer writer)94 public static void writeSInt64(int fieldNumber, long value, Writer writer) throws IOException { 95 if (value != 0) { 96 writer.writeSInt64(fieldNumber, value); 97 } 98 } 99 writeFixed64(int fieldNumber, long value, Writer writer)100 public static void writeFixed64(int fieldNumber, long value, Writer writer) throws IOException { 101 if (value != 0) { 102 writer.writeFixed64(fieldNumber, value); 103 } 104 } 105 writeSFixed64(int fieldNumber, long value, Writer writer)106 public static void writeSFixed64(int fieldNumber, long value, Writer writer) throws IOException { 107 if (value != 0) { 108 writer.writeSFixed64(fieldNumber, value); 109 } 110 } 111 writeInt32(int fieldNumber, int value, Writer writer)112 public static void writeInt32(int fieldNumber, int value, Writer writer) throws IOException { 113 if (value != 0) { 114 writer.writeInt32(fieldNumber, value); 115 } 116 } 117 writeUInt32(int fieldNumber, int value, Writer writer)118 public static void writeUInt32(int fieldNumber, int value, Writer writer) throws IOException { 119 if (value != 0) { 120 writer.writeUInt32(fieldNumber, value); 121 } 122 } 123 writeSInt32(int fieldNumber, int value, Writer writer)124 public static void writeSInt32(int fieldNumber, int value, Writer writer) throws IOException { 125 if (value != 0) { 126 writer.writeSInt32(fieldNumber, value); 127 } 128 } 129 writeFixed32(int fieldNumber, int value, Writer writer)130 public static void writeFixed32(int fieldNumber, int value, Writer writer) throws IOException { 131 if (value != 0) { 132 writer.writeFixed32(fieldNumber, value); 133 } 134 } 135 writeSFixed32(int fieldNumber, int value, Writer writer)136 public static void writeSFixed32(int fieldNumber, int value, Writer writer) throws IOException { 137 if (value != 0) { 138 writer.writeSFixed32(fieldNumber, value); 139 } 140 } 141 writeEnum(int fieldNumber, int value, Writer writer)142 public static void writeEnum(int fieldNumber, int value, Writer writer) throws IOException { 143 if (value != 0) { 144 writer.writeEnum(fieldNumber, value); 145 } 146 } 147 writeBool(int fieldNumber, boolean value, Writer writer)148 public static void writeBool(int fieldNumber, boolean value, Writer writer) throws IOException { 149 if (value) { 150 writer.writeBool(fieldNumber, true); 151 } 152 } 153 writeString(int fieldNumber, Object value, Writer writer)154 public static void writeString(int fieldNumber, Object value, Writer writer) throws IOException { 155 if (value instanceof String) { 156 writeStringInternal(fieldNumber, (String) value, writer); 157 } else { 158 writeBytes(fieldNumber, (ByteString) value, writer); 159 } 160 } 161 writeStringInternal(int fieldNumber, String value, Writer writer)162 private static void writeStringInternal(int fieldNumber, String value, Writer writer) 163 throws IOException { 164 if (value != null && !value.isEmpty()) { 165 writer.writeString(fieldNumber, value); 166 } 167 } 168 writeBytes(int fieldNumber, ByteString value, Writer writer)169 public static void writeBytes(int fieldNumber, ByteString value, Writer writer) 170 throws IOException { 171 if (value != null && !value.isEmpty()) { 172 writer.writeBytes(fieldNumber, value); 173 } 174 } 175 writeMessage(int fieldNumber, Object value, Writer writer)176 public static void writeMessage(int fieldNumber, Object value, Writer writer) throws IOException { 177 if (value != null) { 178 writer.writeMessage(fieldNumber, value); 179 } 180 } 181 writeDoubleList( int fieldNumber, List<Double> value, Writer writer, boolean packed)182 public static void writeDoubleList( 183 int fieldNumber, List<Double> value, Writer writer, boolean packed) throws IOException { 184 if (value != null && !value.isEmpty()) { 185 writer.writeDoubleList(fieldNumber, value, packed); 186 } 187 } 188 writeFloatList( int fieldNumber, List<Float> value, Writer writer, boolean packed)189 public static void writeFloatList( 190 int fieldNumber, List<Float> value, Writer writer, boolean packed) throws IOException { 191 if (value != null && !value.isEmpty()) { 192 writer.writeFloatList(fieldNumber, value, packed); 193 } 194 } 195 writeInt64List( int fieldNumber, List<Long> value, Writer writer, boolean packed)196 public static void writeInt64List( 197 int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException { 198 if (value != null && !value.isEmpty()) { 199 writer.writeInt64List(fieldNumber, value, packed); 200 } 201 } 202 writeUInt64List( int fieldNumber, List<Long> value, Writer writer, boolean packed)203 public static void writeUInt64List( 204 int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException { 205 if (value != null && !value.isEmpty()) { 206 writer.writeUInt64List(fieldNumber, value, packed); 207 } 208 } 209 writeSInt64List( int fieldNumber, List<Long> value, Writer writer, boolean packed)210 public static void writeSInt64List( 211 int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException { 212 if (value != null && !value.isEmpty()) { 213 writer.writeSInt64List(fieldNumber, value, packed); 214 } 215 } 216 writeFixed64List( int fieldNumber, List<Long> value, Writer writer, boolean packed)217 public static void writeFixed64List( 218 int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException { 219 if (value != null && !value.isEmpty()) { 220 writer.writeFixed64List(fieldNumber, value, packed); 221 } 222 } 223 writeSFixed64List( int fieldNumber, List<Long> value, Writer writer, boolean packed)224 public static void writeSFixed64List( 225 int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException { 226 if (value != null && !value.isEmpty()) { 227 writer.writeSFixed64List(fieldNumber, value, packed); 228 } 229 } 230 writeInt32List( int fieldNumber, List<Integer> value, Writer writer, boolean packed)231 public static void writeInt32List( 232 int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException { 233 if (value != null && !value.isEmpty()) { 234 writer.writeInt32List(fieldNumber, value, packed); 235 } 236 } 237 writeUInt32List( int fieldNumber, List<Integer> value, Writer writer, boolean packed)238 public static void writeUInt32List( 239 int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException { 240 if (value != null && !value.isEmpty()) { 241 writer.writeUInt32List(fieldNumber, value, packed); 242 } 243 } 244 writeSInt32List( int fieldNumber, List<Integer> value, Writer writer, boolean packed)245 public static void writeSInt32List( 246 int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException { 247 if (value != null && !value.isEmpty()) { 248 writer.writeSInt32List(fieldNumber, value, packed); 249 } 250 } 251 writeFixed32List( int fieldNumber, List<Integer> value, Writer writer, boolean packed)252 public static void writeFixed32List( 253 int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException { 254 if (value != null && !value.isEmpty()) { 255 writer.writeFixed32List(fieldNumber, value, packed); 256 } 257 } 258 writeSFixed32List( int fieldNumber, List<Integer> value, Writer writer, boolean packed)259 public static void writeSFixed32List( 260 int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException { 261 if (value != null && !value.isEmpty()) { 262 writer.writeSFixed32List(fieldNumber, value, packed); 263 } 264 } 265 writeEnumList( int fieldNumber, List<Integer> value, Writer writer, boolean packed)266 public static void writeEnumList( 267 int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException { 268 if (value != null && !value.isEmpty()) { 269 writer.writeEnumList(fieldNumber, value, packed); 270 } 271 } 272 writeBoolList( int fieldNumber, List<Boolean> value, Writer writer, boolean packed)273 public static void writeBoolList( 274 int fieldNumber, List<Boolean> value, Writer writer, boolean packed) throws IOException { 275 if (value != null && !value.isEmpty()) { 276 writer.writeBoolList(fieldNumber, value, packed); 277 } 278 } 279 writeStringList(int fieldNumber, List<String> value, Writer writer)280 public static void writeStringList(int fieldNumber, List<String> value, Writer writer) 281 throws IOException { 282 if (value != null && !value.isEmpty()) { 283 writer.writeStringList(fieldNumber, value); 284 } 285 } 286 writeBytesList(int fieldNumber, List<ByteString> value, Writer writer)287 public static void writeBytesList(int fieldNumber, List<ByteString> value, Writer writer) 288 throws IOException { 289 if (value != null && !value.isEmpty()) { 290 writer.writeBytesList(fieldNumber, value); 291 } 292 } 293 writeMessageList(int fieldNumber, List<?> value, Writer writer)294 public static void writeMessageList(int fieldNumber, List<?> value, Writer writer) 295 throws IOException { 296 if (value != null && !value.isEmpty()) { 297 writer.writeMessageList(fieldNumber, value); 298 } 299 } 300 writeMessageList(int fieldNumber, List<?> value, Writer writer, Schema schema)301 public static void writeMessageList(int fieldNumber, List<?> value, Writer writer, Schema schema) 302 throws IOException { 303 if (value != null && !value.isEmpty()) { 304 writer.writeMessageList(fieldNumber, value, schema); 305 } 306 } 307 writeLazyFieldList(int fieldNumber, List<?> value, Writer writer)308 public static void writeLazyFieldList(int fieldNumber, List<?> value, Writer writer) 309 throws IOException { 310 if (value != null && !value.isEmpty()) { 311 for (Object item : value) { 312 ((LazyFieldLite) item).writeTo(writer, fieldNumber); 313 } 314 } 315 } 316 writeGroupList(int fieldNumber, List<?> value, Writer writer)317 public static void writeGroupList(int fieldNumber, List<?> value, Writer writer) 318 throws IOException { 319 if (value != null && !value.isEmpty()) { 320 writer.writeGroupList(fieldNumber, value); 321 } 322 } 323 writeGroupList(int fieldNumber, List<?> value, Writer writer, Schema schema)324 public static void writeGroupList(int fieldNumber, List<?> value, Writer writer, Schema schema) 325 throws IOException { 326 if (value != null && !value.isEmpty()) { 327 writer.writeGroupList(fieldNumber, value, schema); 328 } 329 } 330 computeSizeInt64ListNoTag(List<Long> list)331 static int computeSizeInt64ListNoTag(List<Long> list) { 332 final int length = list.size(); 333 if (length == 0) { 334 return 0; 335 } 336 337 int size = 0; 338 339 if (list instanceof LongArrayList) { 340 final LongArrayList primitiveList = (LongArrayList) list; 341 for (int i = 0; i < length; i++) { 342 size += CodedOutputStream.computeInt64SizeNoTag(primitiveList.getLong(i)); 343 } 344 } else { 345 for (int i = 0; i < length; i++) { 346 size += CodedOutputStream.computeInt64SizeNoTag(list.get(i)); 347 } 348 } 349 return size; 350 } 351 computeSizeInt64List(int fieldNumber, List<Long> list, boolean packed)352 static int computeSizeInt64List(int fieldNumber, List<Long> list, boolean packed) { 353 final int length = list.size(); 354 if (length == 0) { 355 return 0; 356 } 357 int size = computeSizeInt64ListNoTag(list); 358 359 if (packed) { 360 return CodedOutputStream.computeTagSize(fieldNumber) 361 + CodedOutputStream.computeLengthDelimitedFieldSize(size); 362 } else { 363 return size + (list.size() * CodedOutputStream.computeTagSize(fieldNumber)); 364 } 365 } 366 computeSizeUInt64ListNoTag(List<Long> list)367 static int computeSizeUInt64ListNoTag(List<Long> list) { 368 final int length = list.size(); 369 if (length == 0) { 370 return 0; 371 } 372 373 int size = 0; 374 375 if (list instanceof LongArrayList) { 376 final LongArrayList primitiveList = (LongArrayList) list; 377 for (int i = 0; i < length; i++) { 378 size += CodedOutputStream.computeUInt64SizeNoTag(primitiveList.getLong(i)); 379 } 380 } else { 381 for (int i = 0; i < length; i++) { 382 size += CodedOutputStream.computeUInt64SizeNoTag(list.get(i)); 383 } 384 } 385 return size; 386 } 387 computeSizeUInt64List(int fieldNumber, List<Long> list, boolean packed)388 static int computeSizeUInt64List(int fieldNumber, List<Long> list, boolean packed) { 389 final int length = list.size(); 390 if (length == 0) { 391 return 0; 392 } 393 int size = computeSizeUInt64ListNoTag(list); 394 395 if (packed) { 396 return CodedOutputStream.computeTagSize(fieldNumber) 397 + CodedOutputStream.computeLengthDelimitedFieldSize(size); 398 } else { 399 return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); 400 } 401 } 402 computeSizeSInt64ListNoTag(List<Long> list)403 static int computeSizeSInt64ListNoTag(List<Long> list) { 404 final int length = list.size(); 405 if (length == 0) { 406 return 0; 407 } 408 409 int size = 0; 410 411 if (list instanceof LongArrayList) { 412 final LongArrayList primitiveList = (LongArrayList) list; 413 for (int i = 0; i < length; i++) { 414 size += CodedOutputStream.computeSInt64SizeNoTag(primitiveList.getLong(i)); 415 } 416 } else { 417 for (int i = 0; i < length; i++) { 418 size += CodedOutputStream.computeSInt64SizeNoTag(list.get(i)); 419 } 420 } 421 return size; 422 } 423 computeSizeSInt64List(int fieldNumber, List<Long> list, boolean packed)424 static int computeSizeSInt64List(int fieldNumber, List<Long> list, boolean packed) { 425 final int length = list.size(); 426 if (length == 0) { 427 return 0; 428 } 429 int size = computeSizeSInt64ListNoTag(list); 430 431 if (packed) { 432 return CodedOutputStream.computeTagSize(fieldNumber) 433 + CodedOutputStream.computeLengthDelimitedFieldSize(size); 434 } else { 435 return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); 436 } 437 } 438 computeSizeEnumListNoTag(List<Integer> list)439 static int computeSizeEnumListNoTag(List<Integer> list) { 440 final int length = list.size(); 441 if (length == 0) { 442 return 0; 443 } 444 445 int size = 0; 446 447 if (list instanceof IntArrayList) { 448 final IntArrayList primitiveList = (IntArrayList) list; 449 for (int i = 0; i < length; i++) { 450 size += CodedOutputStream.computeEnumSizeNoTag(primitiveList.getInt(i)); 451 } 452 } else { 453 for (int i = 0; i < length; i++) { 454 size += CodedOutputStream.computeEnumSizeNoTag(list.get(i)); 455 } 456 } 457 return size; 458 } 459 computeSizeEnumList(int fieldNumber, List<Integer> list, boolean packed)460 static int computeSizeEnumList(int fieldNumber, List<Integer> list, boolean packed) { 461 final int length = list.size(); 462 if (length == 0) { 463 return 0; 464 } 465 int size = computeSizeEnumListNoTag(list); 466 467 if (packed) { 468 return CodedOutputStream.computeTagSize(fieldNumber) 469 + CodedOutputStream.computeLengthDelimitedFieldSize(size); 470 } else { 471 return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); 472 } 473 } 474 computeSizeInt32ListNoTag(List<Integer> list)475 static int computeSizeInt32ListNoTag(List<Integer> list) { 476 final int length = list.size(); 477 if (length == 0) { 478 return 0; 479 } 480 481 int size = 0; 482 483 if (list instanceof IntArrayList) { 484 final IntArrayList primitiveList = (IntArrayList) list; 485 for (int i = 0; i < length; i++) { 486 size += CodedOutputStream.computeInt32SizeNoTag(primitiveList.getInt(i)); 487 } 488 } else { 489 for (int i = 0; i < length; i++) { 490 size += CodedOutputStream.computeInt32SizeNoTag(list.get(i)); 491 } 492 } 493 return size; 494 } 495 computeSizeInt32List(int fieldNumber, List<Integer> list, boolean packed)496 static int computeSizeInt32List(int fieldNumber, List<Integer> list, boolean packed) { 497 final int length = list.size(); 498 if (length == 0) { 499 return 0; 500 } 501 int size = computeSizeInt32ListNoTag(list); 502 503 if (packed) { 504 return CodedOutputStream.computeTagSize(fieldNumber) 505 + CodedOutputStream.computeLengthDelimitedFieldSize(size); 506 } else { 507 return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); 508 } 509 } 510 computeSizeUInt32ListNoTag(List<Integer> list)511 static int computeSizeUInt32ListNoTag(List<Integer> list) { 512 final int length = list.size(); 513 if (length == 0) { 514 return 0; 515 } 516 517 int size = 0; 518 519 if (list instanceof IntArrayList) { 520 final IntArrayList primitiveList = (IntArrayList) list; 521 for (int i = 0; i < length; i++) { 522 size += CodedOutputStream.computeUInt32SizeNoTag(primitiveList.getInt(i)); 523 } 524 } else { 525 for (int i = 0; i < length; i++) { 526 size += CodedOutputStream.computeUInt32SizeNoTag(list.get(i)); 527 } 528 } 529 return size; 530 } 531 computeSizeUInt32List(int fieldNumber, List<Integer> list, boolean packed)532 static int computeSizeUInt32List(int fieldNumber, List<Integer> list, boolean packed) { 533 final int length = list.size(); 534 if (length == 0) { 535 return 0; 536 } 537 int size = computeSizeUInt32ListNoTag(list); 538 539 if (packed) { 540 return CodedOutputStream.computeTagSize(fieldNumber) 541 + CodedOutputStream.computeLengthDelimitedFieldSize(size); 542 } else { 543 return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); 544 } 545 } 546 computeSizeSInt32ListNoTag(List<Integer> list)547 static int computeSizeSInt32ListNoTag(List<Integer> list) { 548 final int length = list.size(); 549 if (length == 0) { 550 return 0; 551 } 552 553 int size = 0; 554 555 if (list instanceof IntArrayList) { 556 final IntArrayList primitiveList = (IntArrayList) list; 557 for (int i = 0; i < length; i++) { 558 size += CodedOutputStream.computeSInt32SizeNoTag(primitiveList.getInt(i)); 559 } 560 } else { 561 for (int i = 0; i < length; i++) { 562 size += CodedOutputStream.computeSInt32SizeNoTag(list.get(i)); 563 } 564 } 565 return size; 566 } 567 computeSizeSInt32List(int fieldNumber, List<Integer> list, boolean packed)568 static int computeSizeSInt32List(int fieldNumber, List<Integer> list, boolean packed) { 569 final int length = list.size(); 570 if (length == 0) { 571 return 0; 572 } 573 574 int size = computeSizeSInt32ListNoTag(list); 575 576 if (packed) { 577 return CodedOutputStream.computeTagSize(fieldNumber) 578 + CodedOutputStream.computeLengthDelimitedFieldSize(size); 579 } else { 580 return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); 581 } 582 } 583 computeSizeFixed32ListNoTag(List<?> list)584 static int computeSizeFixed32ListNoTag(List<?> list) { 585 return list.size() * WireFormat.FIXED32_SIZE; 586 } 587 computeSizeFixed32List(int fieldNumber, List<?> list, boolean packed)588 static int computeSizeFixed32List(int fieldNumber, List<?> list, boolean packed) { 589 final int length = list.size(); 590 if (length == 0) { 591 return 0; 592 } 593 if (packed) { 594 int dataSize = length * WireFormat.FIXED32_SIZE; 595 return CodedOutputStream.computeTagSize(fieldNumber) 596 + CodedOutputStream.computeLengthDelimitedFieldSize(dataSize); 597 } else { 598 return length * CodedOutputStream.computeFixed32Size(fieldNumber, 0); 599 } 600 } 601 computeSizeFixed64ListNoTag(List<?> list)602 static int computeSizeFixed64ListNoTag(List<?> list) { 603 return list.size() * WireFormat.FIXED64_SIZE; 604 } 605 computeSizeFixed64List(int fieldNumber, List<?> list, boolean packed)606 static int computeSizeFixed64List(int fieldNumber, List<?> list, boolean packed) { 607 final int length = list.size(); 608 if (length == 0) { 609 return 0; 610 } 611 if (packed) { 612 final int dataSize = length * WireFormat.FIXED64_SIZE; 613 return CodedOutputStream.computeTagSize(fieldNumber) 614 + CodedOutputStream.computeLengthDelimitedFieldSize(dataSize); 615 } else { 616 return length * CodedOutputStream.computeFixed64Size(fieldNumber, 0); 617 } 618 } 619 computeSizeBoolListNoTag(List<?> list)620 static int computeSizeBoolListNoTag(List<?> list) { 621 // bools are 1 byte varints 622 return list.size(); 623 } 624 computeSizeBoolList(int fieldNumber, List<?> list, boolean packed)625 static int computeSizeBoolList(int fieldNumber, List<?> list, boolean packed) { 626 final int length = list.size(); 627 if (length == 0) { 628 return 0; 629 } 630 if (packed) { 631 // bools are 1 byte varints 632 return CodedOutputStream.computeTagSize(fieldNumber) 633 + CodedOutputStream.computeLengthDelimitedFieldSize(length); 634 } else { 635 return length * CodedOutputStream.computeBoolSize(fieldNumber, true); 636 } 637 } 638 computeSizeStringList(int fieldNumber, List<?> list)639 static int computeSizeStringList(int fieldNumber, List<?> list) { 640 final int length = list.size(); 641 if (length == 0) { 642 return 0; 643 } 644 int size = length * CodedOutputStream.computeTagSize(fieldNumber); 645 if (list instanceof LazyStringList) { 646 LazyStringList lazyList = ((LazyStringList) list); 647 for (int i = 0; i < length; i++) { 648 Object value = lazyList.getRaw(i); 649 if (value instanceof ByteString) { 650 size += CodedOutputStream.computeBytesSizeNoTag((ByteString) value); 651 } else { 652 size += CodedOutputStream.computeStringSizeNoTag((String) value); 653 } 654 } 655 } else { 656 for (int i = 0; i < length; i++) { 657 Object value = list.get(i); 658 if (value instanceof ByteString) { 659 size += CodedOutputStream.computeBytesSizeNoTag((ByteString) value); 660 } else { 661 size += CodedOutputStream.computeStringSizeNoTag((String) value); 662 } 663 } 664 } 665 return size; 666 } 667 computeSizeMessage(int fieldNumber, Object value, Schema schema)668 static int computeSizeMessage(int fieldNumber, Object value, Schema schema) { 669 if (value instanceof LazyFieldLite) { 670 return CodedOutputStream.computeLazyFieldSize(fieldNumber, (LazyFieldLite) value); 671 } else { 672 return CodedOutputStream.computeMessageSize(fieldNumber, (MessageLite) value, schema); 673 } 674 } 675 computeSizeMessageList(int fieldNumber, List<?> list)676 static int computeSizeMessageList(int fieldNumber, List<?> list) { 677 final int length = list.size(); 678 if (length == 0) { 679 return 0; 680 } 681 int size = length * CodedOutputStream.computeTagSize(fieldNumber); 682 for (int i = 0; i < length; i++) { 683 Object value = list.get(i); 684 if (value instanceof LazyFieldLite) { 685 size += CodedOutputStream.computeLazyFieldSizeNoTag((LazyFieldLite) value); 686 } else { 687 size += CodedOutputStream.computeMessageSizeNoTag((MessageLite) value); 688 } 689 } 690 return size; 691 } 692 computeSizeMessageList(int fieldNumber, List<?> list, Schema schema)693 static int computeSizeMessageList(int fieldNumber, List<?> list, Schema schema) { 694 final int length = list.size(); 695 if (length == 0) { 696 return 0; 697 } 698 int size = length * CodedOutputStream.computeTagSize(fieldNumber); 699 for (int i = 0; i < length; i++) { 700 Object value = list.get(i); 701 if (value instanceof LazyFieldLite) { 702 size += CodedOutputStream.computeLazyFieldSizeNoTag((LazyFieldLite) value); 703 } else { 704 size += CodedOutputStream.computeMessageSizeNoTag((MessageLite) value, schema); 705 } 706 } 707 return size; 708 } 709 computeSizeByteStringList(int fieldNumber, List<ByteString> list)710 static int computeSizeByteStringList(int fieldNumber, List<ByteString> list) { 711 final int length = list.size(); 712 if (length == 0) { 713 return 0; 714 } 715 int size = length * CodedOutputStream.computeTagSize(fieldNumber); 716 for (int i = 0; i < list.size(); i++) { 717 size += CodedOutputStream.computeBytesSizeNoTag(list.get(i)); 718 } 719 return size; 720 } 721 computeSizeGroupList(int fieldNumber, List<MessageLite> list)722 static int computeSizeGroupList(int fieldNumber, List<MessageLite> list) { 723 final int length = list.size(); 724 if (length == 0) { 725 return 0; 726 } 727 int size = 0; 728 for (int i = 0; i < length; i++) { 729 size += CodedOutputStream.computeGroupSize(fieldNumber, list.get(i)); 730 } 731 return size; 732 } 733 computeSizeGroupList(int fieldNumber, List<MessageLite> list, Schema schema)734 static int computeSizeGroupList(int fieldNumber, List<MessageLite> list, Schema schema) { 735 final int length = list.size(); 736 if (length == 0) { 737 return 0; 738 } 739 int size = 0; 740 for (int i = 0; i < length; i++) { 741 size += CodedOutputStream.computeGroupSize(fieldNumber, list.get(i), schema); 742 } 743 return size; 744 } 745 746 /** 747 * Determines whether to issue tableswitch or lookupswitch for the mergeFrom method. 748 * 749 * @see #shouldUseTableSwitch(int, int, int) 750 */ shouldUseTableSwitch(FieldInfo[] fields)751 public static boolean shouldUseTableSwitch(FieldInfo[] fields) { 752 // Determine whether to issue a tableswitch or a lookupswitch 753 // instruction. 754 if (fields.length == 0) { 755 return false; 756 } 757 758 int lo = fields[0].getFieldNumber(); 759 int hi = fields[fields.length - 1].getFieldNumber(); 760 return shouldUseTableSwitch(lo, hi, fields.length); 761 } 762 763 /** 764 * Determines whether to issue tableswitch or lookupswitch for the mergeFrom method. This is based 765 * on the <a href= 766 * "http://hg.openjdk.java.net/jdk8/jdk8/langtools/file/30db5e0aaf83/src/share/classes/com/sun/tools/javac/jvm/Gen.java#l1159"> 767 * logic in the JDK</a>. 768 * 769 * @param lo the lowest fieldNumber contained within the message. 770 * @param hi the highest fieldNumber contained within the message. 771 * @param numFields the total number of fields in the message. 772 * @return {@code true} if tableswitch should be used, rather than lookupswitch. 773 */ shouldUseTableSwitch(int lo, int hi, int numFields)774 public static boolean shouldUseTableSwitch(int lo, int hi, int numFields) { 775 if (hi < DEFAULT_LOOK_UP_START_NUMBER) { 776 return true; 777 } 778 long tableSpaceCost = ((long) hi - lo + 1); // words 779 long tableTimeCost = 3; // comparisons 780 long lookupSpaceCost = 3 + 2 * (long) numFields; 781 long lookupTimeCost = 3 + (long) numFields; 782 return tableSpaceCost + 3 * tableTimeCost <= lookupSpaceCost + 3 * lookupTimeCost; 783 } 784 proto2UnknownFieldSetSchema()785 public static UnknownFieldSchema<?, ?> proto2UnknownFieldSetSchema() { 786 return PROTO2_UNKNOWN_FIELD_SET_SCHEMA; 787 } 788 proto3UnknownFieldSetSchema()789 public static UnknownFieldSchema<?, ?> proto3UnknownFieldSetSchema() { 790 return PROTO3_UNKNOWN_FIELD_SET_SCHEMA; 791 } 792 unknownFieldSetLiteSchema()793 public static UnknownFieldSchema<?, ?> unknownFieldSetLiteSchema() { 794 return UNKNOWN_FIELD_SET_LITE_SCHEMA; 795 } 796 getUnknownFieldSetSchema(boolean proto3)797 private static UnknownFieldSchema<?, ?> getUnknownFieldSetSchema(boolean proto3) { 798 try { 799 Class<?> clz = getUnknownFieldSetSchemaClass(); 800 if (clz == null) { 801 return null; 802 } 803 return (UnknownFieldSchema) clz.getConstructor(boolean.class).newInstance(proto3); 804 } catch (Throwable t) { 805 return null; 806 } 807 } 808 getGeneratedMessageClass()809 private static Class<?> getGeneratedMessageClass() { 810 try { 811 return Class.forName("com.google.protobuf.GeneratedMessageV3"); 812 } catch (Throwable e) { 813 return null; 814 } 815 } 816 getUnknownFieldSetSchemaClass()817 private static Class<?> getUnknownFieldSetSchemaClass() { 818 try { 819 return Class.forName("com.google.protobuf.UnknownFieldSetSchema"); 820 } catch (Throwable e) { 821 return null; 822 } 823 } 824 getMapDefaultEntry(Class<?> clazz, String name)825 static Object getMapDefaultEntry(Class<?> clazz, String name) { 826 try { 827 Class<?> holder = 828 Class.forName(clazz.getName() + "$" + toCamelCase(name, true) + "DefaultEntryHolder"); 829 Field[] fields = holder.getDeclaredFields(); 830 if (fields.length != 1) { 831 throw new IllegalStateException( 832 "Unable to look up map field default entry holder class for " 833 + name 834 + " in " 835 + clazz.getName()); 836 } 837 return UnsafeUtil.getStaticObject(fields[0]); 838 } catch (Throwable t) { 839 throw new RuntimeException(t); 840 } 841 } 842 toCamelCase(String name, boolean capNext)843 static String toCamelCase(String name, boolean capNext) { 844 StringBuilder sb = new StringBuilder(); 845 for (int i = 0; i < name.length(); ++i) { 846 char c = name.charAt(i); 847 // Matches protoc field name function: 848 if ('a' <= c && c <= 'z') { 849 if (capNext) { 850 sb.append((char) (c + ('A' - 'a'))); 851 } else { 852 sb.append(c); 853 } 854 capNext = false; 855 } else if ('A' <= c && c <= 'Z') { 856 if (i == 0 && !capNext) { 857 // Force first letter to lower-case unless explicitly told to capitalize it. 858 sb.append((char) (c - ('A' - 'a'))); 859 } else { 860 sb.append(c); 861 } 862 capNext = false; 863 } else if ('0' <= c && c <= '9') { 864 sb.append(c); 865 capNext = true; 866 } else { 867 capNext = true; 868 } 869 } 870 return sb.toString(); 871 } 872 873 /** Returns true if both are null or both are {@link Object#equals}. */ safeEquals(Object a, Object b)874 static boolean safeEquals(Object a, Object b) { 875 return a == b || (a != null && a.equals(b)); 876 } 877 mergeMap(MapFieldSchema mapFieldSchema, T message, T o, long offset)878 static <T> void mergeMap(MapFieldSchema mapFieldSchema, T message, T o, long offset) { 879 Object merged = 880 mapFieldSchema.mergeFrom( 881 UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(o, offset)); 882 UnsafeUtil.putObject(message, offset, merged); 883 } 884 mergeExtensions( ExtensionSchema<FT> schema, T message, T other)885 static <T, FT extends FieldDescriptorLite<FT>> void mergeExtensions( 886 ExtensionSchema<FT> schema, T message, T other) { 887 FieldSet<FT> otherExtensions = schema.getExtensions(other); 888 if (!otherExtensions.isEmpty()) { 889 FieldSet<FT> messageExtensions = schema.getMutableExtensions(message); 890 messageExtensions.mergeFrom(otherExtensions); 891 } 892 } 893 mergeUnknownFields( UnknownFieldSchema<UT, UB> schema, T message, T other)894 static <T, UT, UB> void mergeUnknownFields( 895 UnknownFieldSchema<UT, UB> schema, T message, T other) { 896 UT messageUnknowns = schema.getFromMessage(message); 897 UT otherUnknowns = schema.getFromMessage(other); 898 UT merged = schema.merge(messageUnknowns, otherUnknowns); 899 schema.setToMessage(message, merged); 900 } 901 902 /** Filters unrecognized enum values in a list. */ filterUnknownEnumList( int number, List<Integer> enumList, EnumLiteMap<?> enumMap, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema)903 static <UT, UB> UB filterUnknownEnumList( 904 int number, 905 List<Integer> enumList, 906 EnumLiteMap<?> enumMap, 907 UB unknownFields, 908 UnknownFieldSchema<UT, UB> unknownFieldSchema) { 909 if (enumMap == null) { 910 return unknownFields; 911 } 912 // TODO(dweis): Specialize for IntArrayList to avoid boxing. 913 if (enumList instanceof RandomAccess) { 914 int writePos = 0; 915 int size = enumList.size(); 916 for (int readPos = 0; readPos < size; ++readPos) { 917 int enumValue = enumList.get(readPos); 918 if (enumMap.findValueByNumber(enumValue) != null) { 919 if (readPos != writePos) { 920 enumList.set(writePos, enumValue); 921 } 922 ++writePos; 923 } else { 924 unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema); 925 } 926 } 927 if (writePos != size) { 928 enumList.subList(writePos, size).clear(); 929 } 930 } else { 931 for (Iterator<Integer> it = enumList.iterator(); it.hasNext(); ) { 932 int enumValue = it.next(); 933 if (enumMap.findValueByNumber(enumValue) == null) { 934 unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema); 935 it.remove(); 936 } 937 } 938 } 939 return unknownFields; 940 } 941 942 /** Filters unrecognized enum values in a list. */ filterUnknownEnumList( int number, List<Integer> enumList, EnumVerifier enumVerifier, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema)943 static <UT, UB> UB filterUnknownEnumList( 944 int number, 945 List<Integer> enumList, 946 EnumVerifier enumVerifier, 947 UB unknownFields, 948 UnknownFieldSchema<UT, UB> unknownFieldSchema) { 949 if (enumVerifier == null) { 950 return unknownFields; 951 } 952 // TODO(dweis): Specialize for IntArrayList to avoid boxing. 953 if (enumList instanceof RandomAccess) { 954 int writePos = 0; 955 int size = enumList.size(); 956 for (int readPos = 0; readPos < size; ++readPos) { 957 int enumValue = enumList.get(readPos); 958 if (enumVerifier.isInRange(enumValue)) { 959 if (readPos != writePos) { 960 enumList.set(writePos, enumValue); 961 } 962 ++writePos; 963 } else { 964 unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema); 965 } 966 } 967 if (writePos != size) { 968 enumList.subList(writePos, size).clear(); 969 } 970 } else { 971 for (Iterator<Integer> it = enumList.iterator(); it.hasNext(); ) { 972 int enumValue = it.next(); 973 if (!enumVerifier.isInRange(enumValue)) { 974 unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema); 975 it.remove(); 976 } 977 } 978 } 979 return unknownFields; 980 } 981 982 /** Stores an unrecognized enum value as an unknown value. */ storeUnknownEnum( int number, int enumValue, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema)983 static <UT, UB> UB storeUnknownEnum( 984 int number, int enumValue, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema) { 985 if (unknownFields == null) { 986 unknownFields = unknownFieldSchema.newBuilder(); 987 } 988 unknownFieldSchema.addVarint(unknownFields, number, enumValue); 989 return unknownFields; 990 } 991 } 992