Home | History | Annotate | Download | only in protobuf
      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