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