PageRenderTime 84ms CodeModel.GetById 18ms app.highlight 59ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/third_party/protobuf/protobuf/java/src/main/java/com/google/protobuf/UnknownFieldSet.java

http://github.com/tomahawk-player/tomahawk
Java | 953 lines | 605 code | 89 blank | 259 comment | 100 complexity | 7aa7d1666417ca56e365cd246ccf798e MD5 | raw file
  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
 31package com.google.protobuf;
 32
 33import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
 34
 35import java.io.IOException;
 36import java.io.InputStream;
 37import java.io.OutputStream;
 38import java.util.ArrayList;
 39import java.util.Arrays;
 40import java.util.Collections;
 41import java.util.List;
 42import java.util.Map;
 43import 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@google.com Kenton Varda
 58 */
 59public 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}