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