// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package com.google.protobuf;

import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * {@code UnknownFieldSet} is used to keep track of fields which were seen when
 * parsing a protocol message but whose field numbers or types are unrecognized.
 * This most frequently occurs when new fields are added to a message type
 * and then messages containing those fields are read by old software that was
 * compiled before the new types were added.
 *
 * <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
 * {@link Message.Builder} contains an {@link Builder}).
 *
 * <p>Most users will never need to use this class.
 *
 * @author kenton@google.com Kenton Varda
 */
public final class UnknownFieldSet implements MessageLite {

  private UnknownFieldSet() {
    fields = null;
  }

  /** Create a new {@link Builder}. */
  public static Builder newBuilder() {
    return Builder.create();
  }

  /**
   * Create a new {@link Builder} and initialize it to be a copy
   * of {@code copyFrom}.
   */
  public static Builder newBuilder(final UnknownFieldSet copyFrom) {
    return newBuilder().mergeFrom(copyFrom);
  }

  /** Get an empty {@code UnknownFieldSet}. */
  public static UnknownFieldSet getDefaultInstance() {
    return defaultInstance;
  }
  @Override
  public UnknownFieldSet getDefaultInstanceForType() {
    return defaultInstance;
  }
  private static final UnknownFieldSet defaultInstance =
    new UnknownFieldSet(Collections.<Integer, Field>emptyMap(),
        Collections.<Integer, Field>emptyMap());

  /**
   * Construct an {@code UnknownFieldSet} around the given map.  The map is
   * expected to be immutable.
   */
  UnknownFieldSet(final Map<Integer, Field> fields,
      final Map<Integer, Field> fieldsDescending) {
    this.fields = fields;
  }
  private final Map<Integer, Field> fields;


  @Override
  public boolean equals(final Object other) {
    if (this == other) {
      return true;
    }
    return (other instanceof UnknownFieldSet) &&
           fields.equals(((UnknownFieldSet) other).fields);
  }

  @Override
  public int hashCode() {
    return fields.hashCode();
  }

  /** Get a map of fields in the set by number. */
  public Map<Integer, Field> asMap() {
    return fields;
  }

  /** Check if the given field number is present in the set. */
  public boolean hasField(final int number) {
    return fields.containsKey(number);
  }

  /**
   * Get a field by number.  Returns an empty field if not present.  Never
   * returns {@code null}.
   */
  public Field getField(final int number) {
    final Field result = fields.get(number);
    return (result == null) ? Field.getDefaultInstance() : result;
  }

  /** Serializes the set and writes it to {@code output}. */
  @Override
  public void writeTo(final CodedOutputStream output) throws IOException {
    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
      Field field = entry.getValue();
      field.writeTo(entry.getKey(), output);
    }
  }

  /**
   * Converts the set to a string in protocol buffer text format. This is
   * just a trivial wrapper around
   * {@link TextFormat#printToString(UnknownFieldSet)}.
   */
  @Override
  public String toString() {
    return TextFormat.printToString(this);
  }

  /**
   * Serializes the message to a {@code ByteString} and returns it. This is
   * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
   */
  @Override
  public ByteString toByteString() {
    try {
      final ByteString.CodedBuilder out =
        ByteString.newCodedBuilder(getSerializedSize());
      writeTo(out.getCodedOutput());
      return out.build();
    } catch (final IOException e) {
      throw new RuntimeException(
        "Serializing to a ByteString threw an IOException (should " +
        "never happen).", e);
    }
  }

  /**
   * Serializes the message to a {@code byte} array and returns it.  This is
   * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
   */
  @Override
  public byte[] toByteArray() {
    try {
      final byte[] result = new byte[getSerializedSize()];
      final CodedOutputStream output = CodedOutputStream.newInstance(result);
      writeTo(output);
      output.checkNoSpaceLeft();
      return result;
    } catch (final IOException e) {
      throw new RuntimeException(
        "Serializing to a byte array threw an IOException " +
        "(should never happen).", e);
    }
  }

  /**
   * Serializes the message and writes it to {@code output}.  This is just a
   * trivial wrapper around {@link #writeTo(CodedOutputStream)}.
   */
  @Override
  public void writeTo(final OutputStream output) throws IOException {
    final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
    writeTo(codedOutput);
    codedOutput.flush();
  }

  @Override
  public void writeDelimitedTo(OutputStream output) throws IOException {
    final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
    codedOutput.writeRawVarint32(getSerializedSize());
    writeTo(codedOutput);
    codedOutput.flush();
  }

  /** Get the number of bytes required to encode this set. */
  @Override
  public int getSerializedSize() {
    int result = 0;
    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
      result += entry.getValue().getSerializedSize(entry.getKey());
    }
    return result;
  }

  /**
   * Serializes the set and writes it to {@code output} using
   * {@code MessageSet} wire format.
   */
  public void writeAsMessageSetTo(final CodedOutputStream output)
      throws IOException {
    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
      entry.getValue().writeAsMessageSetExtensionTo(
        entry.getKey(), output);
    }
  }


  /** Get the number of bytes required to encode this set using {@code MessageSet} wire format. */
  public int getSerializedSizeAsMessageSet() {
    int result = 0;
    for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
      result += entry.getValue().getSerializedSizeAsMessageSetExtension(
        entry.getKey());
    }
    return result;
  }

  @Override
  public boolean isInitialized() {
    // UnknownFieldSets do not have required fields, so they are always
    // initialized.
    return true;
  }

  /** Parse an {@code UnknownFieldSet} from the given input stream. */
  public static UnknownFieldSet parseFrom(final CodedInputStream input)
                                          throws IOException {
    return newBuilder().mergeFrom(input).build();
  }

  /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
  public static UnknownFieldSet parseFrom(final ByteString data)
      throws InvalidProtocolBufferException {
    return newBuilder().mergeFrom(data).build();
  }

  /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
  public static UnknownFieldSet parseFrom(final byte[] data)
      throws InvalidProtocolBufferException {
    return newBuilder().mergeFrom(data).build();
  }

  /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */
  public static UnknownFieldSet parseFrom(final InputStream input)
                                          throws IOException {
    return newBuilder().mergeFrom(input).build();
  }

  @Override
  public Builder newBuilderForType() {
    return newBuilder();
  }

  @Override
  public Builder toBuilder() {
    return newBuilder().mergeFrom(this);
  }

  /**
   * Builder for {@link UnknownFieldSet}s.
   *
   * <p>Note that this class maintains {@link Field.Builder}s for all fields
   * in the set.  Thus, adding one element to an existing {@link Field} does not
   * require making a copy.  This is important for efficient parsing of
   * unknown repeated fields.  However, it implies that {@link Field}s cannot
   * be constructed independently, nor can two {@link UnknownFieldSet}s share
   * the same {@code Field} object.
   *
   * <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}.
   */
  public static final class Builder implements MessageLite.Builder {
    // This constructor should never be called directly (except from 'create').
    private Builder() {}

    private Map<Integer, Field> fields;

    // Optimization:  We keep around a builder for the last field that was
    //   modified so that we can efficiently add to it multiple times in a
    //   row (important when parsing an unknown repeated field).
    private int lastFieldNumber;
    private Field.Builder lastField;

    private static Builder create() {
      Builder builder = new Builder();
      builder.reinitialize();
      return builder;
    }

    /**
     * Get a field builder for the given field number which includes any
     * values that already exist.
     */
    private Field.Builder getFieldBuilder(final int number) {
      if (lastField != null) {
        if (number == lastFieldNumber) {
          return lastField;
        }
        // Note:  addField() will reset lastField and lastFieldNumber.
        addField(lastFieldNumber, lastField.build());
      }
      if (number == 0) {
        return null;
      } else {
        final Field existing = fields.get(number);
        lastFieldNumber = number;
        lastField = Field.newBuilder();
        if (existing != null) {
          lastField.mergeFrom(existing);
        }
        return lastField;
      }
    }

    /**
     * Build the {@link UnknownFieldSet} and return it.
     *
     * <p>Once {@code build()} has been called, the {@code Builder} will no
     * longer be usable.  Calling any method after {@code build()} will result
     * in undefined behavior and can cause a {@code NullPointerException} to be
     * thrown.
     */
    @Override
    public UnknownFieldSet build() {
      getFieldBuilder(0); // Force lastField to be built.
      final UnknownFieldSet result;
      if (fields.isEmpty()) {
        result = getDefaultInstance();
      } else {
        Map<Integer, Field> descendingFields = null;
        result = new UnknownFieldSet(Collections.unmodifiableMap(fields), descendingFields);
      }
      fields = null;
      return result;
    }

    @Override
    public UnknownFieldSet buildPartial() {
      // No required fields, so this is the same as build().
      return build();
    }

    @Override
    public Builder clone() {
      getFieldBuilder(0);  // Force lastField to be built.
      Map<Integer, Field> descendingFields = null;
      return UnknownFieldSet.newBuilder().mergeFrom(
          new UnknownFieldSet(fields, descendingFields));
    }

    @Override
    public UnknownFieldSet getDefaultInstanceForType() {
      return UnknownFieldSet.getDefaultInstance();
    }

    private void reinitialize() {
      fields = Collections.emptyMap();
      lastFieldNumber = 0;
      lastField = null;
    }

    /** Reset the builder to an empty set. */
    @Override
    public Builder clear() {
      reinitialize();
      return this;
    }
    
    /** Clear fields from the set with a given field number. */
    public Builder clearField(final int number) {
      if (number == 0) {
        throw new IllegalArgumentException("Zero is not a valid field number.");
      }
      if (lastField != null && lastFieldNumber == number) {
        // Discard this.
        lastField = null;
        lastFieldNumber = 0;
      }
      if (fields.containsKey(number)) {
        fields.remove(number);
      }
      return this;
    }

    /**
     * Merge the fields from {@code other} into this set.  If a field number
     * exists in both sets, {@code other}'s values for that field will be
     * appended to the values in this set.
     */
    public Builder mergeFrom(final UnknownFieldSet other) {
      if (other != getDefaultInstance()) {
        for (final Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
          mergeField(entry.getKey(), entry.getValue());
        }
      }
      return this;
    }

    /**
     * Add a field to the {@code UnknownFieldSet}.  If a field with the same
     * number already exists, the two are merged.
     */
    public Builder mergeField(final int number, final Field field) {
      if (number == 0) {
        throw new IllegalArgumentException("Zero is not a valid field number.");
      }
      if (hasField(number)) {
        getFieldBuilder(number).mergeFrom(field);
      } else {
        // Optimization:  We could call getFieldBuilder(number).mergeFrom(field)
        // in this case, but that would create a copy of the Field object.
        // We'd rather reuse the one passed to us, so call addField() instead.
        addField(number, field);
      }
      return this;
    }

    /**
     * Convenience method for merging a new field containing a single varint
     * value.  This is used in particular when an unknown enum value is
     * encountered.
     */
    public Builder mergeVarintField(final int number, final int value) {
      if (number == 0) {
        throw new IllegalArgumentException("Zero is not a valid field number.");
      }
      getFieldBuilder(number).addVarint(value);
      return this;
    }


    /**
     * Convenience method for merging a length-delimited field.
     *
     * <p>For use by generated code only.
     */
    public Builder mergeLengthDelimitedField(
        final int number, final ByteString value) {  
      if (number == 0) {
        throw new IllegalArgumentException("Zero is not a valid field number.");
      }
      getFieldBuilder(number).addLengthDelimited(value);
      return this;
    }

    /** Check if the given field number is present in the set. */
    public boolean hasField(final int number) {
      if (number == 0) {
        throw new IllegalArgumentException("Zero is not a valid field number.");
      }
      return number == lastFieldNumber || fields.containsKey(number);
    }

    /**
     * Add a field to the {@code UnknownFieldSet}.  If a field with the same
     * number already exists, it is removed.
     */
    public Builder addField(final int number, final Field field) {
      if (number == 0) {
        throw new IllegalArgumentException("Zero is not a valid field number.");
      }
      if (lastField != null && lastFieldNumber == number) {
        // Discard this.
        lastField = null;
        lastFieldNumber = 0;
      }
      if (fields.isEmpty()) {
        fields = new TreeMap<Integer,Field>();
      }
      fields.put(number, field);
      return this;
    }

    /**
     * Get all present {@code Field}s as an immutable {@code Map}.  If more
     * fields are added, the changes may or may not be reflected in this map.
     */
    public Map<Integer, Field> asMap() {
      getFieldBuilder(0);  // Force lastField to be built.
      return Collections.unmodifiableMap(fields);
    }

    /**
     * Parse an entire message from {@code input} and merge its fields into
     * this set.
     */
    @Override
    public Builder mergeFrom(final CodedInputStream input) throws IOException {
      while (true) {
        final int tag = input.readTag();
        if (tag == 0 || !mergeFieldFrom(tag, input)) {
          break;
        }
      }
      return this;
    }

    /**
     * Parse a single field from {@code input} and merge it into this set.
     * @param tag The field's tag number, which was already parsed.
     * @return {@code false} if the tag is an end group tag.
     */
    public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
                                  throws IOException {
      final int number = WireFormat.getTagFieldNumber(tag);
      switch (WireFormat.getTagWireType(tag)) {
        case WireFormat.WIRETYPE_VARINT:
          getFieldBuilder(number).addVarint(input.readInt64());
          return true;
        case WireFormat.WIRETYPE_FIXED64:
          getFieldBuilder(number).addFixed64(input.readFixed64());
          return true;
        case WireFormat.WIRETYPE_LENGTH_DELIMITED:
          getFieldBuilder(number).addLengthDelimited(input.readBytes());
          return true;
        case WireFormat.WIRETYPE_START_GROUP:
          final Builder subBuilder = newBuilder();
          input.readGroup(number, subBuilder,
                          ExtensionRegistry.getEmptyRegistry());
          getFieldBuilder(number).addGroup(subBuilder.build());
          return true;
        case WireFormat.WIRETYPE_END_GROUP:
          return false;
        case WireFormat.WIRETYPE_FIXED32:
          getFieldBuilder(number).addFixed32(input.readFixed32());
          return true;
        default:
          throw InvalidProtocolBufferException.invalidWireType();
      }
    }

    /**
     * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the
     * set being built.  This is just a small wrapper around
     * {@link #mergeFrom(CodedInputStream)}.
     */
    @Override
    public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
      try {
        final CodedInputStream input = data.newCodedInput();
        mergeFrom(input);
        input.checkLastTagWas(0);
        return this;
      } catch (final InvalidProtocolBufferException e) {
        throw e;
      } catch (final IOException e) {
        throw new RuntimeException(
          "Reading from a ByteString threw an IOException (should " +
          "never happen).", e);
      }
    }

    /**
     * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the
     * set being built.  This is just a small wrapper around
     * {@link #mergeFrom(CodedInputStream)}.
     */
    @Override
    public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
      try {
        final CodedInputStream input = CodedInputStream.newInstance(data);
        mergeFrom(input);
        input.checkLastTagWas(0);
        return this;
      } catch (final InvalidProtocolBufferException e) {
        throw e;
      } catch (final IOException e) {
        throw new RuntimeException(
          "Reading from a byte array threw an IOException (should " +
          "never happen).", e);
      }
    }

    /**
     * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the
     * set being built.  This is just a small wrapper around
     * {@link #mergeFrom(CodedInputStream)}.
     */
    @Override
    public Builder mergeFrom(final InputStream input) throws IOException {
      final CodedInputStream codedInput = CodedInputStream.newInstance(input);
      mergeFrom(codedInput);
      codedInput.checkLastTagWas(0);
      return this;
    }

    @Override
    public boolean mergeDelimitedFrom(InputStream input) throws IOException {
      final int firstByte = input.read();
      if (firstByte == -1) {
        return false;
      }
      final int size = CodedInputStream.readRawVarint32(firstByte, input);
      final InputStream limitedInput = new LimitedInputStream(input, size);
      mergeFrom(limitedInput);
      return true;
    }

    @Override
    public boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
        throws IOException {
      // UnknownFieldSet has no extensions.
      return mergeDelimitedFrom(input);
    }

    @Override
    public Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
        throws IOException {
      // UnknownFieldSet has no extensions.
      return mergeFrom(input);
    }

    @Override
    public Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
        throws InvalidProtocolBufferException {
      // UnknownFieldSet has no extensions.
      return mergeFrom(data);
    }

    @Override
    public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException {
      try {
        final CodedInputStream input =
            CodedInputStream.newInstance(data, off, len);
        mergeFrom(input);
        input.checkLastTagWas(0);
        return this;
      } catch (InvalidProtocolBufferException e) {
        throw e;
      } catch (IOException e) {
        throw new RuntimeException(
          "Reading from a byte array threw an IOException (should " +
          "never happen).", e);
      }
    }

    @Override
    public Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
        throws InvalidProtocolBufferException {
      // UnknownFieldSet has no extensions.
      return mergeFrom(data);
    }

    @Override
    public Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
        throws InvalidProtocolBufferException {
      // UnknownFieldSet has no extensions.
      return mergeFrom(data, off, len);
    }

    @Override
    public Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
        throws IOException {
      // UnknownFieldSet has no extensions.
      return mergeFrom(input);
    }

    @Override
    public Builder mergeFrom(MessageLite m) {
      if (m instanceof UnknownFieldSet) {
        return mergeFrom((UnknownFieldSet) m);
      }
      throw new IllegalArgumentException(
          "mergeFrom(MessageLite) can only merge messages of the same type.");
    }

    @Override
    public boolean isInitialized() {
      // UnknownFieldSets do not have required fields, so they are always
      // initialized.
      return true;
    }
  }

  /**
   * Represents a single field in an {@code UnknownFieldSet}.
   *
   * <p>A {@code Field} consists of five lists of values.  The lists correspond
   * to the five "wire types" used in the protocol buffer binary format.
   * The wire type of each field can be determined from the encoded form alone,
   * without knowing the field's declared type.  So, we are able to parse
   * unknown values at least this far and separate them.  Normally, only one
   * of the five lists will contain any values, since it is impossible to
   * define a valid message type that declares two different types for the
   * same field number.  However, the code is designed to allow for the case
   * where the same unknown field number is encountered using multiple different
   * wire types.
   *
   * <p>{@code Field} is an immutable class.  To construct one, you must use a
   * {@link Builder}.
   *
   * @see UnknownFieldSet
   */
  public static final class Field {
    private Field() {}

    /** Construct a new {@link Builder}. */
    public static Builder newBuilder() {
      return Builder.create();
    }

    /**
     * Construct a new {@link Builder} and initialize it to a copy of
     * {@code copyFrom}.
     */
    public static Builder newBuilder(final Field copyFrom) {
      return newBuilder().mergeFrom(copyFrom);
    }

    /** Get an empty {@code Field}. */
    public static Field getDefaultInstance() {
      return fieldDefaultInstance;
    }
    private static final Field fieldDefaultInstance = newBuilder().build();

    /** Get the list of varint values for this field. */
    public List<Long> getVarintList()               { return varint;          }

    /** Get the list of fixed32 values for this field. */
    public List<Integer> getFixed32List()           { return fixed32;         }

    /** Get the list of fixed64 values for this field. */
    public List<Long> getFixed64List()              { return fixed64;         }

    /** Get the list of length-delimited values for this field. */
    public List<ByteString> getLengthDelimitedList() { return lengthDelimited; }

    /**
     * Get the list of embedded group values for this field.  These are
     * represented using {@link UnknownFieldSet}s rather than {@link Message}s
     * since the group's type is presumably unknown.
     */
    public List<UnknownFieldSet> getGroupList()      { return group;           }

    @Override
    public boolean equals(final Object other) {
      if (this == other) {
        return true;
      }
      if (!(other instanceof Field)) {
        return false;
      }
      return Arrays.equals(getIdentityArray(),
          ((Field) other).getIdentityArray());
    }

    @Override
    public int hashCode() {
      return Arrays.hashCode(getIdentityArray());
    }

    /**
     * Returns the array of objects to be used to uniquely identify this
     * {@link Field} instance.
     */
    private Object[] getIdentityArray() {
      return new Object[] {
          varint,
          fixed32,
          fixed64,
          lengthDelimited,
          group};
    }

    /**
     * Serializes the field, including field number, and writes it to
     * {@code output}.
     */
    public void writeTo(final int fieldNumber, final CodedOutputStream output)
                        throws IOException {
      for (final long value : varint) {
        output.writeUInt64(fieldNumber, value);
      }
      for (final int value : fixed32) {
        output.writeFixed32(fieldNumber, value);
      }
      for (final long value : fixed64) {
        output.writeFixed64(fieldNumber, value);
      }
      for (final ByteString value : lengthDelimited) {
        output.writeBytes(fieldNumber, value);
      }
      for (final UnknownFieldSet value : group) {
        output.writeGroup(fieldNumber, value);
      }
    }

    /**
     * Get the number of bytes required to encode this field, including field
     * number.
     */
    public int getSerializedSize(final int fieldNumber) {
      int result = 0;
      for (final long value : varint) {
        result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
      }
      for (final int value : fixed32) {
        result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
      }
      for (final long value : fixed64) {
        result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
      }
      for (final ByteString value : lengthDelimited) {
        result += CodedOutputStream.computeBytesSize(fieldNumber, value);
      }
      for (final UnknownFieldSet value : group) {
        result += CodedOutputStream.computeGroupSize(fieldNumber, value);
      }
      return result;
    }

    /**
     * Serializes the field, including field number, and writes it to
     * {@code output}, using {@code MessageSet} wire format.
     */
    public void writeAsMessageSetExtensionTo(
        final int fieldNumber,
        final CodedOutputStream output)
        throws IOException {
      for (final ByteString value : lengthDelimited) {
        output.writeRawMessageSetExtension(fieldNumber, value);
      }
    }


    /**
     * Get the number of bytes required to encode this field, including field number, using {@code
     * MessageSet} wire format.
     */
    public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) {
      int result = 0;
      for (final ByteString value : lengthDelimited) {
        result += CodedOutputStream.computeRawMessageSetExtensionSize(
          fieldNumber, value);
      }
      return result;
    }

    private List<Long> varint;
    private List<Integer> fixed32;
    private List<Long> fixed64;
    private List<ByteString> lengthDelimited;
    private List<UnknownFieldSet> group;

    /**
     * Used to build a {@link Field} within an {@link UnknownFieldSet}.
     *
     * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
     */
    public static final class Builder {
      // This constructor should never be called directly (except from 'create').
      private Builder() {}

      private static Builder create() {
        Builder builder = new Builder();
        builder.result = new Field();
        return builder;
      }

      private Field result;

      /**
       * Build the field.  After {@code build()} has been called, the
       * {@code Builder} is no longer usable.  Calling any other method will
       * result in undefined behavior and can cause a
       * {@code NullPointerException} to be thrown.
       */
      public Field build() {
        if (result.varint == null) {
          result.varint = Collections.emptyList();
        } else {
          result.varint = Collections.unmodifiableList(result.varint);
        }
        if (result.fixed32 == null) {
          result.fixed32 = Collections.emptyList();
        } else {
          result.fixed32 = Collections.unmodifiableList(result.fixed32);
        }
        if (result.fixed64 == null) {
          result.fixed64 = Collections.emptyList();
        } else {
          result.fixed64 = Collections.unmodifiableList(result.fixed64);
        }
        if (result.lengthDelimited == null) {
          result.lengthDelimited = Collections.emptyList();
        } else {
          result.lengthDelimited =
            Collections.unmodifiableList(result.lengthDelimited);
        }
        if (result.group == null) {
          result.group = Collections.emptyList();
        } else {
          result.group = Collections.unmodifiableList(result.group);
        }

        final Field returnMe = result;
        result = null;
        return returnMe;
      }

      /** Discard the field's contents. */
      public Builder clear() {
        result = new Field();
        return this;
      }

      /**
       * Merge the values in {@code other} into this field.  For each list
       * of values, {@code other}'s values are append to the ones in this
       * field.
       */
      public Builder mergeFrom(final Field other) {
        if (!other.varint.isEmpty()) {
          if (result.varint == null) {
            result.varint = new ArrayList<Long>();
          }
          result.varint.addAll(other.varint);
        }
        if (!other.fixed32.isEmpty()) {
          if (result.fixed32 == null) {
            result.fixed32 = new ArrayList<Integer>();
          }
          result.fixed32.addAll(other.fixed32);
        }
        if (!other.fixed64.isEmpty()) {
          if (result.fixed64 == null) {
            result.fixed64 = new ArrayList<Long>();
          }
          result.fixed64.addAll(other.fixed64);
        }
        if (!other.lengthDelimited.isEmpty()) {
          if (result.lengthDelimited == null) {
            result.lengthDelimited = new ArrayList<ByteString>();
          }
          result.lengthDelimited.addAll(other.lengthDelimited);
        }
        if (!other.group.isEmpty()) {
          if (result.group == null) {
            result.group = new ArrayList<UnknownFieldSet>();
          }
          result.group.addAll(other.group);
        }
        return this;
      }

      /** Add a varint value. */
      public Builder addVarint(final long value) {
        if (result.varint == null) {
          result.varint = new ArrayList<Long>();
        }
        result.varint.add(value);
        return this;
      }

      /** Add a fixed32 value. */
      public Builder addFixed32(final int value) {
        if (result.fixed32 == null) {
          result.fixed32 = new ArrayList<Integer>();
        }
        result.fixed32.add(value);
        return this;
      }

      /** Add a fixed64 value. */
      public Builder addFixed64(final long value) {
        if (result.fixed64 == null) {
          result.fixed64 = new ArrayList<Long>();
        }
        result.fixed64.add(value);
        return this;
      }

      /** Add a length-delimited value. */
      public Builder addLengthDelimited(final ByteString value) {
        if (result.lengthDelimited == null) {
          result.lengthDelimited = new ArrayList<ByteString>();
        }
        result.lengthDelimited.add(value);
        return this;
      }

      /** Add an embedded group. */
      public Builder addGroup(final UnknownFieldSet value) {
        if (result.group == null) {
          result.group = new ArrayList<UnknownFieldSet>();
        }
        result.group.add(value);
        return this;
      }
    }
  }

  /**
   * Parser to implement MessageLite interface.
   */
  public static final class Parser extends AbstractParser<UnknownFieldSet> {
    @Override
    public UnknownFieldSet parsePartialFrom(
        CodedInputStream input, ExtensionRegistryLite extensionRegistry)
        throws InvalidProtocolBufferException {
      Builder builder = newBuilder();
      try {
        builder.mergeFrom(input);
      } catch (InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(builder.buildPartial());
      } catch (IOException e) {
        throw new InvalidProtocolBufferException(e)
            .setUnfinishedMessage(builder.buildPartial());
      }
      return builder.buildPartial();
    }
  }

  private static final Parser PARSER = new Parser();
  @Override
  public final Parser getParserForType() {
    return PARSER;
  }
}
