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