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