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