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.AbstractMessageLite.Builder.LimitedInputStream; 34 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.io.OutputStream; 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 import java.util.Collections; 41 import java.util.List; 42 import java.util.Map; 43 import java.util.TreeMap; 44 45 /** 46 * {@code UnknownFieldSet} is used to keep track of fields which were seen when 47 * parsing a protocol message but whose field numbers or types are unrecognized. 48 * This most frequently occurs when new fields are added to a message type 49 * and then messages containing those fields are read by old software that was 50 * compiled before the new types were added. 51 * 52 * <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every 53 * {@link Message.Builder} contains an {@link Builder}). 54 * 55 * <p>Most users will never need to use this class. 56 * 57 * @author kenton@google.com Kenton Varda 58 */ 59 public final class UnknownFieldSet implements MessageLite { 60 UnknownFieldSet()61 private UnknownFieldSet() {} 62 63 /** Create a new {@link Builder}. */ newBuilder()64 public static Builder newBuilder() { 65 return Builder.create(); 66 } 67 68 /** 69 * Create a new {@link Builder} and initialize it to be a copy 70 * of {@code copyFrom}. 71 */ newBuilder(final UnknownFieldSet copyFrom)72 public static Builder newBuilder(final UnknownFieldSet copyFrom) { 73 return newBuilder().mergeFrom(copyFrom); 74 } 75 76 /** Get an empty {@code UnknownFieldSet}. */ getDefaultInstance()77 public static UnknownFieldSet getDefaultInstance() { 78 return defaultInstance; 79 } 80 @Override getDefaultInstanceForType()81 public UnknownFieldSet getDefaultInstanceForType() { 82 return defaultInstance; 83 } 84 private static final UnknownFieldSet defaultInstance = 85 new UnknownFieldSet(Collections.<Integer, Field>emptyMap()); 86 87 /** 88 * Construct an {@code UnknownFieldSet} around the given map. The map is 89 * expected to be immutable. 90 */ UnknownFieldSet(final Map<Integer, Field> fields)91 private UnknownFieldSet(final Map<Integer, Field> fields) { 92 this.fields = fields; 93 } 94 private Map<Integer, Field> fields; 95 96 97 @Override equals(final Object other)98 public boolean equals(final Object other) { 99 if (this == other) { 100 return true; 101 } 102 return (other instanceof UnknownFieldSet) && 103 fields.equals(((UnknownFieldSet) other).fields); 104 } 105 106 @Override hashCode()107 public int hashCode() { 108 return fields.hashCode(); 109 } 110 111 /** Get a map of fields in the set by number. */ asMap()112 public Map<Integer, Field> asMap() { 113 return fields; 114 } 115 116 /** Check if the given field number is present in the set. */ hasField(final int number)117 public boolean hasField(final int number) { 118 return fields.containsKey(number); 119 } 120 121 /** 122 * Get a field by number. Returns an empty field if not present. Never 123 * returns {@code null}. 124 */ getField(final int number)125 public Field getField(final int number) { 126 final Field result = fields.get(number); 127 return (result == null) ? Field.getDefaultInstance() : result; 128 } 129 130 /** Serializes the set and writes it to {@code output}. */ 131 @Override writeTo(final CodedOutputStream output)132 public void writeTo(final CodedOutputStream output) throws IOException { 133 for (final Map.Entry<Integer, Field> entry : fields.entrySet()) { 134 Field field = entry.getValue(); 135 field.writeTo(entry.getKey(), output); 136 } 137 } 138 139 /** 140 * Converts the set to a string in protocol buffer text format. This is 141 * just a trivial wrapper around 142 * {@link TextFormat#printToString(UnknownFieldSet)}. 143 */ 144 @Override toString()145 public String toString() { 146 return TextFormat.printToString(this); 147 } 148 149 /** 150 * Serializes the message to a {@code ByteString} and returns it. This is 151 * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}. 152 */ 153 @Override toByteString()154 public ByteString toByteString() { 155 try { 156 final ByteString.CodedBuilder out = 157 ByteString.newCodedBuilder(getSerializedSize()); 158 writeTo(out.getCodedOutput()); 159 return out.build(); 160 } catch (final IOException e) { 161 throw new RuntimeException( 162 "Serializing to a ByteString threw an IOException (should " + 163 "never happen).", e); 164 } 165 } 166 167 /** 168 * Serializes the message to a {@code byte} array and returns it. This is 169 * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}. 170 */ 171 @Override toByteArray()172 public byte[] toByteArray() { 173 try { 174 final byte[] result = new byte[getSerializedSize()]; 175 final CodedOutputStream output = CodedOutputStream.newInstance(result); 176 writeTo(output); 177 output.checkNoSpaceLeft(); 178 return result; 179 } catch (final IOException e) { 180 throw new RuntimeException( 181 "Serializing to a byte array threw an IOException " + 182 "(should never happen).", e); 183 } 184 } 185 186 /** 187 * Serializes the message and writes it to {@code output}. This is just a 188 * trivial wrapper around {@link #writeTo(CodedOutputStream)}. 189 */ 190 @Override writeTo(final OutputStream output)191 public void writeTo(final OutputStream output) throws IOException { 192 final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); 193 writeTo(codedOutput); 194 codedOutput.flush(); 195 } 196 197 @Override writeDelimitedTo(OutputStream output)198 public void writeDelimitedTo(OutputStream output) throws IOException { 199 final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); 200 codedOutput.writeRawVarint32(getSerializedSize()); 201 writeTo(codedOutput); 202 codedOutput.flush(); 203 } 204 205 /** Get the number of bytes required to encode this set. */ 206 @Override getSerializedSize()207 public int getSerializedSize() { 208 int result = 0; 209 for (final Map.Entry<Integer, Field> entry : fields.entrySet()) { 210 result += entry.getValue().getSerializedSize(entry.getKey()); 211 } 212 return result; 213 } 214 215 /** 216 * Serializes the set and writes it to {@code output} using 217 * {@code MessageSet} wire format. 218 */ writeAsMessageSetTo(final CodedOutputStream output)219 public void writeAsMessageSetTo(final CodedOutputStream output) 220 throws IOException { 221 for (final Map.Entry<Integer, Field> entry : fields.entrySet()) { 222 entry.getValue().writeAsMessageSetExtensionTo( 223 entry.getKey(), output); 224 } 225 } 226 227 /** 228 * Get the number of bytes required to encode this set using 229 * {@code MessageSet} wire format. 230 */ getSerializedSizeAsMessageSet()231 public int getSerializedSizeAsMessageSet() { 232 int result = 0; 233 for (final Map.Entry<Integer, Field> entry : fields.entrySet()) { 234 result += entry.getValue().getSerializedSizeAsMessageSetExtension( 235 entry.getKey()); 236 } 237 return result; 238 } 239 240 @Override isInitialized()241 public boolean isInitialized() { 242 // UnknownFieldSets do not have required fields, so they are always 243 // initialized. 244 return true; 245 } 246 247 /** Parse an {@code UnknownFieldSet} from the given input stream. */ parseFrom(final CodedInputStream input)248 public static UnknownFieldSet parseFrom(final CodedInputStream input) 249 throws IOException { 250 return newBuilder().mergeFrom(input).build(); 251 } 252 253 /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ parseFrom(final ByteString data)254 public static UnknownFieldSet parseFrom(final ByteString data) 255 throws InvalidProtocolBufferException { 256 return newBuilder().mergeFrom(data).build(); 257 } 258 259 /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ parseFrom(final byte[] data)260 public static UnknownFieldSet parseFrom(final byte[] data) 261 throws InvalidProtocolBufferException { 262 return newBuilder().mergeFrom(data).build(); 263 } 264 265 /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */ parseFrom(final InputStream input)266 public static UnknownFieldSet parseFrom(final InputStream input) 267 throws IOException { 268 return newBuilder().mergeFrom(input).build(); 269 } 270 271 @Override newBuilderForType()272 public Builder newBuilderForType() { 273 return newBuilder(); 274 } 275 276 @Override toBuilder()277 public Builder toBuilder() { 278 return newBuilder().mergeFrom(this); 279 } 280 281 /** 282 * Builder for {@link UnknownFieldSet}s. 283 * 284 * <p>Note that this class maintains {@link Field.Builder}s for all fields 285 * in the set. Thus, adding one element to an existing {@link Field} does not 286 * require making a copy. This is important for efficient parsing of 287 * unknown repeated fields. However, it implies that {@link Field}s cannot 288 * be constructed independently, nor can two {@link UnknownFieldSet}s share 289 * the same {@code Field} object. 290 * 291 * <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}. 292 */ 293 public static final class Builder implements MessageLite.Builder { 294 // This constructor should never be called directly (except from 'create'). Builder()295 private Builder() {} 296 297 private Map<Integer, Field> fields; 298 299 // Optimization: We keep around a builder for the last field that was 300 // modified so that we can efficiently add to it multiple times in a 301 // row (important when parsing an unknown repeated field). 302 private int lastFieldNumber; 303 private Field.Builder lastField; 304 create()305 private static Builder create() { 306 Builder builder = new Builder(); 307 builder.reinitialize(); 308 return builder; 309 } 310 311 /** 312 * Get a field builder for the given field number which includes any 313 * values that already exist. 314 */ getFieldBuilder(final int number)315 private Field.Builder getFieldBuilder(final int number) { 316 if (lastField != null) { 317 if (number == lastFieldNumber) { 318 return lastField; 319 } 320 // Note: addField() will reset lastField and lastFieldNumber. 321 addField(lastFieldNumber, lastField.build()); 322 } 323 if (number == 0) { 324 return null; 325 } else { 326 final Field existing = fields.get(number); 327 lastFieldNumber = number; 328 lastField = Field.newBuilder(); 329 if (existing != null) { 330 lastField.mergeFrom(existing); 331 } 332 return lastField; 333 } 334 } 335 336 /** 337 * Build the {@link UnknownFieldSet} and return it. 338 * 339 * <p>Once {@code build()} has been called, the {@code Builder} will no 340 * longer be usable. Calling any method after {@code build()} will result 341 * in undefined behavior and can cause a {@code NullPointerException} to be 342 * thrown. 343 */ 344 @Override build()345 public UnknownFieldSet build() { 346 getFieldBuilder(0); // Force lastField to be built. 347 final UnknownFieldSet result; 348 if (fields.isEmpty()) { 349 result = getDefaultInstance(); 350 } else { 351 result = new UnknownFieldSet(Collections.unmodifiableMap(fields)); 352 } 353 fields = null; 354 return result; 355 } 356 357 @Override buildPartial()358 public UnknownFieldSet buildPartial() { 359 // No required fields, so this is the same as build(). 360 return build(); 361 } 362 363 @Override clone()364 public Builder clone() { 365 getFieldBuilder(0); // Force lastField to be built. 366 return UnknownFieldSet.newBuilder().mergeFrom( 367 new UnknownFieldSet(fields)); 368 } 369 370 @Override getDefaultInstanceForType()371 public UnknownFieldSet getDefaultInstanceForType() { 372 return UnknownFieldSet.getDefaultInstance(); 373 } 374 reinitialize()375 private void reinitialize() { 376 fields = Collections.emptyMap(); 377 lastFieldNumber = 0; 378 lastField = null; 379 } 380 381 /** Reset the builder to an empty set. */ 382 @Override clear()383 public Builder clear() { 384 reinitialize(); 385 return this; 386 } 387 388 /** Clear fields from the set with a given field number. */ clearField(final int number)389 public Builder clearField(final int number) { 390 if (number == 0) { 391 throw new IllegalArgumentException("Zero is not a valid field number."); 392 } 393 if (lastField != null && lastFieldNumber == number) { 394 // Discard this. 395 lastField = null; 396 lastFieldNumber = 0; 397 } 398 if (fields.containsKey(number)) { 399 fields.remove(number); 400 } 401 return this; 402 } 403 404 /** 405 * Merge the fields from {@code other} into this set. If a field number 406 * exists in both sets, {@code other}'s values for that field will be 407 * appended to the values in this set. 408 */ mergeFrom(final UnknownFieldSet other)409 public Builder mergeFrom(final UnknownFieldSet other) { 410 if (other != getDefaultInstance()) { 411 for (final Map.Entry<Integer, Field> entry : other.fields.entrySet()) { 412 mergeField(entry.getKey(), entry.getValue()); 413 } 414 } 415 return this; 416 } 417 418 /** 419 * Add a field to the {@code UnknownFieldSet}. If a field with the same 420 * number already exists, the two are merged. 421 */ mergeField(final int number, final Field field)422 public Builder mergeField(final int number, final Field field) { 423 if (number == 0) { 424 throw new IllegalArgumentException("Zero is not a valid field number."); 425 } 426 if (hasField(number)) { 427 getFieldBuilder(number).mergeFrom(field); 428 } else { 429 // Optimization: We could call getFieldBuilder(number).mergeFrom(field) 430 // in this case, but that would create a copy of the Field object. 431 // We'd rather reuse the one passed to us, so call addField() instead. 432 addField(number, field); 433 } 434 return this; 435 } 436 437 /** 438 * Convenience method for merging a new field containing a single varint 439 * value. This is used in particular when an unknown enum value is 440 * encountered. 441 */ mergeVarintField(final int number, final int value)442 public Builder mergeVarintField(final int number, final int value) { 443 if (number == 0) { 444 throw new IllegalArgumentException("Zero is not a valid field number."); 445 } 446 getFieldBuilder(number).addVarint(value); 447 return this; 448 } 449 450 451 /** 452 * Convenience method for merging a length-delimited field. 453 * 454 * <p>For use by generated code only. 455 */ mergeLengthDelimitedField( final int number, final ByteString value)456 public Builder mergeLengthDelimitedField( 457 final int number, final ByteString value) { 458 if (number == 0) { 459 throw new IllegalArgumentException("Zero is not a valid field number."); 460 } 461 getFieldBuilder(number).addLengthDelimited(value); 462 return this; 463 } 464 465 /** Check if the given field number is present in the set. */ hasField(final int number)466 public boolean hasField(final int number) { 467 if (number == 0) { 468 throw new IllegalArgumentException("Zero is not a valid field number."); 469 } 470 return number == lastFieldNumber || fields.containsKey(number); 471 } 472 473 /** 474 * Add a field to the {@code UnknownFieldSet}. If a field with the same 475 * number already exists, it is removed. 476 */ addField(final int number, final Field field)477 public Builder addField(final int number, final Field field) { 478 if (number == 0) { 479 throw new IllegalArgumentException("Zero is not a valid field number."); 480 } 481 if (lastField != null && lastFieldNumber == number) { 482 // Discard this. 483 lastField = null; 484 lastFieldNumber = 0; 485 } 486 if (fields.isEmpty()) { 487 fields = new TreeMap<Integer,Field>(); 488 } 489 fields.put(number, field); 490 return this; 491 } 492 493 /** 494 * Get all present {@code Field}s as an immutable {@code Map}. If more 495 * fields are added, the changes may or may not be reflected in this map. 496 */ asMap()497 public Map<Integer, Field> asMap() { 498 getFieldBuilder(0); // Force lastField to be built. 499 return Collections.unmodifiableMap(fields); 500 } 501 502 /** 503 * Parse an entire message from {@code input} and merge its fields into 504 * this set. 505 */ 506 @Override mergeFrom(final CodedInputStream input)507 public Builder mergeFrom(final CodedInputStream input) throws IOException { 508 while (true) { 509 final int tag = input.readTag(); 510 if (tag == 0 || !mergeFieldFrom(tag, input)) { 511 break; 512 } 513 } 514 return this; 515 } 516 517 /** 518 * Parse a single field from {@code input} and merge it into this set. 519 * @param tag The field's tag number, which was already parsed. 520 * @return {@code false} if the tag is an end group tag. 521 */ mergeFieldFrom(final int tag, final CodedInputStream input)522 public boolean mergeFieldFrom(final int tag, final CodedInputStream input) 523 throws IOException { 524 final int number = WireFormat.getTagFieldNumber(tag); 525 switch (WireFormat.getTagWireType(tag)) { 526 case WireFormat.WIRETYPE_VARINT: 527 getFieldBuilder(number).addVarint(input.readInt64()); 528 return true; 529 case WireFormat.WIRETYPE_FIXED64: 530 getFieldBuilder(number).addFixed64(input.readFixed64()); 531 return true; 532 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 533 getFieldBuilder(number).addLengthDelimited(input.readBytes()); 534 return true; 535 case WireFormat.WIRETYPE_START_GROUP: 536 final Builder subBuilder = newBuilder(); 537 input.readGroup(number, subBuilder, 538 ExtensionRegistry.getEmptyRegistry()); 539 getFieldBuilder(number).addGroup(subBuilder.build()); 540 return true; 541 case WireFormat.WIRETYPE_END_GROUP: 542 return false; 543 case WireFormat.WIRETYPE_FIXED32: 544 getFieldBuilder(number).addFixed32(input.readFixed32()); 545 return true; 546 default: 547 throw InvalidProtocolBufferException.invalidWireType(); 548 } 549 } 550 551 /** 552 * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the 553 * set being built. This is just a small wrapper around 554 * {@link #mergeFrom(CodedInputStream)}. 555 */ 556 @Override mergeFrom(final ByteString data)557 public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferException { 558 try { 559 final CodedInputStream input = data.newCodedInput(); 560 mergeFrom(input); 561 input.checkLastTagWas(0); 562 return this; 563 } catch (final InvalidProtocolBufferException e) { 564 throw e; 565 } catch (final IOException e) { 566 throw new RuntimeException( 567 "Reading from a ByteString threw an IOException (should " + 568 "never happen).", e); 569 } 570 } 571 572 /** 573 * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the 574 * set being built. This is just a small wrapper around 575 * {@link #mergeFrom(CodedInputStream)}. 576 */ 577 @Override mergeFrom(final byte[] data)578 public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferException { 579 try { 580 final CodedInputStream input = CodedInputStream.newInstance(data); 581 mergeFrom(input); 582 input.checkLastTagWas(0); 583 return this; 584 } catch (final InvalidProtocolBufferException e) { 585 throw e; 586 } catch (final IOException e) { 587 throw new RuntimeException( 588 "Reading from a byte array threw an IOException (should " + 589 "never happen).", e); 590 } 591 } 592 593 /** 594 * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the 595 * set being built. This is just a small wrapper around 596 * {@link #mergeFrom(CodedInputStream)}. 597 */ 598 @Override mergeFrom(final InputStream input)599 public Builder mergeFrom(final InputStream input) throws IOException { 600 final CodedInputStream codedInput = CodedInputStream.newInstance(input); 601 mergeFrom(codedInput); 602 codedInput.checkLastTagWas(0); 603 return this; 604 } 605 606 @Override mergeDelimitedFrom(InputStream input)607 public boolean mergeDelimitedFrom(InputStream input) throws IOException { 608 final int firstByte = input.read(); 609 if (firstByte == -1) { 610 return false; 611 } 612 final int size = CodedInputStream.readRawVarint32(firstByte, input); 613 final InputStream limitedInput = new LimitedInputStream(input, size); 614 mergeFrom(limitedInput); 615 return true; 616 } 617 618 @Override mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)619 public boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry) 620 throws IOException { 621 // UnknownFieldSet has no extensions. 622 return mergeDelimitedFrom(input); 623 } 624 625 @Override mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)626 public Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) 627 throws IOException { 628 // UnknownFieldSet has no extensions. 629 return mergeFrom(input); 630 } 631 632 @Override mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)633 public Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry) 634 throws InvalidProtocolBufferException { 635 // UnknownFieldSet has no extensions. 636 return mergeFrom(data); 637 } 638 639 @Override mergeFrom(byte[] data, int off, int len)640 public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException { 641 try { 642 final CodedInputStream input = 643 CodedInputStream.newInstance(data, off, len); 644 mergeFrom(input); 645 input.checkLastTagWas(0); 646 return this; 647 } catch (InvalidProtocolBufferException e) { 648 throw e; 649 } catch (IOException e) { 650 throw new RuntimeException( 651 "Reading from a byte array threw an IOException (should " + 652 "never happen).", e); 653 } 654 } 655 656 @Override mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)657 public Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry) 658 throws InvalidProtocolBufferException { 659 // UnknownFieldSet has no extensions. 660 return mergeFrom(data); 661 } 662 663 @Override mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)664 public Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) 665 throws InvalidProtocolBufferException { 666 // UnknownFieldSet has no extensions. 667 return mergeFrom(data, off, len); 668 } 669 670 @Override mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)671 public Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry) 672 throws IOException { 673 // UnknownFieldSet has no extensions. 674 return mergeFrom(input); 675 } 676 677 @Override mergeFrom(MessageLite m)678 public Builder mergeFrom(MessageLite m) { 679 if (m instanceof UnknownFieldSet) { 680 return mergeFrom((UnknownFieldSet) m); 681 } 682 throw new IllegalArgumentException( 683 "mergeFrom(MessageLite) can only merge messages of the same type."); 684 } 685 686 @Override isInitialized()687 public boolean isInitialized() { 688 // UnknownFieldSets do not have required fields, so they are always 689 // initialized. 690 return true; 691 } 692 } 693 694 /** 695 * Represents a single field in an {@code UnknownFieldSet}. 696 * 697 * <p>A {@code Field} consists of five lists of values. The lists correspond 698 * to the five "wire types" used in the protocol buffer binary format. 699 * The wire type of each field can be determined from the encoded form alone, 700 * without knowing the field's declared type. So, we are able to parse 701 * unknown values at least this far and separate them. Normally, only one 702 * of the five lists will contain any values, since it is impossible to 703 * define a valid message type that declares two different types for the 704 * same field number. However, the code is designed to allow for the case 705 * where the same unknown field number is encountered using multiple different 706 * wire types. 707 * 708 * <p>{@code Field} is an immutable class. To construct one, you must use a 709 * {@link Builder}. 710 * 711 * @see UnknownFieldSet 712 */ 713 public static final class Field { Field()714 private Field() {} 715 716 /** Construct a new {@link Builder}. */ newBuilder()717 public static Builder newBuilder() { 718 return Builder.create(); 719 } 720 721 /** 722 * Construct a new {@link Builder} and initialize it to a copy of 723 * {@code copyFrom}. 724 */ newBuilder(final Field copyFrom)725 public static Builder newBuilder(final Field copyFrom) { 726 return newBuilder().mergeFrom(copyFrom); 727 } 728 729 /** Get an empty {@code Field}. */ getDefaultInstance()730 public static Field getDefaultInstance() { 731 return fieldDefaultInstance; 732 } 733 private static final Field fieldDefaultInstance = newBuilder().build(); 734 735 /** Get the list of varint values for this field. */ getVarintList()736 public List<Long> getVarintList() { return varint; } 737 738 /** Get the list of fixed32 values for this field. */ getFixed32List()739 public List<Integer> getFixed32List() { return fixed32; } 740 741 /** Get the list of fixed64 values for this field. */ getFixed64List()742 public List<Long> getFixed64List() { return fixed64; } 743 744 /** Get the list of length-delimited values for this field. */ getLengthDelimitedList()745 public List<ByteString> getLengthDelimitedList() { return lengthDelimited; } 746 747 /** 748 * Get the list of embedded group values for this field. These are 749 * represented using {@link UnknownFieldSet}s rather than {@link Message}s 750 * since the group's type is presumably unknown. 751 */ getGroupList()752 public List<UnknownFieldSet> getGroupList() { return group; } 753 754 @Override equals(final Object other)755 public boolean equals(final Object other) { 756 if (this == other) { 757 return true; 758 } 759 if (!(other instanceof Field)) { 760 return false; 761 } 762 return Arrays.equals(getIdentityArray(), 763 ((Field) other).getIdentityArray()); 764 } 765 766 @Override hashCode()767 public int hashCode() { 768 return Arrays.hashCode(getIdentityArray()); 769 } 770 771 /** 772 * Returns the array of objects to be used to uniquely identify this 773 * {@link Field} instance. 774 */ getIdentityArray()775 private Object[] getIdentityArray() { 776 return new Object[] { 777 varint, 778 fixed32, 779 fixed64, 780 lengthDelimited, 781 group}; 782 } 783 784 /** 785 * Serializes the field, including field number, and writes it to 786 * {@code output}. 787 */ writeTo(final int fieldNumber, final CodedOutputStream output)788 public void writeTo(final int fieldNumber, final CodedOutputStream output) 789 throws IOException { 790 for (final long value : varint) { 791 output.writeUInt64(fieldNumber, value); 792 } 793 for (final int value : fixed32) { 794 output.writeFixed32(fieldNumber, value); 795 } 796 for (final long value : fixed64) { 797 output.writeFixed64(fieldNumber, value); 798 } 799 for (final ByteString value : lengthDelimited) { 800 output.writeBytes(fieldNumber, value); 801 } 802 for (final UnknownFieldSet value : group) { 803 output.writeGroup(fieldNumber, value); 804 } 805 } 806 807 /** 808 * Get the number of bytes required to encode this field, including field 809 * number. 810 */ getSerializedSize(final int fieldNumber)811 public int getSerializedSize(final int fieldNumber) { 812 int result = 0; 813 for (final long value : varint) { 814 result += CodedOutputStream.computeUInt64Size(fieldNumber, value); 815 } 816 for (final int value : fixed32) { 817 result += CodedOutputStream.computeFixed32Size(fieldNumber, value); 818 } 819 for (final long value : fixed64) { 820 result += CodedOutputStream.computeFixed64Size(fieldNumber, value); 821 } 822 for (final ByteString value : lengthDelimited) { 823 result += CodedOutputStream.computeBytesSize(fieldNumber, value); 824 } 825 for (final UnknownFieldSet value : group) { 826 result += CodedOutputStream.computeGroupSize(fieldNumber, value); 827 } 828 return result; 829 } 830 831 /** 832 * Serializes the field, including field number, and writes it to 833 * {@code output}, using {@code MessageSet} wire format. 834 */ writeAsMessageSetExtensionTo( final int fieldNumber, final CodedOutputStream output)835 public void writeAsMessageSetExtensionTo( 836 final int fieldNumber, 837 final CodedOutputStream output) 838 throws IOException { 839 for (final ByteString value : lengthDelimited) { 840 output.writeRawMessageSetExtension(fieldNumber, value); 841 } 842 } 843 844 /** 845 * Get the number of bytes required to encode this field, including field 846 * number, using {@code MessageSet} wire format. 847 */ getSerializedSizeAsMessageSetExtension(final int fieldNumber)848 public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) { 849 int result = 0; 850 for (final ByteString value : lengthDelimited) { 851 result += CodedOutputStream.computeRawMessageSetExtensionSize( 852 fieldNumber, value); 853 } 854 return result; 855 } 856 857 private List<Long> varint; 858 private List<Integer> fixed32; 859 private List<Long> fixed64; 860 private List<ByteString> lengthDelimited; 861 private List<UnknownFieldSet> group; 862 863 /** 864 * Used to build a {@link Field} within an {@link UnknownFieldSet}. 865 * 866 * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}. 867 */ 868 public static final class Builder { 869 // This constructor should never be called directly (except from 'create'). Builder()870 private Builder() {} 871 create()872 private static Builder create() { 873 Builder builder = new Builder(); 874 builder.result = new Field(); 875 return builder; 876 } 877 878 private Field result; 879 880 /** 881 * Build the field. After {@code build()} has been called, the 882 * {@code Builder} is no longer usable. Calling any other method will 883 * result in undefined behavior and can cause a 884 * {@code NullPointerException} to be thrown. 885 */ build()886 public Field build() { 887 if (result.varint == null) { 888 result.varint = Collections.emptyList(); 889 } else { 890 result.varint = Collections.unmodifiableList(result.varint); 891 } 892 if (result.fixed32 == null) { 893 result.fixed32 = Collections.emptyList(); 894 } else { 895 result.fixed32 = Collections.unmodifiableList(result.fixed32); 896 } 897 if (result.fixed64 == null) { 898 result.fixed64 = Collections.emptyList(); 899 } else { 900 result.fixed64 = Collections.unmodifiableList(result.fixed64); 901 } 902 if (result.lengthDelimited == null) { 903 result.lengthDelimited = Collections.emptyList(); 904 } else { 905 result.lengthDelimited = 906 Collections.unmodifiableList(result.lengthDelimited); 907 } 908 if (result.group == null) { 909 result.group = Collections.emptyList(); 910 } else { 911 result.group = Collections.unmodifiableList(result.group); 912 } 913 914 final Field returnMe = result; 915 result = null; 916 return returnMe; 917 } 918 919 /** Discard the field's contents. */ clear()920 public Builder clear() { 921 result = new Field(); 922 return this; 923 } 924 925 /** 926 * Merge the values in {@code other} into this field. For each list 927 * of values, {@code other}'s values are append to the ones in this 928 * field. 929 */ mergeFrom(final Field other)930 public Builder mergeFrom(final Field other) { 931 if (!other.varint.isEmpty()) { 932 if (result.varint == null) { 933 result.varint = new ArrayList<Long>(); 934 } 935 result.varint.addAll(other.varint); 936 } 937 if (!other.fixed32.isEmpty()) { 938 if (result.fixed32 == null) { 939 result.fixed32 = new ArrayList<Integer>(); 940 } 941 result.fixed32.addAll(other.fixed32); 942 } 943 if (!other.fixed64.isEmpty()) { 944 if (result.fixed64 == null) { 945 result.fixed64 = new ArrayList<Long>(); 946 } 947 result.fixed64.addAll(other.fixed64); 948 } 949 if (!other.lengthDelimited.isEmpty()) { 950 if (result.lengthDelimited == null) { 951 result.lengthDelimited = new ArrayList<ByteString>(); 952 } 953 result.lengthDelimited.addAll(other.lengthDelimited); 954 } 955 if (!other.group.isEmpty()) { 956 if (result.group == null) { 957 result.group = new ArrayList<UnknownFieldSet>(); 958 } 959 result.group.addAll(other.group); 960 } 961 return this; 962 } 963 964 /** Add a varint value. */ addVarint(final long value)965 public Builder addVarint(final long value) { 966 if (result.varint == null) { 967 result.varint = new ArrayList<Long>(); 968 } 969 result.varint.add(value); 970 return this; 971 } 972 973 /** Add a fixed32 value. */ addFixed32(final int value)974 public Builder addFixed32(final int value) { 975 if (result.fixed32 == null) { 976 result.fixed32 = new ArrayList<Integer>(); 977 } 978 result.fixed32.add(value); 979 return this; 980 } 981 982 /** Add a fixed64 value. */ addFixed64(final long value)983 public Builder addFixed64(final long value) { 984 if (result.fixed64 == null) { 985 result.fixed64 = new ArrayList<Long>(); 986 } 987 result.fixed64.add(value); 988 return this; 989 } 990 991 /** Add a length-delimited value. */ addLengthDelimited(final ByteString value)992 public Builder addLengthDelimited(final ByteString value) { 993 if (result.lengthDelimited == null) { 994 result.lengthDelimited = new ArrayList<ByteString>(); 995 } 996 result.lengthDelimited.add(value); 997 return this; 998 } 999 1000 /** Add an embedded group. */ addGroup(final UnknownFieldSet value)1001 public Builder addGroup(final UnknownFieldSet value) { 1002 if (result.group == null) { 1003 result.group = new ArrayList<UnknownFieldSet>(); 1004 } 1005 result.group.add(value); 1006 return this; 1007 } 1008 } 1009 } 1010 1011 /** 1012 * Parser to implement MessageLite interface. 1013 */ 1014 public static final class Parser extends AbstractParser<UnknownFieldSet> { 1015 @Override parsePartialFrom( CodedInputStream input, ExtensionRegistryLite extensionRegistry)1016 public UnknownFieldSet parsePartialFrom( 1017 CodedInputStream input, ExtensionRegistryLite extensionRegistry) 1018 throws InvalidProtocolBufferException { 1019 Builder builder = newBuilder(); 1020 try { 1021 builder.mergeFrom(input); 1022 } catch (InvalidProtocolBufferException e) { 1023 throw e.setUnfinishedMessage(builder.buildPartial()); 1024 } catch (IOException e) { 1025 throw new InvalidProtocolBufferException(e.getMessage()) 1026 .setUnfinishedMessage(builder.buildPartial()); 1027 } 1028 return builder.buildPartial(); 1029 } 1030 } 1031 1032 private static final Parser PARSER = new Parser(); 1033 @Override getParserForType()1034 public final Parser getParserForType() { 1035 return PARSER; 1036 } 1037 } 1038