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