// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: google/protobuf/unittest_drop_unknown_fields.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code

using pb = global::Google.ProtocolBuffers;
using pbc = global::Google.ProtocolBuffers.Collections;
using pbd = global::Google.ProtocolBuffers.Descriptors;
using scg = global::System.Collections.Generic;
namespace Google.ProtocolBuffers.TestProtos {

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public static partial class UnittestDropUnknownFields {

    #region Extension registration
    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
    }
    #endregion
    #region Static variables
    internal static pbd::MessageDescriptor internal__static_unittest_drop_unknown_fields_Foo__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.Foo, global::Google.ProtocolBuffers.TestProtos.Foo.Builder> internal__static_unittest_drop_unknown_fields_Foo__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_unittest_drop_unknown_fields_FooWithExtraFields__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields, global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.Builder> internal__static_unittest_drop_unknown_fields_FooWithExtraFields__FieldAccessorTable;
    #endregion
    #region Descriptor
    public static pbd::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbd::FileDescriptor descriptor;

    static UnittestDropUnknownFields() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "CjJnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfZHJvcF91bmtub3duX2ZpZWxk", 
            "cy5wcm90bxIcdW5pdHRlc3RfZHJvcF91bmtub3duX2ZpZWxkcyKFAQoDRm9v", 
            "EhMKC2ludDMyX3ZhbHVlGAEgASgFEkAKCmVudW1fdmFsdWUYAiABKA4yLC51", 
            "bml0dGVzdF9kcm9wX3Vua25vd25fZmllbGRzLkZvby5OZXN0ZWRFbnVtIicK", 
            "Ck5lc3RlZEVudW0SBwoDRk9PEAASBwoDQkFSEAESBwoDQkFaEAIixwEKEkZv", 
            "b1dpdGhFeHRyYUZpZWxkcxITCgtpbnQzMl92YWx1ZRgBIAEoBRJPCgplbnVt", 
            "X3ZhbHVlGAIgASgOMjsudW5pdHRlc3RfZHJvcF91bmtub3duX2ZpZWxkcy5G", 
            "b29XaXRoRXh0cmFGaWVsZHMuTmVzdGVkRW51bRIZChFleHRyYV9pbnQzMl92", 
            "YWx1ZRgDIAEoBSIwCgpOZXN0ZWRFbnVtEgcKA0ZPTxAAEgcKA0JBUhABEgcK", 
            "A0JBWhACEgcKA1FVWBADQiSqAiFHb29nbGUuUHJvdG9jb2xCdWZmZXJzLlRl", 
          "c3RQcm90b3NiBnByb3RvMw=="));
      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
        descriptor = root;
        internal__static_unittest_drop_unknown_fields_Foo__Descriptor = Descriptor.MessageTypes[0];
        internal__static_unittest_drop_unknown_fields_Foo__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.Foo, global::Google.ProtocolBuffers.TestProtos.Foo.Builder>(internal__static_unittest_drop_unknown_fields_Foo__Descriptor,
                new string[] { "Int32Value", "EnumValue", });
        internal__static_unittest_drop_unknown_fields_FooWithExtraFields__Descriptor = Descriptor.MessageTypes[1];
        internal__static_unittest_drop_unknown_fields_FooWithExtraFields__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields, global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.Builder>(internal__static_unittest_drop_unknown_fields_FooWithExtraFields__Descriptor,
                new string[] { "Int32Value", "EnumValue", "ExtraInt32Value", });
        pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
        RegisterAllExtensions(registry);
        return registry;
      };
      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
          new pbd::FileDescriptor[] {
          }, assigner);
    }
    #endregion

  }
  #region Messages
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class Foo : pb::GeneratedMessage<Foo, Foo.Builder> {
    private Foo() { }
    private static readonly Foo defaultInstance = new Foo().MakeReadOnly();
    private static readonly string[] _fooFieldNames = new string[] { "enum_value", "int32_value" };
    private static readonly uint[] _fooFieldTags = new uint[] { 16, 8 };
    public static Foo DefaultInstance {
      get { return defaultInstance; }
    }

    public override Foo DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override Foo ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestDropUnknownFields.internal__static_unittest_drop_unknown_fields_Foo__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<Foo, Foo.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestDropUnknownFields.internal__static_unittest_drop_unknown_fields_Foo__FieldAccessorTable; }
    }

    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      public enum NestedEnum {
        FOO = 0,
        BAR = 1,
        BAZ = 2,
      }

    }
    #endregion

    public const int Int32ValueFieldNumber = 1;
    private bool hasInt32Value;
    private int int32Value_;
    public bool HasInt32Value {
      get { return hasInt32Value; }
    }
    public int Int32Value {
      get { return int32Value_; }
    }

    public const int EnumValueFieldNumber = 2;
    private bool hasEnumValue;
    private global::Google.ProtocolBuffers.TestProtos.Foo.Types.NestedEnum enumValue_ = global::Google.ProtocolBuffers.TestProtos.Foo.Types.NestedEnum.FOO;
    public bool HasEnumValue {
      get { return hasEnumValue; }
    }
    public global::Google.ProtocolBuffers.TestProtos.Foo.Types.NestedEnum EnumValue {
      get { return enumValue_; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _fooFieldNames;
      if (hasInt32Value) {
        output.WriteInt32(1, field_names[1], Int32Value);
      }
      if (hasEnumValue) {
        output.WriteEnum(2, field_names[0], (int) EnumValue, EnumValue);
      }
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (hasInt32Value) {
        size += pb::CodedOutputStream.ComputeInt32Size(1, Int32Value);
      }
      if (hasEnumValue) {
        size += pb::CodedOutputStream.ComputeEnumSize(2, (int) EnumValue);
      }
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static Foo ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static Foo ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static Foo ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static Foo ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static Foo ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static Foo ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static Foo ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static Foo ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static Foo ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static Foo ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private Foo MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(Foo prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<Foo, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(Foo cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private Foo result;

      private Foo PrepareBuilder() {
        if (resultIsReadOnly) {
          Foo original = result;
          result = new Foo();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override Foo MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.Foo.Descriptor; }
      }

      public override Foo DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.Foo.DefaultInstance; }
      }

      public override Foo BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is Foo) {
          return MergeFrom((Foo) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(Foo other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.Foo.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasInt32Value) {
          Int32Value = other.Int32Value;
        }
        if (other.HasEnumValue) {
          EnumValue = other.EnumValue;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_fooFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _fooFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.hasInt32Value = input.ReadInt32(ref result.int32Value_);
              break;
            }
            case 16: {
              object unknown;
              if(input.ReadEnum(ref result.enumValue_, out unknown)) {
                result.hasEnumValue = true;
              } else if(unknown is int) {
                if (unknownFields == null) {
                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                }
                unknownFields.MergeVarintField(2, (ulong)(int)unknown);
              }
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }


      public bool HasInt32Value {
        get { return result.hasInt32Value; }
      }
      public int Int32Value {
        get { return result.Int32Value; }
        set { SetInt32Value(value); }
      }
      public Builder SetInt32Value(int value) {
        PrepareBuilder();
        result.hasInt32Value = true;
        result.int32Value_ = value;
        return this;
      }
      public Builder ClearInt32Value() {
        PrepareBuilder();
        result.hasInt32Value = false;
        result.int32Value_ = 0;
        return this;
      }

      public bool HasEnumValue {
       get { return result.hasEnumValue; }
      }
      public global::Google.ProtocolBuffers.TestProtos.Foo.Types.NestedEnum EnumValue {
        get { return result.EnumValue; }
        set { SetEnumValue(value); }
      }
      public Builder SetEnumValue(global::Google.ProtocolBuffers.TestProtos.Foo.Types.NestedEnum value) {
        PrepareBuilder();
        result.hasEnumValue = true;
        result.enumValue_ = value;
        return this;
      }
      public Builder ClearEnumValue() {
        PrepareBuilder();
        result.hasEnumValue = false;
        result.enumValue_ = global::Google.ProtocolBuffers.TestProtos.Foo.Types.NestedEnum.FOO;
        return this;
      }
    }
    static Foo() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestDropUnknownFields.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class FooWithExtraFields : pb::GeneratedMessage<FooWithExtraFields, FooWithExtraFields.Builder> {
    private FooWithExtraFields() { }
    private static readonly FooWithExtraFields defaultInstance = new FooWithExtraFields().MakeReadOnly();
    private static readonly string[] _fooWithExtraFieldsFieldNames = new string[] { "enum_value", "extra_int32_value", "int32_value" };
    private static readonly uint[] _fooWithExtraFieldsFieldTags = new uint[] { 16, 24, 8 };
    public static FooWithExtraFields DefaultInstance {
      get { return defaultInstance; }
    }

    public override FooWithExtraFields DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override FooWithExtraFields ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestDropUnknownFields.internal__static_unittest_drop_unknown_fields_FooWithExtraFields__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<FooWithExtraFields, FooWithExtraFields.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestDropUnknownFields.internal__static_unittest_drop_unknown_fields_FooWithExtraFields__FieldAccessorTable; }
    }

    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      public enum NestedEnum {
        FOO = 0,
        BAR = 1,
        BAZ = 2,
        QUX = 3,
      }

    }
    #endregion

    public const int Int32ValueFieldNumber = 1;
    private bool hasInt32Value;
    private int int32Value_;
    public bool HasInt32Value {
      get { return hasInt32Value; }
    }
    public int Int32Value {
      get { return int32Value_; }
    }

    public const int EnumValueFieldNumber = 2;
    private bool hasEnumValue;
    private global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.Types.NestedEnum enumValue_ = global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.Types.NestedEnum.FOO;
    public bool HasEnumValue {
      get { return hasEnumValue; }
    }
    public global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.Types.NestedEnum EnumValue {
      get { return enumValue_; }
    }

    public const int ExtraInt32ValueFieldNumber = 3;
    private bool hasExtraInt32Value;
    private int extraInt32Value_;
    public bool HasExtraInt32Value {
      get { return hasExtraInt32Value; }
    }
    public int ExtraInt32Value {
      get { return extraInt32Value_; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _fooWithExtraFieldsFieldNames;
      if (hasInt32Value) {
        output.WriteInt32(1, field_names[2], Int32Value);
      }
      if (hasEnumValue) {
        output.WriteEnum(2, field_names[0], (int) EnumValue, EnumValue);
      }
      if (hasExtraInt32Value) {
        output.WriteInt32(3, field_names[1], ExtraInt32Value);
      }
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (hasInt32Value) {
        size += pb::CodedOutputStream.ComputeInt32Size(1, Int32Value);
      }
      if (hasEnumValue) {
        size += pb::CodedOutputStream.ComputeEnumSize(2, (int) EnumValue);
      }
      if (hasExtraInt32Value) {
        size += pb::CodedOutputStream.ComputeInt32Size(3, ExtraInt32Value);
      }
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static FooWithExtraFields ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static FooWithExtraFields ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static FooWithExtraFields ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static FooWithExtraFields ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static FooWithExtraFields ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static FooWithExtraFields ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static FooWithExtraFields ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static FooWithExtraFields ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static FooWithExtraFields ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static FooWithExtraFields ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private FooWithExtraFields MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(FooWithExtraFields prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<FooWithExtraFields, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(FooWithExtraFields cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private FooWithExtraFields result;

      private FooWithExtraFields PrepareBuilder() {
        if (resultIsReadOnly) {
          FooWithExtraFields original = result;
          result = new FooWithExtraFields();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override FooWithExtraFields MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.Descriptor; }
      }

      public override FooWithExtraFields DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.DefaultInstance; }
      }

      public override FooWithExtraFields BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is FooWithExtraFields) {
          return MergeFrom((FooWithExtraFields) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(FooWithExtraFields other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasInt32Value) {
          Int32Value = other.Int32Value;
        }
        if (other.HasEnumValue) {
          EnumValue = other.EnumValue;
        }
        if (other.HasExtraInt32Value) {
          ExtraInt32Value = other.ExtraInt32Value;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_fooWithExtraFieldsFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _fooWithExtraFieldsFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.hasInt32Value = input.ReadInt32(ref result.int32Value_);
              break;
            }
            case 16: {
              object unknown;
              if(input.ReadEnum(ref result.enumValue_, out unknown)) {
                result.hasEnumValue = true;
              } else if(unknown is int) {
                if (unknownFields == null) {
                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                }
                unknownFields.MergeVarintField(2, (ulong)(int)unknown);
              }
              break;
            }
            case 24: {
              result.hasExtraInt32Value = input.ReadInt32(ref result.extraInt32Value_);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }


      public bool HasInt32Value {
        get { return result.hasInt32Value; }
      }
      public int Int32Value {
        get { return result.Int32Value; }
        set { SetInt32Value(value); }
      }
      public Builder SetInt32Value(int value) {
        PrepareBuilder();
        result.hasInt32Value = true;
        result.int32Value_ = value;
        return this;
      }
      public Builder ClearInt32Value() {
        PrepareBuilder();
        result.hasInt32Value = false;
        result.int32Value_ = 0;
        return this;
      }

      public bool HasEnumValue {
       get { return result.hasEnumValue; }
      }
      public global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.Types.NestedEnum EnumValue {
        get { return result.EnumValue; }
        set { SetEnumValue(value); }
      }
      public Builder SetEnumValue(global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.Types.NestedEnum value) {
        PrepareBuilder();
        result.hasEnumValue = true;
        result.enumValue_ = value;
        return this;
      }
      public Builder ClearEnumValue() {
        PrepareBuilder();
        result.hasEnumValue = false;
        result.enumValue_ = global::Google.ProtocolBuffers.TestProtos.FooWithExtraFields.Types.NestedEnum.FOO;
        return this;
      }

      public bool HasExtraInt32Value {
        get { return result.hasExtraInt32Value; }
      }
      public int ExtraInt32Value {
        get { return result.ExtraInt32Value; }
        set { SetExtraInt32Value(value); }
      }
      public Builder SetExtraInt32Value(int value) {
        PrepareBuilder();
        result.hasExtraInt32Value = true;
        result.extraInt32Value_ = value;
        return this;
      }
      public Builder ClearExtraInt32Value() {
        PrepareBuilder();
        result.hasExtraInt32Value = false;
        result.extraInt32Value_ = 0;
        return this;
      }
    }
    static FooWithExtraFields() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestDropUnknownFields.Descriptor, null);
    }
  }

  #endregion

}

#endregion Designer generated code
