// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: src/test/protobuf/test.proto
// Protobuf Java Version: 4.26.1

package org.apache.avro.protobuf.noopt;

public final class Test {
  private Test() {
  }

  static {
    com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
        com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 26, /* patch= */ 1,
        /* suffix= */ "", Test.class.getName());
  }

  public static void registerAllExtensions(com.google.protobuf.ExtensionRegistryLite registry) {
  }

  public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) {
    registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry);
  }

  /**
   * <pre>
   * an enum
   * </pre>
   *
   * Protobuf enum {@code org.apache.avro.protobuf.noopt.A}
   */
  public enum A implements com.google.protobuf.ProtocolMessageEnum {
    /**
     * <code>X = 1;</code>
     */
    X(1),
    /**
     * <code>Y = 2;</code>
     */
    Y(2),
    /**
     * <code>Z = 3;</code>
     */
    Z(3),;

    static {
      com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
          com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 26, /* patch= */ 1,
          /* suffix= */ "", A.class.getName());
    }
    /**
     * <code>X = 1;</code>
     */
    public static final int X_VALUE = 1;
    /**
     * <code>Y = 2;</code>
     */
    public static final int Y_VALUE = 2;
    /**
     * <code>Z = 3;</code>
     */
    public static final int Z_VALUE = 3;

    public final int getNumber() {
      return value;
    }

    /**
     * @param value The numeric wire value of the corresponding enum entry.
     * @return The enum associated with the given numeric wire value.
     * @deprecated Use {@link #forNumber(int)} instead.
     */
    @java.lang.Deprecated
    public static A valueOf(int value) {
      return forNumber(value);
    }

    /**
     * @param value The numeric wire value of the corresponding enum entry.
     * @return The enum associated with the given numeric wire value.
     */
    public static A forNumber(int value) {
      switch (value) {
      case 1:
        return X;
      case 2:
        return Y;
      case 3:
        return Z;
      default:
        return null;
      }
    }

    public static com.google.protobuf.Internal.EnumLiteMap<A> internalGetValueMap() {
      return internalValueMap;
    }

    private static final com.google.protobuf.Internal.EnumLiteMap<A> internalValueMap = new com.google.protobuf.Internal.EnumLiteMap<A>() {
      public A findValueByNumber(int number) {
        return A.forNumber(number);
      }
    };

    public final com.google.protobuf.Descriptors.EnumValueDescriptor getValueDescriptor() {
      return getDescriptor().getValues().get(ordinal());
    }

    public final com.google.protobuf.Descriptors.EnumDescriptor getDescriptorForType() {
      return getDescriptor();
    }

    public static final com.google.protobuf.Descriptors.EnumDescriptor getDescriptor() {
      return org.apache.avro.protobuf.noopt.Test.getDescriptor().getEnumTypes().get(0);
    }

    private static final A[] VALUES = values();

    public static A valueOf(com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
      if (desc.getType() != getDescriptor()) {
        throw new java.lang.IllegalArgumentException("EnumValueDescriptor is not for this type.");
      }
      return VALUES[desc.getIndex()];
    }

    private final int value;

    private A(int value) {
      this.value = value;
    }

    // @@protoc_insertion_point(enum_scope:org.apache.avro.protobuf.noopt.A)
  }

  public interface FooOrBuilder extends
      // @@protoc_insertion_point(interface_extends:org.apache.avro.protobuf.noopt.Foo)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <pre>
     * all the primitive types
     * </pre>
     *
     * <code>required int32 int32 = 1;</code>
     * 
     * @return Whether the int32 field is set.
     */
    boolean hasInt32();

    /**
     * <pre>
     * all the primitive types
     * </pre>
     *
     * <code>required int32 int32 = 1;</code>
     * 
     * @return The int32.
     */
    int getInt32();

    /**
     * <code>optional int64 int64 = 2;</code>
     * 
     * @return Whether the int64 field is set.
     */
    boolean hasInt64();

    /**
     * <code>optional int64 int64 = 2;</code>
     * 
     * @return The int64.
     */
    long getInt64();

    /**
     * <code>optional uint32 uint32 = 3;</code>
     * 
     * @return Whether the uint32 field is set.
     */
    boolean hasUint32();

    /**
     * <code>optional uint32 uint32 = 3;</code>
     * 
     * @return The uint32.
     */
    int getUint32();

    /**
     * <code>optional uint64 uint64 = 4;</code>
     * 
     * @return Whether the uint64 field is set.
     */
    boolean hasUint64();

    /**
     * <code>optional uint64 uint64 = 4;</code>
     * 
     * @return The uint64.
     */
    long getUint64();

    /**
     * <code>optional sint32 sint32 = 5;</code>
     * 
     * @return Whether the sint32 field is set.
     */
    boolean hasSint32();

    /**
     * <code>optional sint32 sint32 = 5;</code>
     * 
     * @return The sint32.
     */
    int getSint32();

    /**
     * <code>optional sint64 sint64 = 6;</code>
     * 
     * @return Whether the sint64 field is set.
     */
    boolean hasSint64();

    /**
     * <code>optional sint64 sint64 = 6;</code>
     * 
     * @return The sint64.
     */
    long getSint64();

    /**
     * <code>optional fixed32 fixed32 = 7;</code>
     * 
     * @return Whether the fixed32 field is set.
     */
    boolean hasFixed32();

    /**
     * <code>optional fixed32 fixed32 = 7;</code>
     * 
     * @return The fixed32.
     */
    int getFixed32();

    /**
     * <code>optional fixed64 fixed64 = 8;</code>
     * 
     * @return Whether the fixed64 field is set.
     */
    boolean hasFixed64();

    /**
     * <code>optional fixed64 fixed64 = 8;</code>
     * 
     * @return The fixed64.
     */
    long getFixed64();

    /**
     * <code>optional sfixed32 sfixed32 = 9;</code>
     * 
     * @return Whether the sfixed32 field is set.
     */
    boolean hasSfixed32();

    /**
     * <code>optional sfixed32 sfixed32 = 9;</code>
     * 
     * @return The sfixed32.
     */
    int getSfixed32();

    /**
     * <code>optional sfixed64 sfixed64 = 10;</code>
     * 
     * @return Whether the sfixed64 field is set.
     */
    boolean hasSfixed64();

    /**
     * <code>optional sfixed64 sfixed64 = 10;</code>
     * 
     * @return The sfixed64.
     */
    long getSfixed64();

    /**
     * <code>optional float float = 11;</code>
     * 
     * @return Whether the float field is set.
     */
    boolean hasFloat();

    /**
     * <code>optional float float = 11;</code>
     * 
     * @return The float.
     */
    float getFloat();

    /**
     * <code>optional double double = 12;</code>
     * 
     * @return Whether the double field is set.
     */
    boolean hasDouble();

    /**
     * <code>optional double double = 12;</code>
     * 
     * @return The double.
     */
    double getDouble();

    /**
     * <code>optional bool bool = 13;</code>
     * 
     * @return Whether the bool field is set.
     */
    boolean hasBool();

    /**
     * <code>optional bool bool = 13;</code>
     * 
     * @return The bool.
     */
    boolean getBool();

    /**
     * <code>optional string string = 14;</code>
     * 
     * @return Whether the string field is set.
     */
    boolean hasString();

    /**
     * <code>optional string string = 14;</code>
     * 
     * @return The string.
     */
    java.lang.String getString();

    /**
     * <code>optional string string = 14;</code>
     * 
     * @return The bytes for string.
     */
    com.google.protobuf.ByteString getStringBytes();

    /**
     * <code>optional bytes bytes = 15;</code>
     * 
     * @return Whether the bytes field is set.
     */
    boolean hasBytes();

    /**
     * <code>optional bytes bytes = 15;</code>
     * 
     * @return The bytes.
     */
    com.google.protobuf.ByteString getBytes();

    /**
     * <code>optional .org.apache.avro.protobuf.noopt.A enum = 16 [default = Z];</code>
     * 
     * @return Whether the enum field is set.
     */
    boolean hasEnum();

    /**
     * <code>optional .org.apache.avro.protobuf.noopt.A enum = 16 [default = Z];</code>
     * 
     * @return The enum.
     */
    org.apache.avro.protobuf.noopt.Test.A getEnum();

    /**
     * <pre>
     * some repeated types
     * </pre>
     *
     * <code>repeated int32 intArray = 17;</code>
     * 
     * @return A list containing the intArray.
     */
    java.util.List<java.lang.Integer> getIntArrayList();

    /**
     * <pre>
     * some repeated types
     * </pre>
     *
     * <code>repeated int32 intArray = 17;</code>
     * 
     * @return The count of intArray.
     */
    int getIntArrayCount();

    /**
     * <pre>
     * some repeated types
     * </pre>
     *
     * <code>repeated int32 intArray = 17;</code>
     * 
     * @param index The index of the element to return.
     * @return The intArray at the given index.
     */
    int getIntArray(int index);

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
     */
    java.util.List<org.apache.avro.protobuf.noopt.Test.Foo> getFooArrayList();

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
     */
    org.apache.avro.protobuf.noopt.Test.Foo getFooArray(int index);

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
     */
    int getFooArrayCount();

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
     */
    java.util.List<? extends org.apache.avro.protobuf.noopt.Test.FooOrBuilder> getFooArrayOrBuilderList();

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
     */
    org.apache.avro.protobuf.noopt.Test.FooOrBuilder getFooArrayOrBuilder(int index);

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
     * 
     * @return A list containing the syms.
     */
    java.util.List<org.apache.avro.protobuf.noopt.Test.A> getSymsList();

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
     * 
     * @return The count of syms.
     */
    int getSymsCount();

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
     * 
     * @param index The index of the element to return.
     * @return The syms at the given index.
     */
    org.apache.avro.protobuf.noopt.Test.A getSyms(int index);

    /**
     * <pre>
     * a recursive type
     * </pre>
     *
     * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
     * 
     * @return Whether the foo field is set.
     */
    boolean hasFoo();

    /**
     * <pre>
     * a recursive type
     * </pre>
     *
     * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
     * 
     * @return The foo.
     */
    org.apache.avro.protobuf.noopt.Test.Foo getFoo();

    /**
     * <pre>
     * a recursive type
     * </pre>
     *
     * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
     */
    org.apache.avro.protobuf.noopt.Test.FooOrBuilder getFooOrBuilder();

    /**
     * <pre>
     * a predefined message type
     * </pre>
     *
     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
     * 
     * @return Whether the timestamp field is set.
     */
    boolean hasTimestamp();

    /**
     * <pre>
     * a predefined message type
     * </pre>
     *
     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
     * 
     * @return The timestamp.
     */
    com.google.protobuf.Timestamp getTimestamp();

    /**
     * <pre>
     * a predefined message type
     * </pre>
     *
     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
     */
    com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder();
  }

  /**
   * Protobuf type {@code org.apache.avro.protobuf.noopt.Foo}
   */
  public static final class Foo extends com.google.protobuf.GeneratedMessage implements
      // @@protoc_insertion_point(message_implements:org.apache.avro.protobuf.noopt.Foo)
      FooOrBuilder {
    private static final long serialVersionUID = 0L;
    static {
      com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
          com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 26, /* patch= */ 1,
          /* suffix= */ "", Foo.class.getName());
    }

    // Use Foo.newBuilder() to construct.
    private Foo(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
    }

    private Foo() {
      string_ = "";
      bytes_ = com.google.protobuf.ByteString.EMPTY;
      enum_ = 3;
      intArray_ = emptyIntList();
      fooArray_ = java.util.Collections.emptyList();
      syms_ = java.util.Collections.emptyList();
    }

    public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
      return org.apache.avro.protobuf.noopt.Test.internal_static_org_apache_avro_protobuf_noopt_Foo_descriptor;
    }

    @java.lang.Override
    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() {
      return org.apache.avro.protobuf.noopt.Test.internal_static_org_apache_avro_protobuf_noopt_Foo_fieldAccessorTable
          .ensureFieldAccessorsInitialized(org.apache.avro.protobuf.noopt.Test.Foo.class,
              org.apache.avro.protobuf.noopt.Test.Foo.Builder.class);
    }

    private int bitField0_;
    public static final int INT32_FIELD_NUMBER = 1;
    private int int32_ = 0;

    /**
     * <pre>
     * all the primitive types
     * </pre>
     *
     * <code>required int32 int32 = 1;</code>
     * 
     * @return Whether the int32 field is set.
     */
    @java.lang.Override
    public boolean hasInt32() {
      return ((bitField0_ & 0x00000001) != 0);
    }

    /**
     * <pre>
     * all the primitive types
     * </pre>
     *
     * <code>required int32 int32 = 1;</code>
     * 
     * @return The int32.
     */
    @java.lang.Override
    public int getInt32() {
      return int32_;
    }

    public static final int INT64_FIELD_NUMBER = 2;
    private long int64_ = 0L;

    /**
     * <code>optional int64 int64 = 2;</code>
     * 
     * @return Whether the int64 field is set.
     */
    @java.lang.Override
    public boolean hasInt64() {
      return ((bitField0_ & 0x00000002) != 0);
    }

    /**
     * <code>optional int64 int64 = 2;</code>
     * 
     * @return The int64.
     */
    @java.lang.Override
    public long getInt64() {
      return int64_;
    }

    public static final int UINT32_FIELD_NUMBER = 3;
    private int uint32_ = 0;

    /**
     * <code>optional uint32 uint32 = 3;</code>
     * 
     * @return Whether the uint32 field is set.
     */
    @java.lang.Override
    public boolean hasUint32() {
      return ((bitField0_ & 0x00000004) != 0);
    }

    /**
     * <code>optional uint32 uint32 = 3;</code>
     * 
     * @return The uint32.
     */
    @java.lang.Override
    public int getUint32() {
      return uint32_;
    }

    public static final int UINT64_FIELD_NUMBER = 4;
    private long uint64_ = 0L;

    /**
     * <code>optional uint64 uint64 = 4;</code>
     * 
     * @return Whether the uint64 field is set.
     */
    @java.lang.Override
    public boolean hasUint64() {
      return ((bitField0_ & 0x00000008) != 0);
    }

    /**
     * <code>optional uint64 uint64 = 4;</code>
     * 
     * @return The uint64.
     */
    @java.lang.Override
    public long getUint64() {
      return uint64_;
    }

    public static final int SINT32_FIELD_NUMBER = 5;
    private int sint32_ = 0;

    /**
     * <code>optional sint32 sint32 = 5;</code>
     * 
     * @return Whether the sint32 field is set.
     */
    @java.lang.Override
    public boolean hasSint32() {
      return ((bitField0_ & 0x00000010) != 0);
    }

    /**
     * <code>optional sint32 sint32 = 5;</code>
     * 
     * @return The sint32.
     */
    @java.lang.Override
    public int getSint32() {
      return sint32_;
    }

    public static final int SINT64_FIELD_NUMBER = 6;
    private long sint64_ = 0L;

    /**
     * <code>optional sint64 sint64 = 6;</code>
     * 
     * @return Whether the sint64 field is set.
     */
    @java.lang.Override
    public boolean hasSint64() {
      return ((bitField0_ & 0x00000020) != 0);
    }

    /**
     * <code>optional sint64 sint64 = 6;</code>
     * 
     * @return The sint64.
     */
    @java.lang.Override
    public long getSint64() {
      return sint64_;
    }

    public static final int FIXED32_FIELD_NUMBER = 7;
    private int fixed32_ = 0;

    /**
     * <code>optional fixed32 fixed32 = 7;</code>
     * 
     * @return Whether the fixed32 field is set.
     */
    @java.lang.Override
    public boolean hasFixed32() {
      return ((bitField0_ & 0x00000040) != 0);
    }

    /**
     * <code>optional fixed32 fixed32 = 7;</code>
     * 
     * @return The fixed32.
     */
    @java.lang.Override
    public int getFixed32() {
      return fixed32_;
    }

    public static final int FIXED64_FIELD_NUMBER = 8;
    private long fixed64_ = 0L;

    /**
     * <code>optional fixed64 fixed64 = 8;</code>
     * 
     * @return Whether the fixed64 field is set.
     */
    @java.lang.Override
    public boolean hasFixed64() {
      return ((bitField0_ & 0x00000080) != 0);
    }

    /**
     * <code>optional fixed64 fixed64 = 8;</code>
     * 
     * @return The fixed64.
     */
    @java.lang.Override
    public long getFixed64() {
      return fixed64_;
    }

    public static final int SFIXED32_FIELD_NUMBER = 9;
    private int sfixed32_ = 0;

    /**
     * <code>optional sfixed32 sfixed32 = 9;</code>
     * 
     * @return Whether the sfixed32 field is set.
     */
    @java.lang.Override
    public boolean hasSfixed32() {
      return ((bitField0_ & 0x00000100) != 0);
    }

    /**
     * <code>optional sfixed32 sfixed32 = 9;</code>
     * 
     * @return The sfixed32.
     */
    @java.lang.Override
    public int getSfixed32() {
      return sfixed32_;
    }

    public static final int SFIXED64_FIELD_NUMBER = 10;
    private long sfixed64_ = 0L;

    /**
     * <code>optional sfixed64 sfixed64 = 10;</code>
     * 
     * @return Whether the sfixed64 field is set.
     */
    @java.lang.Override
    public boolean hasSfixed64() {
      return ((bitField0_ & 0x00000200) != 0);
    }

    /**
     * <code>optional sfixed64 sfixed64 = 10;</code>
     * 
     * @return The sfixed64.
     */
    @java.lang.Override
    public long getSfixed64() {
      return sfixed64_;
    }

    public static final int FLOAT_FIELD_NUMBER = 11;
    private float float_ = 0F;

    /**
     * <code>optional float float = 11;</code>
     * 
     * @return Whether the float field is set.
     */
    @java.lang.Override
    public boolean hasFloat() {
      return ((bitField0_ & 0x00000400) != 0);
    }

    /**
     * <code>optional float float = 11;</code>
     * 
     * @return The float.
     */
    @java.lang.Override
    public float getFloat() {
      return float_;
    }

    public static final int DOUBLE_FIELD_NUMBER = 12;
    private double double_ = 0D;

    /**
     * <code>optional double double = 12;</code>
     * 
     * @return Whether the double field is set.
     */
    @java.lang.Override
    public boolean hasDouble() {
      return ((bitField0_ & 0x00000800) != 0);
    }

    /**
     * <code>optional double double = 12;</code>
     * 
     * @return The double.
     */
    @java.lang.Override
    public double getDouble() {
      return double_;
    }

    public static final int BOOL_FIELD_NUMBER = 13;
    private boolean bool_ = false;

    /**
     * <code>optional bool bool = 13;</code>
     * 
     * @return Whether the bool field is set.
     */
    @java.lang.Override
    public boolean hasBool() {
      return ((bitField0_ & 0x00001000) != 0);
    }

    /**
     * <code>optional bool bool = 13;</code>
     * 
     * @return The bool.
     */
    @java.lang.Override
    public boolean getBool() {
      return bool_;
    }

    public static final int STRING_FIELD_NUMBER = 14;
    @SuppressWarnings("serial")
    private volatile java.lang.Object string_ = "";

    /**
     * <code>optional string string = 14;</code>
     * 
     * @return Whether the string field is set.
     */
    @java.lang.Override
    public boolean hasString() {
      return ((bitField0_ & 0x00002000) != 0);
    }

    /**
     * <code>optional string string = 14;</code>
     * 
     * @return The string.
     */
    @java.lang.Override
    public java.lang.String getString() {
      java.lang.Object ref = string_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          string_ = s;
        }
        return s;
      }
    }

    /**
     * <code>optional string string = 14;</code>
     * 
     * @return The bytes for string.
     */
    @java.lang.Override
    public com.google.protobuf.ByteString getStringBytes() {
      java.lang.Object ref = string_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
        string_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    public static final int BYTES_FIELD_NUMBER = 15;
    private com.google.protobuf.ByteString bytes_ = com.google.protobuf.ByteString.EMPTY;

    /**
     * <code>optional bytes bytes = 15;</code>
     * 
     * @return Whether the bytes field is set.
     */
    @java.lang.Override
    public boolean hasBytes() {
      return ((bitField0_ & 0x00004000) != 0);
    }

    /**
     * <code>optional bytes bytes = 15;</code>
     * 
     * @return The bytes.
     */
    @java.lang.Override
    public com.google.protobuf.ByteString getBytes() {
      return bytes_;
    }

    public static final int ENUM_FIELD_NUMBER = 16;
    private int enum_ = 3;

    /**
     * <code>optional .org.apache.avro.protobuf.noopt.A enum = 16 [default = Z];</code>
     * 
     * @return Whether the enum field is set.
     */
    @java.lang.Override
    public boolean hasEnum() {
      return ((bitField0_ & 0x00008000) != 0);
    }

    /**
     * <code>optional .org.apache.avro.protobuf.noopt.A enum = 16 [default = Z];</code>
     * 
     * @return The enum.
     */
    @java.lang.Override
    public org.apache.avro.protobuf.noopt.Test.A getEnum() {
      org.apache.avro.protobuf.noopt.Test.A result = org.apache.avro.protobuf.noopt.Test.A.forNumber(enum_);
      return result == null ? org.apache.avro.protobuf.noopt.Test.A.Z : result;
    }

    public static final int INTARRAY_FIELD_NUMBER = 17;
    @SuppressWarnings("serial")
    private com.google.protobuf.Internal.IntList intArray_ = emptyIntList();

    /**
     * <pre>
     * some repeated types
     * </pre>
     *
     * <code>repeated int32 intArray = 17;</code>
     * 
     * @return A list containing the intArray.
     */
    @java.lang.Override
    public java.util.List<java.lang.Integer> getIntArrayList() {
      return intArray_;
    }

    /**
     * <pre>
     * some repeated types
     * </pre>
     *
     * <code>repeated int32 intArray = 17;</code>
     * 
     * @return The count of intArray.
     */
    public int getIntArrayCount() {
      return intArray_.size();
    }

    /**
     * <pre>
     * some repeated types
     * </pre>
     *
     * <code>repeated int32 intArray = 17;</code>
     * 
     * @param index The index of the element to return.
     * @return The intArray at the given index.
     */
    public int getIntArray(int index) {
      return intArray_.getInt(index);
    }

    public static final int FOOARRAY_FIELD_NUMBER = 20;
    @SuppressWarnings("serial")
    private java.util.List<org.apache.avro.protobuf.noopt.Test.Foo> fooArray_;

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
     */
    @java.lang.Override
    public java.util.List<org.apache.avro.protobuf.noopt.Test.Foo> getFooArrayList() {
      return fooArray_;
    }

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
     */
    @java.lang.Override
    public java.util.List<? extends org.apache.avro.protobuf.noopt.Test.FooOrBuilder> getFooArrayOrBuilderList() {
      return fooArray_;
    }

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
     */
    @java.lang.Override
    public int getFooArrayCount() {
      return fooArray_.size();
    }

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
     */
    @java.lang.Override
    public org.apache.avro.protobuf.noopt.Test.Foo getFooArray(int index) {
      return fooArray_.get(index);
    }

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
     */
    @java.lang.Override
    public org.apache.avro.protobuf.noopt.Test.FooOrBuilder getFooArrayOrBuilder(int index) {
      return fooArray_.get(index);
    }

    public static final int SYMS_FIELD_NUMBER = 19;
    @SuppressWarnings("serial")
    private java.util.List<java.lang.Integer> syms_;
    private static final com.google.protobuf.Internal.ListAdapter.Converter<java.lang.Integer, org.apache.avro.protobuf.noopt.Test.A> syms_converter_ = new com.google.protobuf.Internal.ListAdapter.Converter<java.lang.Integer, org.apache.avro.protobuf.noopt.Test.A>() {
      public org.apache.avro.protobuf.noopt.Test.A convert(java.lang.Integer from) {
        org.apache.avro.protobuf.noopt.Test.A result = org.apache.avro.protobuf.noopt.Test.A.forNumber(from);
        return result == null ? org.apache.avro.protobuf.noopt.Test.A.X : result;
      }
    };

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
     * 
     * @return A list containing the syms.
     */
    @java.lang.Override
    public java.util.List<org.apache.avro.protobuf.noopt.Test.A> getSymsList() {
      return new com.google.protobuf.Internal.ListAdapter<java.lang.Integer, org.apache.avro.protobuf.noopt.Test.A>(
          syms_, syms_converter_);
    }

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
     * 
     * @return The count of syms.
     */
    @java.lang.Override
    public int getSymsCount() {
      return syms_.size();
    }

    /**
     * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
     * 
     * @param index The index of the element to return.
     * @return The syms at the given index.
     */
    @java.lang.Override
    public org.apache.avro.protobuf.noopt.Test.A getSyms(int index) {
      return syms_converter_.convert(syms_.get(index));
    }

    public static final int FOO_FIELD_NUMBER = 18;
    private org.apache.avro.protobuf.noopt.Test.Foo foo_;

    /**
     * <pre>
     * a recursive type
     * </pre>
     *
     * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
     * 
     * @return Whether the foo field is set.
     */
    @java.lang.Override
    public boolean hasFoo() {
      return ((bitField0_ & 0x00010000) != 0);
    }

    /**
     * <pre>
     * a recursive type
     * </pre>
     *
     * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
     * 
     * @return The foo.
     */
    @java.lang.Override
    public org.apache.avro.protobuf.noopt.Test.Foo getFoo() {
      return foo_ == null ? org.apache.avro.protobuf.noopt.Test.Foo.getDefaultInstance() : foo_;
    }

    /**
     * <pre>
     * a recursive type
     * </pre>
     *
     * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
     */
    @java.lang.Override
    public org.apache.avro.protobuf.noopt.Test.FooOrBuilder getFooOrBuilder() {
      return foo_ == null ? org.apache.avro.protobuf.noopt.Test.Foo.getDefaultInstance() : foo_;
    }

    public static final int TIMESTAMP_FIELD_NUMBER = 21;
    private com.google.protobuf.Timestamp timestamp_;

    /**
     * <pre>
     * a predefined message type
     * </pre>
     *
     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
     * 
     * @return Whether the timestamp field is set.
     */
    @java.lang.Override
    public boolean hasTimestamp() {
      return ((bitField0_ & 0x00020000) != 0);
    }

    /**
     * <pre>
     * a predefined message type
     * </pre>
     *
     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
     * 
     * @return The timestamp.
     */
    @java.lang.Override
    public com.google.protobuf.Timestamp getTimestamp() {
      return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
    }

    /**
     * <pre>
     * a predefined message type
     * </pre>
     *
     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
     */
    @java.lang.Override
    public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() {
      return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
    }

    private byte memoizedIsInitialized = -1;

    @java.lang.Override
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized == 1)
        return true;
      if (isInitialized == 0)
        return false;

      if (!hasInt32()) {
        memoizedIsInitialized = 0;
        return false;
      }
      for (int i = 0; i < getFooArrayCount(); i++) {
        if (!getFooArray(i).isInitialized()) {
          memoizedIsInitialized = 0;
          return false;
        }
      }
      if (hasFoo()) {
        if (!getFoo().isInitialized()) {
          memoizedIsInitialized = 0;
          return false;
        }
      }
      memoizedIsInitialized = 1;
      return true;
    }

    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
      if (((bitField0_ & 0x00000001) != 0)) {
        output.writeInt32(1, int32_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        output.writeInt64(2, int64_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        output.writeUInt32(3, uint32_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        output.writeUInt64(4, uint64_);
      }
      if (((bitField0_ & 0x00000010) != 0)) {
        output.writeSInt32(5, sint32_);
      }
      if (((bitField0_ & 0x00000020) != 0)) {
        output.writeSInt64(6, sint64_);
      }
      if (((bitField0_ & 0x00000040) != 0)) {
        output.writeFixed32(7, fixed32_);
      }
      if (((bitField0_ & 0x00000080) != 0)) {
        output.writeFixed64(8, fixed64_);
      }
      if (((bitField0_ & 0x00000100) != 0)) {
        output.writeSFixed32(9, sfixed32_);
      }
      if (((bitField0_ & 0x00000200) != 0)) {
        output.writeSFixed64(10, sfixed64_);
      }
      if (((bitField0_ & 0x00000400) != 0)) {
        output.writeFloat(11, float_);
      }
      if (((bitField0_ & 0x00000800) != 0)) {
        output.writeDouble(12, double_);
      }
      if (((bitField0_ & 0x00001000) != 0)) {
        output.writeBool(13, bool_);
      }
      if (((bitField0_ & 0x00002000) != 0)) {
        com.google.protobuf.GeneratedMessage.writeString(output, 14, string_);
      }
      if (((bitField0_ & 0x00004000) != 0)) {
        output.writeBytes(15, bytes_);
      }
      if (((bitField0_ & 0x00008000) != 0)) {
        output.writeEnum(16, enum_);
      }
      for (int i = 0; i < intArray_.size(); i++) {
        output.writeInt32(17, intArray_.getInt(i));
      }
      if (((bitField0_ & 0x00010000) != 0)) {
        output.writeMessage(18, getFoo());
      }
      for (int i = 0; i < syms_.size(); i++) {
        output.writeEnum(19, syms_.get(i));
      }
      for (int i = 0; i < fooArray_.size(); i++) {
        output.writeMessage(20, fooArray_.get(i));
      }
      if (((bitField0_ & 0x00020000) != 0)) {
        output.writeMessage(21, getTimestamp());
      }
      getUnknownFields().writeTo(output);
    }

    @java.lang.Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1)
        return size;

      size = 0;
      if (((bitField0_ & 0x00000001) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeInt32Size(1, int32_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeInt64Size(2, int64_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeUInt32Size(3, uint32_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeUInt64Size(4, uint64_);
      }
      if (((bitField0_ & 0x00000010) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeSInt32Size(5, sint32_);
      }
      if (((bitField0_ & 0x00000020) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeSInt64Size(6, sint64_);
      }
      if (((bitField0_ & 0x00000040) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeFixed32Size(7, fixed32_);
      }
      if (((bitField0_ & 0x00000080) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeFixed64Size(8, fixed64_);
      }
      if (((bitField0_ & 0x00000100) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeSFixed32Size(9, sfixed32_);
      }
      if (((bitField0_ & 0x00000200) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeSFixed64Size(10, sfixed64_);
      }
      if (((bitField0_ & 0x00000400) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeFloatSize(11, float_);
      }
      if (((bitField0_ & 0x00000800) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeDoubleSize(12, double_);
      }
      if (((bitField0_ & 0x00001000) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeBoolSize(13, bool_);
      }
      if (((bitField0_ & 0x00002000) != 0)) {
        size += com.google.protobuf.GeneratedMessage.computeStringSize(14, string_);
      }
      if (((bitField0_ & 0x00004000) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeBytesSize(15, bytes_);
      }
      if (((bitField0_ & 0x00008000) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeEnumSize(16, enum_);
      }
      {
        int dataSize = 0;
        for (int i = 0; i < intArray_.size(); i++) {
          dataSize += com.google.protobuf.CodedOutputStream.computeInt32SizeNoTag(intArray_.getInt(i));
        }
        size += dataSize;
        size += 2 * getIntArrayList().size();
      }
      if (((bitField0_ & 0x00010000) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeMessageSize(18, getFoo());
      }
      {
        int dataSize = 0;
        for (int i = 0; i < syms_.size(); i++) {
          dataSize += com.google.protobuf.CodedOutputStream.computeEnumSizeNoTag(syms_.get(i));
        }
        size += dataSize;
        size += 2 * syms_.size();
      }
      for (int i = 0; i < fooArray_.size(); i++) {
        size += com.google.protobuf.CodedOutputStream.computeMessageSize(20, fooArray_.get(i));
      }
      if (((bitField0_ & 0x00020000) != 0)) {
        size += com.google.protobuf.CodedOutputStream.computeMessageSize(21, getTimestamp());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSize = size;
      return size;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
        return true;
      }
      if (!(obj instanceof org.apache.avro.protobuf.noopt.Test.Foo)) {
        return super.equals(obj);
      }
      org.apache.avro.protobuf.noopt.Test.Foo other = (org.apache.avro.protobuf.noopt.Test.Foo) obj;

      if (hasInt32() != other.hasInt32())
        return false;
      if (hasInt32()) {
        if (getInt32() != other.getInt32())
          return false;
      }
      if (hasInt64() != other.hasInt64())
        return false;
      if (hasInt64()) {
        if (getInt64() != other.getInt64())
          return false;
      }
      if (hasUint32() != other.hasUint32())
        return false;
      if (hasUint32()) {
        if (getUint32() != other.getUint32())
          return false;
      }
      if (hasUint64() != other.hasUint64())
        return false;
      if (hasUint64()) {
        if (getUint64() != other.getUint64())
          return false;
      }
      if (hasSint32() != other.hasSint32())
        return false;
      if (hasSint32()) {
        if (getSint32() != other.getSint32())
          return false;
      }
      if (hasSint64() != other.hasSint64())
        return false;
      if (hasSint64()) {
        if (getSint64() != other.getSint64())
          return false;
      }
      if (hasFixed32() != other.hasFixed32())
        return false;
      if (hasFixed32()) {
        if (getFixed32() != other.getFixed32())
          return false;
      }
      if (hasFixed64() != other.hasFixed64())
        return false;
      if (hasFixed64()) {
        if (getFixed64() != other.getFixed64())
          return false;
      }
      if (hasSfixed32() != other.hasSfixed32())
        return false;
      if (hasSfixed32()) {
        if (getSfixed32() != other.getSfixed32())
          return false;
      }
      if (hasSfixed64() != other.hasSfixed64())
        return false;
      if (hasSfixed64()) {
        if (getSfixed64() != other.getSfixed64())
          return false;
      }
      if (hasFloat() != other.hasFloat())
        return false;
      if (hasFloat()) {
        if (java.lang.Float.floatToIntBits(getFloat()) != java.lang.Float.floatToIntBits(other.getFloat()))
          return false;
      }
      if (hasDouble() != other.hasDouble())
        return false;
      if (hasDouble()) {
        if (java.lang.Double.doubleToLongBits(getDouble()) != java.lang.Double.doubleToLongBits(other.getDouble()))
          return false;
      }
      if (hasBool() != other.hasBool())
        return false;
      if (hasBool()) {
        if (getBool() != other.getBool())
          return false;
      }
      if (hasString() != other.hasString())
        return false;
      if (hasString()) {
        if (!getString().equals(other.getString()))
          return false;
      }
      if (hasBytes() != other.hasBytes())
        return false;
      if (hasBytes()) {
        if (!getBytes().equals(other.getBytes()))
          return false;
      }
      if (hasEnum() != other.hasEnum())
        return false;
      if (hasEnum()) {
        if (enum_ != other.enum_)
          return false;
      }
      if (!getIntArrayList().equals(other.getIntArrayList()))
        return false;
      if (!getFooArrayList().equals(other.getFooArrayList()))
        return false;
      if (!syms_.equals(other.syms_))
        return false;
      if (hasFoo() != other.hasFoo())
        return false;
      if (hasFoo()) {
        if (!getFoo().equals(other.getFoo()))
          return false;
      }
      if (hasTimestamp() != other.hasTimestamp())
        return false;
      if (hasTimestamp()) {
        if (!getTimestamp().equals(other.getTimestamp()))
          return false;
      }
      if (!getUnknownFields().equals(other.getUnknownFields()))
        return false;
      return true;
    }

    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptor().hashCode();
      if (hasInt32()) {
        hash = (37 * hash) + INT32_FIELD_NUMBER;
        hash = (53 * hash) + getInt32();
      }
      if (hasInt64()) {
        hash = (37 * hash) + INT64_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getInt64());
      }
      if (hasUint32()) {
        hash = (37 * hash) + UINT32_FIELD_NUMBER;
        hash = (53 * hash) + getUint32();
      }
      if (hasUint64()) {
        hash = (37 * hash) + UINT64_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getUint64());
      }
      if (hasSint32()) {
        hash = (37 * hash) + SINT32_FIELD_NUMBER;
        hash = (53 * hash) + getSint32();
      }
      if (hasSint64()) {
        hash = (37 * hash) + SINT64_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getSint64());
      }
      if (hasFixed32()) {
        hash = (37 * hash) + FIXED32_FIELD_NUMBER;
        hash = (53 * hash) + getFixed32();
      }
      if (hasFixed64()) {
        hash = (37 * hash) + FIXED64_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getFixed64());
      }
      if (hasSfixed32()) {
        hash = (37 * hash) + SFIXED32_FIELD_NUMBER;
        hash = (53 * hash) + getSfixed32();
      }
      if (hasSfixed64()) {
        hash = (37 * hash) + SFIXED64_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getSfixed64());
      }
      if (hasFloat()) {
        hash = (37 * hash) + FLOAT_FIELD_NUMBER;
        hash = (53 * hash) + java.lang.Float.floatToIntBits(getFloat());
      }
      if (hasDouble()) {
        hash = (37 * hash) + DOUBLE_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashLong(java.lang.Double.doubleToLongBits(getDouble()));
      }
      if (hasBool()) {
        hash = (37 * hash) + BOOL_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(getBool());
      }
      if (hasString()) {
        hash = (37 * hash) + STRING_FIELD_NUMBER;
        hash = (53 * hash) + getString().hashCode();
      }
      if (hasBytes()) {
        hash = (37 * hash) + BYTES_FIELD_NUMBER;
        hash = (53 * hash) + getBytes().hashCode();
      }
      if (hasEnum()) {
        hash = (37 * hash) + ENUM_FIELD_NUMBER;
        hash = (53 * hash) + enum_;
      }
      if (getIntArrayCount() > 0) {
        hash = (37 * hash) + INTARRAY_FIELD_NUMBER;
        hash = (53 * hash) + getIntArrayList().hashCode();
      }
      if (getFooArrayCount() > 0) {
        hash = (37 * hash) + FOOARRAY_FIELD_NUMBER;
        hash = (53 * hash) + getFooArrayList().hashCode();
      }
      if (getSymsCount() > 0) {
        hash = (37 * hash) + SYMS_FIELD_NUMBER;
        hash = (53 * hash) + syms_.hashCode();
      }
      if (hasFoo()) {
        hash = (37 * hash) + FOO_FIELD_NUMBER;
        hash = (53 * hash) + getFoo().hashCode();
      }
      if (hasTimestamp()) {
        hash = (37 * hash) + TIMESTAMP_FIELD_NUMBER;
        hash = (53 * hash) + getTimestamp().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseFrom(java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseFrom(java.nio.ByteBuffer data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseFrom(com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseFrom(com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseFrom(byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseFrom(java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseDelimitedFrom(java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseFrom(com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo parseFrom(com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);
    }

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

    public static Builder newBuilder() {
      return DEFAULT_INSTANCE.toBuilder();
    }

    public static Builder newBuilder(org.apache.avro.protobuf.noopt.Test.Foo prototype) {
      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }

    @java.lang.Override
    public Builder toBuilder() {
      return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
    }

    @java.lang.Override
    protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }

    /**
     * Protobuf type {@code org.apache.avro.protobuf.noopt.Foo}
     */
    public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:org.apache.avro.protobuf.noopt.Foo)
        org.apache.avro.protobuf.noopt.Test.FooOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
        return org.apache.avro.protobuf.noopt.Test.internal_static_org_apache_avro_protobuf_noopt_Foo_descriptor;
      }

      @java.lang.Override
      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() {
        return org.apache.avro.protobuf.noopt.Test.internal_static_org_apache_avro_protobuf_noopt_Foo_fieldAccessorTable
            .ensureFieldAccessorsInitialized(org.apache.avro.protobuf.noopt.Test.Foo.class,
                org.apache.avro.protobuf.noopt.Test.Foo.Builder.class);
      }

      // Construct using org.apache.avro.protobuf.noopt.Test.Foo.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }

      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
          getFooArrayFieldBuilder();
          getFooFieldBuilder();
          getTimestampFieldBuilder();
        }
      }

      @java.lang.Override
      public Builder clear() {
        super.clear();
        bitField0_ = 0;
        int32_ = 0;
        int64_ = 0L;
        uint32_ = 0;
        uint64_ = 0L;
        sint32_ = 0;
        sint64_ = 0L;
        fixed32_ = 0;
        fixed64_ = 0L;
        sfixed32_ = 0;
        sfixed64_ = 0L;
        float_ = 0F;
        double_ = 0D;
        bool_ = false;
        string_ = "";
        bytes_ = com.google.protobuf.ByteString.EMPTY;
        enum_ = 3;
        intArray_ = emptyIntList();
        if (fooArrayBuilder_ == null) {
          fooArray_ = java.util.Collections.emptyList();
        } else {
          fooArray_ = null;
          fooArrayBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00020000);
        syms_ = java.util.Collections.emptyList();
        bitField0_ = (bitField0_ & ~0x00040000);
        foo_ = null;
        if (fooBuilder_ != null) {
          fooBuilder_.dispose();
          fooBuilder_ = null;
        }
        timestamp_ = null;
        if (timestampBuilder_ != null) {
          timestampBuilder_.dispose();
          timestampBuilder_ = null;
        }
        return this;
      }

      @java.lang.Override
      public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
        return org.apache.avro.protobuf.noopt.Test.internal_static_org_apache_avro_protobuf_noopt_Foo_descriptor;
      }

      @java.lang.Override
      public org.apache.avro.protobuf.noopt.Test.Foo getDefaultInstanceForType() {
        return org.apache.avro.protobuf.noopt.Test.Foo.getDefaultInstance();
      }

      @java.lang.Override
      public org.apache.avro.protobuf.noopt.Test.Foo build() {
        org.apache.avro.protobuf.noopt.Test.Foo result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      @java.lang.Override
      public org.apache.avro.protobuf.noopt.Test.Foo buildPartial() {
        org.apache.avro.protobuf.noopt.Test.Foo result = new org.apache.avro.protobuf.noopt.Test.Foo(this);
        buildPartialRepeatedFields(result);
        if (bitField0_ != 0) {
          buildPartial0(result);
        }
        onBuilt();
        return result;
      }

      private void buildPartialRepeatedFields(org.apache.avro.protobuf.noopt.Test.Foo result) {
        if (fooArrayBuilder_ == null) {
          if (((bitField0_ & 0x00020000) != 0)) {
            fooArray_ = java.util.Collections.unmodifiableList(fooArray_);
            bitField0_ = (bitField0_ & ~0x00020000);
          }
          result.fooArray_ = fooArray_;
        } else {
          result.fooArray_ = fooArrayBuilder_.build();
        }
        if (((bitField0_ & 0x00040000) != 0)) {
          syms_ = java.util.Collections.unmodifiableList(syms_);
          bitField0_ = (bitField0_ & ~0x00040000);
        }
        result.syms_ = syms_;
      }

      private void buildPartial0(org.apache.avro.protobuf.noopt.Test.Foo result) {
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          result.int32_ = int32_;
          to_bitField0_ |= 0x00000001;
        }
        if (((from_bitField0_ & 0x00000002) != 0)) {
          result.int64_ = int64_;
          to_bitField0_ |= 0x00000002;
        }
        if (((from_bitField0_ & 0x00000004) != 0)) {
          result.uint32_ = uint32_;
          to_bitField0_ |= 0x00000004;
        }
        if (((from_bitField0_ & 0x00000008) != 0)) {
          result.uint64_ = uint64_;
          to_bitField0_ |= 0x00000008;
        }
        if (((from_bitField0_ & 0x00000010) != 0)) {
          result.sint32_ = sint32_;
          to_bitField0_ |= 0x00000010;
        }
        if (((from_bitField0_ & 0x00000020) != 0)) {
          result.sint64_ = sint64_;
          to_bitField0_ |= 0x00000020;
        }
        if (((from_bitField0_ & 0x00000040) != 0)) {
          result.fixed32_ = fixed32_;
          to_bitField0_ |= 0x00000040;
        }
        if (((from_bitField0_ & 0x00000080) != 0)) {
          result.fixed64_ = fixed64_;
          to_bitField0_ |= 0x00000080;
        }
        if (((from_bitField0_ & 0x00000100) != 0)) {
          result.sfixed32_ = sfixed32_;
          to_bitField0_ |= 0x00000100;
        }
        if (((from_bitField0_ & 0x00000200) != 0)) {
          result.sfixed64_ = sfixed64_;
          to_bitField0_ |= 0x00000200;
        }
        if (((from_bitField0_ & 0x00000400) != 0)) {
          result.float_ = float_;
          to_bitField0_ |= 0x00000400;
        }
        if (((from_bitField0_ & 0x00000800) != 0)) {
          result.double_ = double_;
          to_bitField0_ |= 0x00000800;
        }
        if (((from_bitField0_ & 0x00001000) != 0)) {
          result.bool_ = bool_;
          to_bitField0_ |= 0x00001000;
        }
        if (((from_bitField0_ & 0x00002000) != 0)) {
          result.string_ = string_;
          to_bitField0_ |= 0x00002000;
        }
        if (((from_bitField0_ & 0x00004000) != 0)) {
          result.bytes_ = bytes_;
          to_bitField0_ |= 0x00004000;
        }
        if (((from_bitField0_ & 0x00008000) != 0)) {
          result.enum_ = enum_;
          to_bitField0_ |= 0x00008000;
        }
        if (((from_bitField0_ & 0x00010000) != 0)) {
          intArray_.makeImmutable();
          result.intArray_ = intArray_;
        }
        if (((from_bitField0_ & 0x00080000) != 0)) {
          result.foo_ = fooBuilder_ == null ? foo_ : fooBuilder_.build();
          to_bitField0_ |= 0x00010000;
        }
        if (((from_bitField0_ & 0x00100000) != 0)) {
          result.timestamp_ = timestampBuilder_ == null ? timestamp_ : timestampBuilder_.build();
          to_bitField0_ |= 0x00020000;
        }
        result.bitField0_ |= to_bitField0_;
      }

      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.avro.protobuf.noopt.Test.Foo) {
          return mergeFrom((org.apache.avro.protobuf.noopt.Test.Foo) other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.avro.protobuf.noopt.Test.Foo other) {
        if (other == org.apache.avro.protobuf.noopt.Test.Foo.getDefaultInstance())
          return this;
        if (other.hasInt32()) {
          setInt32(other.getInt32());
        }
        if (other.hasInt64()) {
          setInt64(other.getInt64());
        }
        if (other.hasUint32()) {
          setUint32(other.getUint32());
        }
        if (other.hasUint64()) {
          setUint64(other.getUint64());
        }
        if (other.hasSint32()) {
          setSint32(other.getSint32());
        }
        if (other.hasSint64()) {
          setSint64(other.getSint64());
        }
        if (other.hasFixed32()) {
          setFixed32(other.getFixed32());
        }
        if (other.hasFixed64()) {
          setFixed64(other.getFixed64());
        }
        if (other.hasSfixed32()) {
          setSfixed32(other.getSfixed32());
        }
        if (other.hasSfixed64()) {
          setSfixed64(other.getSfixed64());
        }
        if (other.hasFloat()) {
          setFloat(other.getFloat());
        }
        if (other.hasDouble()) {
          setDouble(other.getDouble());
        }
        if (other.hasBool()) {
          setBool(other.getBool());
        }
        if (other.hasString()) {
          string_ = other.string_;
          bitField0_ |= 0x00002000;
          onChanged();
        }
        if (other.hasBytes()) {
          setBytes(other.getBytes());
        }
        if (other.hasEnum()) {
          setEnum(other.getEnum());
        }
        if (!other.intArray_.isEmpty()) {
          if (intArray_.isEmpty()) {
            intArray_ = other.intArray_;
            intArray_.makeImmutable();
            bitField0_ |= 0x00010000;
          } else {
            ensureIntArrayIsMutable();
            intArray_.addAll(other.intArray_);
          }
          onChanged();
        }
        if (fooArrayBuilder_ == null) {
          if (!other.fooArray_.isEmpty()) {
            if (fooArray_.isEmpty()) {
              fooArray_ = other.fooArray_;
              bitField0_ = (bitField0_ & ~0x00020000);
            } else {
              ensureFooArrayIsMutable();
              fooArray_.addAll(other.fooArray_);
            }
            onChanged();
          }
        } else {
          if (!other.fooArray_.isEmpty()) {
            if (fooArrayBuilder_.isEmpty()) {
              fooArrayBuilder_.dispose();
              fooArrayBuilder_ = null;
              fooArray_ = other.fooArray_;
              bitField0_ = (bitField0_ & ~0x00020000);
              fooArrayBuilder_ = com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? getFooArrayFieldBuilder()
                  : null;
            } else {
              fooArrayBuilder_.addAllMessages(other.fooArray_);
            }
          }
        }
        if (!other.syms_.isEmpty()) {
          if (syms_.isEmpty()) {
            syms_ = other.syms_;
            bitField0_ = (bitField0_ & ~0x00040000);
          } else {
            ensureSymsIsMutable();
            syms_.addAll(other.syms_);
          }
          onChanged();
        }
        if (other.hasFoo()) {
          mergeFoo(other.getFoo());
        }
        if (other.hasTimestamp()) {
          mergeTimestamp(other.getTimestamp());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        onChanged();
        return this;
      }

      @java.lang.Override
      public final boolean isInitialized() {
        if (!hasInt32()) {
          return false;
        }
        for (int i = 0; i < getFooArrayCount(); i++) {
          if (!getFooArray(i).isInitialized()) {
            return false;
          }
        }
        if (hasFoo()) {
          if (!getFoo().isInitialized()) {
            return false;
          }
        }
        return true;
      }

      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
        if (extensionRegistry == null) {
          throw new java.lang.NullPointerException();
        }
        try {
          boolean done = false;
          while (!done) {
            int tag = input.readTag();
            switch (tag) {
            case 0:
              done = true;
              break;
            case 8: {
              int32_ = input.readInt32();
              bitField0_ |= 0x00000001;
              break;
            } // case 8
            case 16: {
              int64_ = input.readInt64();
              bitField0_ |= 0x00000002;
              break;
            } // case 16
            case 24: {
              uint32_ = input.readUInt32();
              bitField0_ |= 0x00000004;
              break;
            } // case 24
            case 32: {
              uint64_ = input.readUInt64();
              bitField0_ |= 0x00000008;
              break;
            } // case 32
            case 40: {
              sint32_ = input.readSInt32();
              bitField0_ |= 0x00000010;
              break;
            } // case 40
            case 48: {
              sint64_ = input.readSInt64();
              bitField0_ |= 0x00000020;
              break;
            } // case 48
            case 61: {
              fixed32_ = input.readFixed32();
              bitField0_ |= 0x00000040;
              break;
            } // case 61
            case 65: {
              fixed64_ = input.readFixed64();
              bitField0_ |= 0x00000080;
              break;
            } // case 65
            case 77: {
              sfixed32_ = input.readSFixed32();
              bitField0_ |= 0x00000100;
              break;
            } // case 77
            case 81: {
              sfixed64_ = input.readSFixed64();
              bitField0_ |= 0x00000200;
              break;
            } // case 81
            case 93: {
              float_ = input.readFloat();
              bitField0_ |= 0x00000400;
              break;
            } // case 93
            case 97: {
              double_ = input.readDouble();
              bitField0_ |= 0x00000800;
              break;
            } // case 97
            case 104: {
              bool_ = input.readBool();
              bitField0_ |= 0x00001000;
              break;
            } // case 104
            case 114: {
              string_ = input.readBytes();
              bitField0_ |= 0x00002000;
              break;
            } // case 114
            case 122: {
              bytes_ = input.readBytes();
              bitField0_ |= 0x00004000;
              break;
            } // case 122
            case 128: {
              int tmpRaw = input.readEnum();
              org.apache.avro.protobuf.noopt.Test.A tmpValue = org.apache.avro.protobuf.noopt.Test.A.forNumber(tmpRaw);
              if (tmpValue == null) {
                mergeUnknownVarintField(16, tmpRaw);
              } else {
                enum_ = tmpRaw;
                bitField0_ |= 0x00008000;
              }
              break;
            } // case 128
            case 136: {
              int v = input.readInt32();
              ensureIntArrayIsMutable();
              intArray_.addInt(v);
              break;
            } // case 136
            case 138: {
              int length = input.readRawVarint32();
              int limit = input.pushLimit(length);
              ensureIntArrayIsMutable();
              while (input.getBytesUntilLimit() > 0) {
                intArray_.addInt(input.readInt32());
              }
              input.popLimit(limit);
              break;
            } // case 138
            case 146: {
              input.readMessage(getFooFieldBuilder().getBuilder(), extensionRegistry);
              bitField0_ |= 0x00080000;
              break;
            } // case 146
            case 152: {
              int tmpRaw = input.readEnum();
              org.apache.avro.protobuf.noopt.Test.A tmpValue = org.apache.avro.protobuf.noopt.Test.A.forNumber(tmpRaw);
              if (tmpValue == null) {
                mergeUnknownVarintField(19, tmpRaw);
              } else {
                ensureSymsIsMutable();
                syms_.add(tmpRaw);
              }
              break;
            } // case 152
            case 154: {
              int length = input.readRawVarint32();
              int oldLimit = input.pushLimit(length);
              while (input.getBytesUntilLimit() > 0) {
                int tmpRaw = input.readEnum();
                org.apache.avro.protobuf.noopt.Test.A tmpValue = org.apache.avro.protobuf.noopt.Test.A
                    .forNumber(tmpRaw);
                if (tmpValue == null) {
                  mergeUnknownVarintField(19, tmpRaw);
                } else {
                  ensureSymsIsMutable();
                  syms_.add(tmpRaw);
                }
              }
              input.popLimit(oldLimit);
              break;
            } // case 154
            case 162: {
              org.apache.avro.protobuf.noopt.Test.Foo m = input
                  .readMessage(org.apache.avro.protobuf.noopt.Test.Foo.parser(), extensionRegistry);
              if (fooArrayBuilder_ == null) {
                ensureFooArrayIsMutable();
                fooArray_.add(m);
              } else {
                fooArrayBuilder_.addMessage(m);
              }
              break;
            } // case 162
            case 170: {
              input.readMessage(getTimestampFieldBuilder().getBuilder(), extensionRegistry);
              bitField0_ |= 0x00100000;
              break;
            } // case 170
            default: {
              if (!super.parseUnknownField(input, extensionRegistry, tag)) {
                done = true; // was an endgroup tag
              }
              break;
            } // default:
            } // switch (tag)
          } // while (!done)
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.unwrapIOException();
        } finally {
          onChanged();
        } // finally
        return this;
      }

      private int bitField0_;

      private int int32_;

      /**
       * <pre>
       * all the primitive types
       * </pre>
       *
       * <code>required int32 int32 = 1;</code>
       * 
       * @return Whether the int32 field is set.
       */
      @java.lang.Override
      public boolean hasInt32() {
        return ((bitField0_ & 0x00000001) != 0);
      }

      /**
       * <pre>
       * all the primitive types
       * </pre>
       *
       * <code>required int32 int32 = 1;</code>
       * 
       * @return The int32.
       */
      @java.lang.Override
      public int getInt32() {
        return int32_;
      }

      /**
       * <pre>
       * all the primitive types
       * </pre>
       *
       * <code>required int32 int32 = 1;</code>
       * 
       * @param value The int32 to set.
       * @return This builder for chaining.
       */
      public Builder setInt32(int value) {

        int32_ = value;
        bitField0_ |= 0x00000001;
        onChanged();
        return this;
      }

      /**
       * <pre>
       * all the primitive types
       * </pre>
       *
       * <code>required int32 int32 = 1;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearInt32() {
        bitField0_ = (bitField0_ & ~0x00000001);
        int32_ = 0;
        onChanged();
        return this;
      }

      private long int64_;

      /**
       * <code>optional int64 int64 = 2;</code>
       * 
       * @return Whether the int64 field is set.
       */
      @java.lang.Override
      public boolean hasInt64() {
        return ((bitField0_ & 0x00000002) != 0);
      }

      /**
       * <code>optional int64 int64 = 2;</code>
       * 
       * @return The int64.
       */
      @java.lang.Override
      public long getInt64() {
        return int64_;
      }

      /**
       * <code>optional int64 int64 = 2;</code>
       * 
       * @param value The int64 to set.
       * @return This builder for chaining.
       */
      public Builder setInt64(long value) {

        int64_ = value;
        bitField0_ |= 0x00000002;
        onChanged();
        return this;
      }

      /**
       * <code>optional int64 int64 = 2;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearInt64() {
        bitField0_ = (bitField0_ & ~0x00000002);
        int64_ = 0L;
        onChanged();
        return this;
      }

      private int uint32_;

      /**
       * <code>optional uint32 uint32 = 3;</code>
       * 
       * @return Whether the uint32 field is set.
       */
      @java.lang.Override
      public boolean hasUint32() {
        return ((bitField0_ & 0x00000004) != 0);
      }

      /**
       * <code>optional uint32 uint32 = 3;</code>
       * 
       * @return The uint32.
       */
      @java.lang.Override
      public int getUint32() {
        return uint32_;
      }

      /**
       * <code>optional uint32 uint32 = 3;</code>
       * 
       * @param value The uint32 to set.
       * @return This builder for chaining.
       */
      public Builder setUint32(int value) {

        uint32_ = value;
        bitField0_ |= 0x00000004;
        onChanged();
        return this;
      }

      /**
       * <code>optional uint32 uint32 = 3;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearUint32() {
        bitField0_ = (bitField0_ & ~0x00000004);
        uint32_ = 0;
        onChanged();
        return this;
      }

      private long uint64_;

      /**
       * <code>optional uint64 uint64 = 4;</code>
       * 
       * @return Whether the uint64 field is set.
       */
      @java.lang.Override
      public boolean hasUint64() {
        return ((bitField0_ & 0x00000008) != 0);
      }

      /**
       * <code>optional uint64 uint64 = 4;</code>
       * 
       * @return The uint64.
       */
      @java.lang.Override
      public long getUint64() {
        return uint64_;
      }

      /**
       * <code>optional uint64 uint64 = 4;</code>
       * 
       * @param value The uint64 to set.
       * @return This builder for chaining.
       */
      public Builder setUint64(long value) {

        uint64_ = value;
        bitField0_ |= 0x00000008;
        onChanged();
        return this;
      }

      /**
       * <code>optional uint64 uint64 = 4;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearUint64() {
        bitField0_ = (bitField0_ & ~0x00000008);
        uint64_ = 0L;
        onChanged();
        return this;
      }

      private int sint32_;

      /**
       * <code>optional sint32 sint32 = 5;</code>
       * 
       * @return Whether the sint32 field is set.
       */
      @java.lang.Override
      public boolean hasSint32() {
        return ((bitField0_ & 0x00000010) != 0);
      }

      /**
       * <code>optional sint32 sint32 = 5;</code>
       * 
       * @return The sint32.
       */
      @java.lang.Override
      public int getSint32() {
        return sint32_;
      }

      /**
       * <code>optional sint32 sint32 = 5;</code>
       * 
       * @param value The sint32 to set.
       * @return This builder for chaining.
       */
      public Builder setSint32(int value) {

        sint32_ = value;
        bitField0_ |= 0x00000010;
        onChanged();
        return this;
      }

      /**
       * <code>optional sint32 sint32 = 5;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearSint32() {
        bitField0_ = (bitField0_ & ~0x00000010);
        sint32_ = 0;
        onChanged();
        return this;
      }

      private long sint64_;

      /**
       * <code>optional sint64 sint64 = 6;</code>
       * 
       * @return Whether the sint64 field is set.
       */
      @java.lang.Override
      public boolean hasSint64() {
        return ((bitField0_ & 0x00000020) != 0);
      }

      /**
       * <code>optional sint64 sint64 = 6;</code>
       * 
       * @return The sint64.
       */
      @java.lang.Override
      public long getSint64() {
        return sint64_;
      }

      /**
       * <code>optional sint64 sint64 = 6;</code>
       * 
       * @param value The sint64 to set.
       * @return This builder for chaining.
       */
      public Builder setSint64(long value) {

        sint64_ = value;
        bitField0_ |= 0x00000020;
        onChanged();
        return this;
      }

      /**
       * <code>optional sint64 sint64 = 6;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearSint64() {
        bitField0_ = (bitField0_ & ~0x00000020);
        sint64_ = 0L;
        onChanged();
        return this;
      }

      private int fixed32_;

      /**
       * <code>optional fixed32 fixed32 = 7;</code>
       * 
       * @return Whether the fixed32 field is set.
       */
      @java.lang.Override
      public boolean hasFixed32() {
        return ((bitField0_ & 0x00000040) != 0);
      }

      /**
       * <code>optional fixed32 fixed32 = 7;</code>
       * 
       * @return The fixed32.
       */
      @java.lang.Override
      public int getFixed32() {
        return fixed32_;
      }

      /**
       * <code>optional fixed32 fixed32 = 7;</code>
       * 
       * @param value The fixed32 to set.
       * @return This builder for chaining.
       */
      public Builder setFixed32(int value) {

        fixed32_ = value;
        bitField0_ |= 0x00000040;
        onChanged();
        return this;
      }

      /**
       * <code>optional fixed32 fixed32 = 7;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearFixed32() {
        bitField0_ = (bitField0_ & ~0x00000040);
        fixed32_ = 0;
        onChanged();
        return this;
      }

      private long fixed64_;

      /**
       * <code>optional fixed64 fixed64 = 8;</code>
       * 
       * @return Whether the fixed64 field is set.
       */
      @java.lang.Override
      public boolean hasFixed64() {
        return ((bitField0_ & 0x00000080) != 0);
      }

      /**
       * <code>optional fixed64 fixed64 = 8;</code>
       * 
       * @return The fixed64.
       */
      @java.lang.Override
      public long getFixed64() {
        return fixed64_;
      }

      /**
       * <code>optional fixed64 fixed64 = 8;</code>
       * 
       * @param value The fixed64 to set.
       * @return This builder for chaining.
       */
      public Builder setFixed64(long value) {

        fixed64_ = value;
        bitField0_ |= 0x00000080;
        onChanged();
        return this;
      }

      /**
       * <code>optional fixed64 fixed64 = 8;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearFixed64() {
        bitField0_ = (bitField0_ & ~0x00000080);
        fixed64_ = 0L;
        onChanged();
        return this;
      }

      private int sfixed32_;

      /**
       * <code>optional sfixed32 sfixed32 = 9;</code>
       * 
       * @return Whether the sfixed32 field is set.
       */
      @java.lang.Override
      public boolean hasSfixed32() {
        return ((bitField0_ & 0x00000100) != 0);
      }

      /**
       * <code>optional sfixed32 sfixed32 = 9;</code>
       * 
       * @return The sfixed32.
       */
      @java.lang.Override
      public int getSfixed32() {
        return sfixed32_;
      }

      /**
       * <code>optional sfixed32 sfixed32 = 9;</code>
       * 
       * @param value The sfixed32 to set.
       * @return This builder for chaining.
       */
      public Builder setSfixed32(int value) {

        sfixed32_ = value;
        bitField0_ |= 0x00000100;
        onChanged();
        return this;
      }

      /**
       * <code>optional sfixed32 sfixed32 = 9;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearSfixed32() {
        bitField0_ = (bitField0_ & ~0x00000100);
        sfixed32_ = 0;
        onChanged();
        return this;
      }

      private long sfixed64_;

      /**
       * <code>optional sfixed64 sfixed64 = 10;</code>
       * 
       * @return Whether the sfixed64 field is set.
       */
      @java.lang.Override
      public boolean hasSfixed64() {
        return ((bitField0_ & 0x00000200) != 0);
      }

      /**
       * <code>optional sfixed64 sfixed64 = 10;</code>
       * 
       * @return The sfixed64.
       */
      @java.lang.Override
      public long getSfixed64() {
        return sfixed64_;
      }

      /**
       * <code>optional sfixed64 sfixed64 = 10;</code>
       * 
       * @param value The sfixed64 to set.
       * @return This builder for chaining.
       */
      public Builder setSfixed64(long value) {

        sfixed64_ = value;
        bitField0_ |= 0x00000200;
        onChanged();
        return this;
      }

      /**
       * <code>optional sfixed64 sfixed64 = 10;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearSfixed64() {
        bitField0_ = (bitField0_ & ~0x00000200);
        sfixed64_ = 0L;
        onChanged();
        return this;
      }

      private float float_;

      /**
       * <code>optional float float = 11;</code>
       * 
       * @return Whether the float field is set.
       */
      @java.lang.Override
      public boolean hasFloat() {
        return ((bitField0_ & 0x00000400) != 0);
      }

      /**
       * <code>optional float float = 11;</code>
       * 
       * @return The float.
       */
      @java.lang.Override
      public float getFloat() {
        return float_;
      }

      /**
       * <code>optional float float = 11;</code>
       * 
       * @param value The float to set.
       * @return This builder for chaining.
       */
      public Builder setFloat(float value) {

        float_ = value;
        bitField0_ |= 0x00000400;
        onChanged();
        return this;
      }

      /**
       * <code>optional float float = 11;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearFloat() {
        bitField0_ = (bitField0_ & ~0x00000400);
        float_ = 0F;
        onChanged();
        return this;
      }

      private double double_;

      /**
       * <code>optional double double = 12;</code>
       * 
       * @return Whether the double field is set.
       */
      @java.lang.Override
      public boolean hasDouble() {
        return ((bitField0_ & 0x00000800) != 0);
      }

      /**
       * <code>optional double double = 12;</code>
       * 
       * @return The double.
       */
      @java.lang.Override
      public double getDouble() {
        return double_;
      }

      /**
       * <code>optional double double = 12;</code>
       * 
       * @param value The double to set.
       * @return This builder for chaining.
       */
      public Builder setDouble(double value) {

        double_ = value;
        bitField0_ |= 0x00000800;
        onChanged();
        return this;
      }

      /**
       * <code>optional double double = 12;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearDouble() {
        bitField0_ = (bitField0_ & ~0x00000800);
        double_ = 0D;
        onChanged();
        return this;
      }

      private boolean bool_;

      /**
       * <code>optional bool bool = 13;</code>
       * 
       * @return Whether the bool field is set.
       */
      @java.lang.Override
      public boolean hasBool() {
        return ((bitField0_ & 0x00001000) != 0);
      }

      /**
       * <code>optional bool bool = 13;</code>
       * 
       * @return The bool.
       */
      @java.lang.Override
      public boolean getBool() {
        return bool_;
      }

      /**
       * <code>optional bool bool = 13;</code>
       * 
       * @param value The bool to set.
       * @return This builder for chaining.
       */
      public Builder setBool(boolean value) {

        bool_ = value;
        bitField0_ |= 0x00001000;
        onChanged();
        return this;
      }

      /**
       * <code>optional bool bool = 13;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearBool() {
        bitField0_ = (bitField0_ & ~0x00001000);
        bool_ = false;
        onChanged();
        return this;
      }

      private java.lang.Object string_ = "";

      /**
       * <code>optional string string = 14;</code>
       * 
       * @return Whether the string field is set.
       */
      public boolean hasString() {
        return ((bitField0_ & 0x00002000) != 0);
      }

      /**
       * <code>optional string string = 14;</code>
       * 
       * @return The string.
       */
      public java.lang.String getString() {
        java.lang.Object ref = string_;
        if (!(ref instanceof java.lang.String)) {
          com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
          java.lang.String s = bs.toStringUtf8();
          if (bs.isValidUtf8()) {
            string_ = s;
          }
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }

      /**
       * <code>optional string string = 14;</code>
       * 
       * @return The bytes for string.
       */
      public com.google.protobuf.ByteString getStringBytes() {
        java.lang.Object ref = string_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
          string_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }

      /**
       * <code>optional string string = 14;</code>
       * 
       * @param value The string to set.
       * @return This builder for chaining.
       */
      public Builder setString(java.lang.String value) {
        if (value == null) {
          throw new NullPointerException();
        }
        string_ = value;
        bitField0_ |= 0x00002000;
        onChanged();
        return this;
      }

      /**
       * <code>optional string string = 14;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearString() {
        string_ = getDefaultInstance().getString();
        bitField0_ = (bitField0_ & ~0x00002000);
        onChanged();
        return this;
      }

      /**
       * <code>optional string string = 14;</code>
       * 
       * @param value The bytes for string to set.
       * @return This builder for chaining.
       */
      public Builder setStringBytes(com.google.protobuf.ByteString value) {
        if (value == null) {
          throw new NullPointerException();
        }
        string_ = value;
        bitField0_ |= 0x00002000;
        onChanged();
        return this;
      }

      private com.google.protobuf.ByteString bytes_ = com.google.protobuf.ByteString.EMPTY;

      /**
       * <code>optional bytes bytes = 15;</code>
       * 
       * @return Whether the bytes field is set.
       */
      @java.lang.Override
      public boolean hasBytes() {
        return ((bitField0_ & 0x00004000) != 0);
      }

      /**
       * <code>optional bytes bytes = 15;</code>
       * 
       * @return The bytes.
       */
      @java.lang.Override
      public com.google.protobuf.ByteString getBytes() {
        return bytes_;
      }

      /**
       * <code>optional bytes bytes = 15;</code>
       * 
       * @param value The bytes to set.
       * @return This builder for chaining.
       */
      public Builder setBytes(com.google.protobuf.ByteString value) {
        if (value == null) {
          throw new NullPointerException();
        }
        bytes_ = value;
        bitField0_ |= 0x00004000;
        onChanged();
        return this;
      }

      /**
       * <code>optional bytes bytes = 15;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearBytes() {
        bitField0_ = (bitField0_ & ~0x00004000);
        bytes_ = getDefaultInstance().getBytes();
        onChanged();
        return this;
      }

      private int enum_ = 3;

      /**
       * <code>optional .org.apache.avro.protobuf.noopt.A enum = 16 [default = Z];</code>
       * 
       * @return Whether the enum field is set.
       */
      @java.lang.Override
      public boolean hasEnum() {
        return ((bitField0_ & 0x00008000) != 0);
      }

      /**
       * <code>optional .org.apache.avro.protobuf.noopt.A enum = 16 [default = Z];</code>
       * 
       * @return The enum.
       */
      @java.lang.Override
      public org.apache.avro.protobuf.noopt.Test.A getEnum() {
        org.apache.avro.protobuf.noopt.Test.A result = org.apache.avro.protobuf.noopt.Test.A.forNumber(enum_);
        return result == null ? org.apache.avro.protobuf.noopt.Test.A.Z : result;
      }

      /**
       * <code>optional .org.apache.avro.protobuf.noopt.A enum = 16 [default = Z];</code>
       * 
       * @param value The enum to set.
       * @return This builder for chaining.
       */
      public Builder setEnum(org.apache.avro.protobuf.noopt.Test.A value) {
        if (value == null) {
          throw new NullPointerException();
        }
        bitField0_ |= 0x00008000;
        enum_ = value.getNumber();
        onChanged();
        return this;
      }

      /**
       * <code>optional .org.apache.avro.protobuf.noopt.A enum = 16 [default = Z];</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearEnum() {
        bitField0_ = (bitField0_ & ~0x00008000);
        enum_ = 3;
        onChanged();
        return this;
      }

      private com.google.protobuf.Internal.IntList intArray_ = emptyIntList();

      private void ensureIntArrayIsMutable() {
        if (!intArray_.isModifiable()) {
          intArray_ = makeMutableCopy(intArray_);
        }
        bitField0_ |= 0x00010000;
      }

      /**
       * <pre>
       * some repeated types
       * </pre>
       *
       * <code>repeated int32 intArray = 17;</code>
       * 
       * @return A list containing the intArray.
       */
      public java.util.List<java.lang.Integer> getIntArrayList() {
        intArray_.makeImmutable();
        return intArray_;
      }

      /**
       * <pre>
       * some repeated types
       * </pre>
       *
       * <code>repeated int32 intArray = 17;</code>
       * 
       * @return The count of intArray.
       */
      public int getIntArrayCount() {
        return intArray_.size();
      }

      /**
       * <pre>
       * some repeated types
       * </pre>
       *
       * <code>repeated int32 intArray = 17;</code>
       * 
       * @param index The index of the element to return.
       * @return The intArray at the given index.
       */
      public int getIntArray(int index) {
        return intArray_.getInt(index);
      }

      /**
       * <pre>
       * some repeated types
       * </pre>
       *
       * <code>repeated int32 intArray = 17;</code>
       * 
       * @param index The index to set the value at.
       * @param value The intArray to set.
       * @return This builder for chaining.
       */
      public Builder setIntArray(int index, int value) {

        ensureIntArrayIsMutable();
        intArray_.setInt(index, value);
        bitField0_ |= 0x00010000;
        onChanged();
        return this;
      }

      /**
       * <pre>
       * some repeated types
       * </pre>
       *
       * <code>repeated int32 intArray = 17;</code>
       * 
       * @param value The intArray to add.
       * @return This builder for chaining.
       */
      public Builder addIntArray(int value) {

        ensureIntArrayIsMutable();
        intArray_.addInt(value);
        bitField0_ |= 0x00010000;
        onChanged();
        return this;
      }

      /**
       * <pre>
       * some repeated types
       * </pre>
       *
       * <code>repeated int32 intArray = 17;</code>
       * 
       * @param values The intArray to add.
       * @return This builder for chaining.
       */
      public Builder addAllIntArray(java.lang.Iterable<? extends java.lang.Integer> values) {
        ensureIntArrayIsMutable();
        com.google.protobuf.AbstractMessageLite.Builder.addAll(values, intArray_);
        bitField0_ |= 0x00010000;
        onChanged();
        return this;
      }

      /**
       * <pre>
       * some repeated types
       * </pre>
       *
       * <code>repeated int32 intArray = 17;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearIntArray() {
        intArray_ = emptyIntList();
        bitField0_ = (bitField0_ & ~0x00010000);
        onChanged();
        return this;
      }

      private java.util.List<org.apache.avro.protobuf.noopt.Test.Foo> fooArray_ = java.util.Collections.emptyList();

      private void ensureFooArrayIsMutable() {
        if (!((bitField0_ & 0x00020000) != 0)) {
          fooArray_ = new java.util.ArrayList<org.apache.avro.protobuf.noopt.Test.Foo>(fooArray_);
          bitField0_ |= 0x00020000;
        }
      }

      private com.google.protobuf.RepeatedFieldBuilder<org.apache.avro.protobuf.noopt.Test.Foo, org.apache.avro.protobuf.noopt.Test.Foo.Builder, org.apache.avro.protobuf.noopt.Test.FooOrBuilder> fooArrayBuilder_;

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public java.util.List<org.apache.avro.protobuf.noopt.Test.Foo> getFooArrayList() {
        if (fooArrayBuilder_ == null) {
          return java.util.Collections.unmodifiableList(fooArray_);
        } else {
          return fooArrayBuilder_.getMessageList();
        }
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public int getFooArrayCount() {
        if (fooArrayBuilder_ == null) {
          return fooArray_.size();
        } else {
          return fooArrayBuilder_.getCount();
        }
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public org.apache.avro.protobuf.noopt.Test.Foo getFooArray(int index) {
        if (fooArrayBuilder_ == null) {
          return fooArray_.get(index);
        } else {
          return fooArrayBuilder_.getMessage(index);
        }
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public Builder setFooArray(int index, org.apache.avro.protobuf.noopt.Test.Foo value) {
        if (fooArrayBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          ensureFooArrayIsMutable();
          fooArray_.set(index, value);
          onChanged();
        } else {
          fooArrayBuilder_.setMessage(index, value);
        }
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public Builder setFooArray(int index, org.apache.avro.protobuf.noopt.Test.Foo.Builder builderForValue) {
        if (fooArrayBuilder_ == null) {
          ensureFooArrayIsMutable();
          fooArray_.set(index, builderForValue.build());
          onChanged();
        } else {
          fooArrayBuilder_.setMessage(index, builderForValue.build());
        }
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public Builder addFooArray(org.apache.avro.protobuf.noopt.Test.Foo value) {
        if (fooArrayBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          ensureFooArrayIsMutable();
          fooArray_.add(value);
          onChanged();
        } else {
          fooArrayBuilder_.addMessage(value);
        }
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public Builder addFooArray(int index, org.apache.avro.protobuf.noopt.Test.Foo value) {
        if (fooArrayBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          ensureFooArrayIsMutable();
          fooArray_.add(index, value);
          onChanged();
        } else {
          fooArrayBuilder_.addMessage(index, value);
        }
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public Builder addFooArray(org.apache.avro.protobuf.noopt.Test.Foo.Builder builderForValue) {
        if (fooArrayBuilder_ == null) {
          ensureFooArrayIsMutable();
          fooArray_.add(builderForValue.build());
          onChanged();
        } else {
          fooArrayBuilder_.addMessage(builderForValue.build());
        }
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public Builder addFooArray(int index, org.apache.avro.protobuf.noopt.Test.Foo.Builder builderForValue) {
        if (fooArrayBuilder_ == null) {
          ensureFooArrayIsMutable();
          fooArray_.add(index, builderForValue.build());
          onChanged();
        } else {
          fooArrayBuilder_.addMessage(index, builderForValue.build());
        }
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public Builder addAllFooArray(java.lang.Iterable<? extends org.apache.avro.protobuf.noopt.Test.Foo> values) {
        if (fooArrayBuilder_ == null) {
          ensureFooArrayIsMutable();
          com.google.protobuf.AbstractMessageLite.Builder.addAll(values, fooArray_);
          onChanged();
        } else {
          fooArrayBuilder_.addAllMessages(values);
        }
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public Builder clearFooArray() {
        if (fooArrayBuilder_ == null) {
          fooArray_ = java.util.Collections.emptyList();
          bitField0_ = (bitField0_ & ~0x00020000);
          onChanged();
        } else {
          fooArrayBuilder_.clear();
        }
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public Builder removeFooArray(int index) {
        if (fooArrayBuilder_ == null) {
          ensureFooArrayIsMutable();
          fooArray_.remove(index);
          onChanged();
        } else {
          fooArrayBuilder_.remove(index);
        }
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public org.apache.avro.protobuf.noopt.Test.Foo.Builder getFooArrayBuilder(int index) {
        return getFooArrayFieldBuilder().getBuilder(index);
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public org.apache.avro.protobuf.noopt.Test.FooOrBuilder getFooArrayOrBuilder(int index) {
        if (fooArrayBuilder_ == null) {
          return fooArray_.get(index);
        } else {
          return fooArrayBuilder_.getMessageOrBuilder(index);
        }
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public java.util.List<? extends org.apache.avro.protobuf.noopt.Test.FooOrBuilder> getFooArrayOrBuilderList() {
        if (fooArrayBuilder_ != null) {
          return fooArrayBuilder_.getMessageOrBuilderList();
        } else {
          return java.util.Collections.unmodifiableList(fooArray_);
        }
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public org.apache.avro.protobuf.noopt.Test.Foo.Builder addFooArrayBuilder() {
        return getFooArrayFieldBuilder().addBuilder(org.apache.avro.protobuf.noopt.Test.Foo.getDefaultInstance());
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public org.apache.avro.protobuf.noopt.Test.Foo.Builder addFooArrayBuilder(int index) {
        return getFooArrayFieldBuilder().addBuilder(index,
            org.apache.avro.protobuf.noopt.Test.Foo.getDefaultInstance());
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.Foo fooArray = 20;</code>
       */
      public java.util.List<org.apache.avro.protobuf.noopt.Test.Foo.Builder> getFooArrayBuilderList() {
        return getFooArrayFieldBuilder().getBuilderList();
      }

      private com.google.protobuf.RepeatedFieldBuilder<org.apache.avro.protobuf.noopt.Test.Foo, org.apache.avro.protobuf.noopt.Test.Foo.Builder, org.apache.avro.protobuf.noopt.Test.FooOrBuilder> getFooArrayFieldBuilder() {
        if (fooArrayBuilder_ == null) {
          fooArrayBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<org.apache.avro.protobuf.noopt.Test.Foo, org.apache.avro.protobuf.noopt.Test.Foo.Builder, org.apache.avro.protobuf.noopt.Test.FooOrBuilder>(
              fooArray_, ((bitField0_ & 0x00020000) != 0), getParentForChildren(), isClean());
          fooArray_ = null;
        }
        return fooArrayBuilder_;
      }

      private java.util.List<java.lang.Integer> syms_ = java.util.Collections.emptyList();

      private void ensureSymsIsMutable() {
        if (!((bitField0_ & 0x00040000) != 0)) {
          syms_ = new java.util.ArrayList<java.lang.Integer>(syms_);
          bitField0_ |= 0x00040000;
        }
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
       * 
       * @return A list containing the syms.
       */
      public java.util.List<org.apache.avro.protobuf.noopt.Test.A> getSymsList() {
        return new com.google.protobuf.Internal.ListAdapter<java.lang.Integer, org.apache.avro.protobuf.noopt.Test.A>(
            syms_, syms_converter_);
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
       * 
       * @return The count of syms.
       */
      public int getSymsCount() {
        return syms_.size();
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
       * 
       * @param index The index of the element to return.
       * @return The syms at the given index.
       */
      public org.apache.avro.protobuf.noopt.Test.A getSyms(int index) {
        return syms_converter_.convert(syms_.get(index));
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
       * 
       * @param index The index to set the value at.
       * @param value The syms to set.
       * @return This builder for chaining.
       */
      public Builder setSyms(int index, org.apache.avro.protobuf.noopt.Test.A value) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensureSymsIsMutable();
        syms_.set(index, value.getNumber());
        onChanged();
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
       * 
       * @param value The syms to add.
       * @return This builder for chaining.
       */
      public Builder addSyms(org.apache.avro.protobuf.noopt.Test.A value) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensureSymsIsMutable();
        syms_.add(value.getNumber());
        onChanged();
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
       * 
       * @param values The syms to add.
       * @return This builder for chaining.
       */
      public Builder addAllSyms(java.lang.Iterable<? extends org.apache.avro.protobuf.noopt.Test.A> values) {
        ensureSymsIsMutable();
        for (org.apache.avro.protobuf.noopt.Test.A value : values) {
          syms_.add(value.getNumber());
        }
        onChanged();
        return this;
      }

      /**
       * <code>repeated .org.apache.avro.protobuf.noopt.A syms = 19;</code>
       * 
       * @return This builder for chaining.
       */
      public Builder clearSyms() {
        syms_ = java.util.Collections.emptyList();
        bitField0_ = (bitField0_ & ~0x00040000);
        onChanged();
        return this;
      }

      private org.apache.avro.protobuf.noopt.Test.Foo foo_;
      private com.google.protobuf.SingleFieldBuilder<org.apache.avro.protobuf.noopt.Test.Foo, org.apache.avro.protobuf.noopt.Test.Foo.Builder, org.apache.avro.protobuf.noopt.Test.FooOrBuilder> fooBuilder_;

      /**
       * <pre>
       * a recursive type
       * </pre>
       *
       * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
       * 
       * @return Whether the foo field is set.
       */
      public boolean hasFoo() {
        return ((bitField0_ & 0x00080000) != 0);
      }

      /**
       * <pre>
       * a recursive type
       * </pre>
       *
       * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
       * 
       * @return The foo.
       */
      public org.apache.avro.protobuf.noopt.Test.Foo getFoo() {
        if (fooBuilder_ == null) {
          return foo_ == null ? org.apache.avro.protobuf.noopt.Test.Foo.getDefaultInstance() : foo_;
        } else {
          return fooBuilder_.getMessage();
        }
      }

      /**
       * <pre>
       * a recursive type
       * </pre>
       *
       * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
       */
      public Builder setFoo(org.apache.avro.protobuf.noopt.Test.Foo value) {
        if (fooBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          foo_ = value;
        } else {
          fooBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00080000;
        onChanged();
        return this;
      }

      /**
       * <pre>
       * a recursive type
       * </pre>
       *
       * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
       */
      public Builder setFoo(org.apache.avro.protobuf.noopt.Test.Foo.Builder builderForValue) {
        if (fooBuilder_ == null) {
          foo_ = builderForValue.build();
        } else {
          fooBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00080000;
        onChanged();
        return this;
      }

      /**
       * <pre>
       * a recursive type
       * </pre>
       *
       * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
       */
      public Builder mergeFoo(org.apache.avro.protobuf.noopt.Test.Foo value) {
        if (fooBuilder_ == null) {
          if (((bitField0_ & 0x00080000) != 0) && foo_ != null
              && foo_ != org.apache.avro.protobuf.noopt.Test.Foo.getDefaultInstance()) {
            getFooBuilder().mergeFrom(value);
          } else {
            foo_ = value;
          }
        } else {
          fooBuilder_.mergeFrom(value);
        }
        if (foo_ != null) {
          bitField0_ |= 0x00080000;
          onChanged();
        }
        return this;
      }

      /**
       * <pre>
       * a recursive type
       * </pre>
       *
       * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
       */
      public Builder clearFoo() {
        bitField0_ = (bitField0_ & ~0x00080000);
        foo_ = null;
        if (fooBuilder_ != null) {
          fooBuilder_.dispose();
          fooBuilder_ = null;
        }
        onChanged();
        return this;
      }

      /**
       * <pre>
       * a recursive type
       * </pre>
       *
       * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
       */
      public org.apache.avro.protobuf.noopt.Test.Foo.Builder getFooBuilder() {
        bitField0_ |= 0x00080000;
        onChanged();
        return getFooFieldBuilder().getBuilder();
      }

      /**
       * <pre>
       * a recursive type
       * </pre>
       *
       * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
       */
      public org.apache.avro.protobuf.noopt.Test.FooOrBuilder getFooOrBuilder() {
        if (fooBuilder_ != null) {
          return fooBuilder_.getMessageOrBuilder();
        } else {
          return foo_ == null ? org.apache.avro.protobuf.noopt.Test.Foo.getDefaultInstance() : foo_;
        }
      }

      /**
       * <pre>
       * a recursive type
       * </pre>
       *
       * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
       */
      private com.google.protobuf.SingleFieldBuilder<org.apache.avro.protobuf.noopt.Test.Foo, org.apache.avro.protobuf.noopt.Test.Foo.Builder, org.apache.avro.protobuf.noopt.Test.FooOrBuilder> getFooFieldBuilder() {
        if (fooBuilder_ == null) {
          fooBuilder_ = new com.google.protobuf.SingleFieldBuilder<org.apache.avro.protobuf.noopt.Test.Foo, org.apache.avro.protobuf.noopt.Test.Foo.Builder, org.apache.avro.protobuf.noopt.Test.FooOrBuilder>(
              getFoo(), getParentForChildren(), isClean());
          foo_ = null;
        }
        return fooBuilder_;
      }

      private com.google.protobuf.Timestamp timestamp_;
      private com.google.protobuf.SingleFieldBuilder<com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> timestampBuilder_;

      /**
       * <pre>
       * a predefined message type
       * </pre>
       *
       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
       * 
       * @return Whether the timestamp field is set.
       */
      public boolean hasTimestamp() {
        return ((bitField0_ & 0x00100000) != 0);
      }

      /**
       * <pre>
       * a predefined message type
       * </pre>
       *
       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
       * 
       * @return The timestamp.
       */
      public com.google.protobuf.Timestamp getTimestamp() {
        if (timestampBuilder_ == null) {
          return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
        } else {
          return timestampBuilder_.getMessage();
        }
      }

      /**
       * <pre>
       * a predefined message type
       * </pre>
       *
       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
       */
      public Builder setTimestamp(com.google.protobuf.Timestamp value) {
        if (timestampBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          timestamp_ = value;
        } else {
          timestampBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00100000;
        onChanged();
        return this;
      }

      /**
       * <pre>
       * a predefined message type
       * </pre>
       *
       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
       */
      public Builder setTimestamp(com.google.protobuf.Timestamp.Builder builderForValue) {
        if (timestampBuilder_ == null) {
          timestamp_ = builderForValue.build();
        } else {
          timestampBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00100000;
        onChanged();
        return this;
      }

      /**
       * <pre>
       * a predefined message type
       * </pre>
       *
       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
       */
      public Builder mergeTimestamp(com.google.protobuf.Timestamp value) {
        if (timestampBuilder_ == null) {
          if (((bitField0_ & 0x00100000) != 0) && timestamp_ != null
              && timestamp_ != com.google.protobuf.Timestamp.getDefaultInstance()) {
            getTimestampBuilder().mergeFrom(value);
          } else {
            timestamp_ = value;
          }
        } else {
          timestampBuilder_.mergeFrom(value);
        }
        if (timestamp_ != null) {
          bitField0_ |= 0x00100000;
          onChanged();
        }
        return this;
      }

      /**
       * <pre>
       * a predefined message type
       * </pre>
       *
       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
       */
      public Builder clearTimestamp() {
        bitField0_ = (bitField0_ & ~0x00100000);
        timestamp_ = null;
        if (timestampBuilder_ != null) {
          timestampBuilder_.dispose();
          timestampBuilder_ = null;
        }
        onChanged();
        return this;
      }

      /**
       * <pre>
       * a predefined message type
       * </pre>
       *
       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
       */
      public com.google.protobuf.Timestamp.Builder getTimestampBuilder() {
        bitField0_ |= 0x00100000;
        onChanged();
        return getTimestampFieldBuilder().getBuilder();
      }

      /**
       * <pre>
       * a predefined message type
       * </pre>
       *
       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
       */
      public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() {
        if (timestampBuilder_ != null) {
          return timestampBuilder_.getMessageOrBuilder();
        } else {
          return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
        }
      }

      /**
       * <pre>
       * a predefined message type
       * </pre>
       *
       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
       */
      private com.google.protobuf.SingleFieldBuilder<com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> getTimestampFieldBuilder() {
        if (timestampBuilder_ == null) {
          timestampBuilder_ = new com.google.protobuf.SingleFieldBuilder<com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>(
              getTimestamp(), getParentForChildren(), isClean());
          timestamp_ = null;
        }
        return timestampBuilder_;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.avro.protobuf.noopt.Foo)
    }

    // @@protoc_insertion_point(class_scope:org.apache.avro.protobuf.noopt.Foo)
    private static final org.apache.avro.protobuf.noopt.Test.Foo DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.avro.protobuf.noopt.Test.Foo();
    }

    public static org.apache.avro.protobuf.noopt.Test.Foo getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

    private static final com.google.protobuf.Parser<Foo> PARSER = new com.google.protobuf.AbstractParser<Foo>() {
      @java.lang.Override
      public Foo parsePartialFrom(com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        Builder builder = newBuilder();
        try {
          builder.mergeFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.setUnfinishedMessage(builder.buildPartial());
        } catch (com.google.protobuf.UninitializedMessageException e) {
          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
        } catch (java.io.IOException e) {
          throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(builder.buildPartial());
        }
        return builder.buildPartial();
      }
    };

    public static com.google.protobuf.Parser<Foo> parser() {
      return PARSER;
    }

    @java.lang.Override
    public com.google.protobuf.Parser<Foo> getParserForType() {
      return PARSER;
    }

    @java.lang.Override
    public org.apache.avro.protobuf.noopt.Test.Foo getDefaultInstanceForType() {
      return DEFAULT_INSTANCE;
    }

  }

  public interface MOrBuilder extends
      // @@protoc_insertion_point(interface_extends:org.apache.avro.protobuf.noopt.M)
      com.google.protobuf.MessageOrBuilder {
  }

  /**
   * <pre>
   * a nested enum
   * </pre>
   *
   * Protobuf type {@code org.apache.avro.protobuf.noopt.M}
   */
  public static final class M extends com.google.protobuf.GeneratedMessage implements
      // @@protoc_insertion_point(message_implements:org.apache.avro.protobuf.noopt.M)
      MOrBuilder {
    private static final long serialVersionUID = 0L;
    static {
      com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
          com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 26, /* patch= */ 1,
          /* suffix= */ "", M.class.getName());
    }

    // Use M.newBuilder() to construct.
    private M(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
    }

    private M() {
    }

    public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
      return org.apache.avro.protobuf.noopt.Test.internal_static_org_apache_avro_protobuf_noopt_M_descriptor;
    }

    @java.lang.Override
    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() {
      return org.apache.avro.protobuf.noopt.Test.internal_static_org_apache_avro_protobuf_noopt_M_fieldAccessorTable
          .ensureFieldAccessorsInitialized(org.apache.avro.protobuf.noopt.Test.M.class,
              org.apache.avro.protobuf.noopt.Test.M.Builder.class);
    }

    /**
     * Protobuf enum {@code org.apache.avro.protobuf.noopt.M.N}
     */
    public enum N implements com.google.protobuf.ProtocolMessageEnum {
      /**
       * <code>A = 1;</code>
       */
      A(1),;

      static {
        com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
            com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 26, /* patch= */ 1,
            /* suffix= */ "", N.class.getName());
      }
      /**
       * <code>A = 1;</code>
       */
      public static final int A_VALUE = 1;

      public final int getNumber() {
        return value;
      }

      /**
       * @param value The numeric wire value of the corresponding enum entry.
       * @return The enum associated with the given numeric wire value.
       * @deprecated Use {@link #forNumber(int)} instead.
       */
      @java.lang.Deprecated
      public static N valueOf(int value) {
        return forNumber(value);
      }

      /**
       * @param value The numeric wire value of the corresponding enum entry.
       * @return The enum associated with the given numeric wire value.
       */
      public static N forNumber(int value) {
        switch (value) {
        case 1:
          return A;
        default:
          return null;
        }
      }

      public static com.google.protobuf.Internal.EnumLiteMap<N> internalGetValueMap() {
        return internalValueMap;
      }

      private static final com.google.protobuf.Internal.EnumLiteMap<N> internalValueMap = new com.google.protobuf.Internal.EnumLiteMap<N>() {
        public N findValueByNumber(int number) {
          return N.forNumber(number);
        }
      };

      public final com.google.protobuf.Descriptors.EnumValueDescriptor getValueDescriptor() {
        return getDescriptor().getValues().get(ordinal());
      }

      public final com.google.protobuf.Descriptors.EnumDescriptor getDescriptorForType() {
        return getDescriptor();
      }

      public static final com.google.protobuf.Descriptors.EnumDescriptor getDescriptor() {
        return org.apache.avro.protobuf.noopt.Test.M.getDescriptor().getEnumTypes().get(0);
      }

      private static final N[] VALUES = values();

      public static N valueOf(com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
        if (desc.getType() != getDescriptor()) {
          throw new java.lang.IllegalArgumentException("EnumValueDescriptor is not for this type.");
        }
        return VALUES[desc.getIndex()];
      }

      private final int value;

      private N(int value) {
        this.value = value;
      }

      // @@protoc_insertion_point(enum_scope:org.apache.avro.protobuf.noopt.M.N)
    }

    private byte memoizedIsInitialized = -1;

    @java.lang.Override
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized == 1)
        return true;
      if (isInitialized == 0)
        return false;

      memoizedIsInitialized = 1;
      return true;
    }

    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
      getUnknownFields().writeTo(output);
    }

    @java.lang.Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1)
        return size;

      size = 0;
      size += getUnknownFields().getSerializedSize();
      memoizedSize = size;
      return size;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
        return true;
      }
      if (!(obj instanceof org.apache.avro.protobuf.noopt.Test.M)) {
        return super.equals(obj);
      }
      org.apache.avro.protobuf.noopt.Test.M other = (org.apache.avro.protobuf.noopt.Test.M) obj;

      if (!getUnknownFields().equals(other.getUnknownFields()))
        return false;
      return true;
    }

    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptor().hashCode();
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseFrom(java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseFrom(java.nio.ByteBuffer data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseFrom(com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseFrom(com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseFrom(byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseFrom(java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseDelimitedFrom(java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseFrom(com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);
    }

    public static org.apache.avro.protobuf.noopt.Test.M parseFrom(com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
      return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);
    }

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

    public static Builder newBuilder() {
      return DEFAULT_INSTANCE.toBuilder();
    }

    public static Builder newBuilder(org.apache.avro.protobuf.noopt.Test.M prototype) {
      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }

    @java.lang.Override
    public Builder toBuilder() {
      return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
    }

    @java.lang.Override
    protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }

    /**
     * <pre>
     * a nested enum
     * </pre>
     *
     * Protobuf type {@code org.apache.avro.protobuf.noopt.M}
     */
    public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:org.apache.avro.protobuf.noopt.M)
        org.apache.avro.protobuf.noopt.Test.MOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
        return org.apache.avro.protobuf.noopt.Test.internal_static_org_apache_avro_protobuf_noopt_M_descriptor;
      }

      @java.lang.Override
      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() {
        return org.apache.avro.protobuf.noopt.Test.internal_static_org_apache_avro_protobuf_noopt_M_fieldAccessorTable
            .ensureFieldAccessorsInitialized(org.apache.avro.protobuf.noopt.Test.M.class,
                org.apache.avro.protobuf.noopt.Test.M.Builder.class);
      }

      // Construct using org.apache.avro.protobuf.noopt.Test.M.newBuilder()
      private Builder() {

      }

      private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);

      }

      @java.lang.Override
      public Builder clear() {
        super.clear();
        return this;
      }

      @java.lang.Override
      public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
        return org.apache.avro.protobuf.noopt.Test.internal_static_org_apache_avro_protobuf_noopt_M_descriptor;
      }

      @java.lang.Override
      public org.apache.avro.protobuf.noopt.Test.M getDefaultInstanceForType() {
        return org.apache.avro.protobuf.noopt.Test.M.getDefaultInstance();
      }

      @java.lang.Override
      public org.apache.avro.protobuf.noopt.Test.M build() {
        org.apache.avro.protobuf.noopt.Test.M result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      @java.lang.Override
      public org.apache.avro.protobuf.noopt.Test.M buildPartial() {
        org.apache.avro.protobuf.noopt.Test.M result = new org.apache.avro.protobuf.noopt.Test.M(this);
        onBuilt();
        return result;
      }

      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.avro.protobuf.noopt.Test.M) {
          return mergeFrom((org.apache.avro.protobuf.noopt.Test.M) other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.avro.protobuf.noopt.Test.M other) {
        if (other == org.apache.avro.protobuf.noopt.Test.M.getDefaultInstance())
          return this;
        this.mergeUnknownFields(other.getUnknownFields());
        onChanged();
        return this;
      }

      @java.lang.Override
      public final boolean isInitialized() {
        return true;
      }

      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
        if (extensionRegistry == null) {
          throw new java.lang.NullPointerException();
        }
        try {
          boolean done = false;
          while (!done) {
            int tag = input.readTag();
            switch (tag) {
            case 0:
              done = true;
              break;
            default: {
              if (!super.parseUnknownField(input, extensionRegistry, tag)) {
                done = true; // was an endgroup tag
              }
              break;
            } // default:
            } // switch (tag)
          } // while (!done)
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.unwrapIOException();
        } finally {
          onChanged();
        } // finally
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.avro.protobuf.noopt.M)
    }

    // @@protoc_insertion_point(class_scope:org.apache.avro.protobuf.noopt.M)
    private static final org.apache.avro.protobuf.noopt.Test.M DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.avro.protobuf.noopt.Test.M();
    }

    public static org.apache.avro.protobuf.noopt.Test.M getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

    private static final com.google.protobuf.Parser<M> PARSER = new com.google.protobuf.AbstractParser<M>() {
      @java.lang.Override
      public M parsePartialFrom(com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        Builder builder = newBuilder();
        try {
          builder.mergeFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.setUnfinishedMessage(builder.buildPartial());
        } catch (com.google.protobuf.UninitializedMessageException e) {
          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
        } catch (java.io.IOException e) {
          throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(builder.buildPartial());
        }
        return builder.buildPartial();
      }
    };

    public static com.google.protobuf.Parser<M> parser() {
      return PARSER;
    }

    @java.lang.Override
    public com.google.protobuf.Parser<M> getParserForType() {
      return PARSER;
    }

    @java.lang.Override
    public org.apache.avro.protobuf.noopt.Test.M getDefaultInstanceForType() {
      return DEFAULT_INSTANCE;
    }

  }

  private static final com.google.protobuf.Descriptors.Descriptor internal_static_org_apache_avro_protobuf_noopt_Foo_descriptor;
  private static final com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_org_apache_avro_protobuf_noopt_Foo_fieldAccessorTable;
  private static final com.google.protobuf.Descriptors.Descriptor internal_static_org_apache_avro_protobuf_noopt_M_descriptor;
  private static final com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_org_apache_avro_protobuf_noopt_M_fieldAccessorTable;

  public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
    return descriptor;
  }

  private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
  static {
    java.lang.String[] descriptorData = { "\n\034src/test/protobuf/test.proto\022\036org.apac"
        + "he.avro.protobuf.noopt\032\037google/protobuf/"
        + "timestamp.proto\"\204\004\n\003Foo\022\r\n\005int32\030\001 \002(\005\022\r"
        + "\n\005int64\030\002 \001(\003\022\016\n\006uint32\030\003 \001(\r\022\016\n\006uint64\030"
        + "\004 \001(\004\022\016\n\006sint32\030\005 \001(\021\022\016\n\006sint64\030\006 \001(\022\022\017\n"
        + "\007fixed32\030\007 \001(\007\022\017\n\007fixed64\030\010 \001(\006\022\020\n\010sfixe"
        + "d32\030\t \001(\017\022\020\n\010sfixed64\030\n \001(\020\022\r\n\005float\030\013 \001"
        + "(\002\022\016\n\006double\030\014 \001(\001\022\014\n\004bool\030\r \001(\010\022\016\n\006stri"
        + "ng\030\016 \001(\t\022\r\n\005bytes\030\017 \001(\014\0222\n\004enum\030\020 \001(\0162!."
        + "org.apache.avro.protobuf.noopt.A:\001Z\022\020\n\010i"
        + "ntArray\030\021 \003(\005\0225\n\010fooArray\030\024 \003(\0132#.org.ap"
        + "ache.avro.protobuf.noopt.Foo\022/\n\004syms\030\023 \003" + "(\0162!.org.apache.avro.protobuf.noopt.A\0220\n"
        + "\003foo\030\022 \001(\0132#.org.apache.avro.protobuf.no"
        + "opt.Foo\022-\n\ttimestamp\030\025 \001(\0132\032.google.prot"
        + "obuf.Timestamp\"\017\n\001M\"\n\n\001N\022\005\n\001A\020\001*\030\n\001A\022\005\n\001"
        + "X\020\001\022\005\n\001Y\020\002\022\005\n\001Z\020\003" };
    descriptor = com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(descriptorData,
        new com.google.protobuf.Descriptors.FileDescriptor[] { com.google.protobuf.TimestampProto.getDescriptor(), });
    internal_static_org_apache_avro_protobuf_noopt_Foo_descriptor = getDescriptor().getMessageTypes().get(0);
    internal_static_org_apache_avro_protobuf_noopt_Foo_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable(
        internal_static_org_apache_avro_protobuf_noopt_Foo_descriptor,
        new java.lang.String[] { "Int32", "Int64", "Uint32", "Uint64", "Sint32", "Sint64", "Fixed32", "Fixed64",
            "Sfixed32", "Sfixed64", "Float", "Double", "Bool", "String", "Bytes", "Enum", "IntArray", "FooArray",
            "Syms", "Foo", "Timestamp", });
    internal_static_org_apache_avro_protobuf_noopt_M_descriptor = getDescriptor().getMessageTypes().get(1);
    internal_static_org_apache_avro_protobuf_noopt_M_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable(
        internal_static_org_apache_avro_protobuf_noopt_M_descriptor, new java.lang.String[] {});
    descriptor.resolveAllFeaturesImmutable();
    com.google.protobuf.TimestampProto.getDescriptor();
  }

  // @@protoc_insertion_point(outer_class_scope)
}
