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

using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace UnitTest.Issues.TestProtos {

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

    #region Static variables
    internal static pbr::FieldAccessorTable internal__static_unittest_issues_Issue307__FieldAccessorTable;
    internal static pbr::FieldAccessorTable internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable;
    internal static pbr::FieldAccessorTable internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable;
    internal static pbr::FieldAccessorTable internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable;
    internal static pbr::FieldAccessorTable internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable;
    internal static pbr::FieldAccessorTable internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable;
    internal static pbr::FieldAccessorTable internal__static_unittest_issues_ItemField__FieldAccessorTable;
    #endregion
    #region Descriptor
    public static pbr::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbr::FileDescriptor descriptor;

    static UnittestIssues() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcyInCghJ", 
            "c3N1ZTMwNxobCgpOZXN0ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdh", 
            "dGl2ZUVudW1NZXNzYWdlEiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNz", 
            "dWVzLk5lZ2F0aXZlRW51bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9p", 
            "c3N1ZXMuTmVnYXRpdmVFbnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygO", 
            "Mh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVj", 
            "YXRlZENoaWxkIrkCChdEZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5Qcmlt", 
            "aXRpdmVWYWx1ZRgBIAEoBUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVC", 
            "AhgBEjoKDE1lc3NhZ2VWYWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E", 
            "ZXByZWNhdGVkQ2hpbGRCAhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVu", 
            "aXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1", 
            "ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAES", 
            "NgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0", 
            "ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgBIAEoBSpVCgxOZWdh", 
            "dGl2ZUVudW0SFgoSTkVHQVRJVkVfRU5VTV9aRVJPEAASFgoJRml2ZUJlbG93", 
            "EPv//////////wESFQoITWludXNPbmUQ////////////ASouCg5EZXByZWNh", 
            "dGVkRW51bRITCg9ERVBSRUNBVEVEX1pFUk8QABIHCgNvbmUQAUIfSAGqAhpV", 
          "bml0VGVzdC5Jc3N1ZXMuVGVzdFByb3Rvc2IGcHJvdG8z"));
      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
          new pbr::FileDescriptor[] {
          });
      internal__static_unittest_issues_Issue307__FieldAccessorTable = 
          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.Issue307), descriptor.MessageTypes[0],
              new string[] { }, new string[] { });
      internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable = 
          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), descriptor.MessageTypes[0].NestedTypes[0],
              new string[] { }, new string[] { });
      internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable = 
          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), descriptor.MessageTypes[0].NestedTypes[0].NestedTypes[0],
              new string[] { }, new string[] { });
      internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable = 
          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), descriptor.MessageTypes[1],
              new string[] { "Value", "Values", "PackedValues", }, new string[] { });
      internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable = 
          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), descriptor.MessageTypes[2],
              new string[] { }, new string[] { });
      internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable = 
          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), descriptor.MessageTypes[3],
              new string[] { "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray", }, new string[] { });
      internal__static_unittest_issues_ItemField__FieldAccessorTable = 
          new pbr::FieldAccessorTable(typeof(global::UnitTest.Issues.TestProtos.ItemField), descriptor.MessageTypes[4],
              new string[] { "Item", }, new string[] { });
    }
    #endregion

  }
  #region Enums
  public enum NegativeEnum {
    NEGATIVE_ENUM_ZERO = 0,
    FiveBelow = -5,
    MinusOne = -1,
  }

  public enum DeprecatedEnum {
    DEPRECATED_ZERO = 0,
    one = 1,
  }

  #endregion

  #region Messages
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class Issue307 : pb::IMessage<Issue307> {
    private static readonly pb::MessageParser<Issue307> _parser = new pb::MessageParser<Issue307>(() => new Issue307());
    public static pb::MessageParser<Issue307> Parser { get { return _parser; } }

    private static readonly string[] _fieldNames = new string[] {  };
    private static readonly uint[] _fieldTags = new uint[] {  };
    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[0]; }
    }

    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307__FieldAccessorTable; }
    }

    private bool _frozen = false;
    public bool IsFrozen { get { return _frozen; } }

    public Issue307() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Issue307(Issue307 other) : this() {
    }

    public Issue307 Clone() {
      return new Issue307(this);
    }

    public void Freeze() {
      if (IsFrozen) {
        return;
      }
      _frozen = true;
    }

    public override bool Equals(object other) {
      return Equals(other as Issue307);
    }

    public bool Equals(Issue307 other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
    }

    public int CalculateSize() {
      int size = 0;
      return size;
    }

    public void MergeFrom(Issue307 other) {
      if (other == null) {
        return;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
        }
      }
    }

    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      public sealed partial class NestedOnce : pb::IMessage<NestedOnce> {
        private static readonly pb::MessageParser<NestedOnce> _parser = new pb::MessageParser<NestedOnce>(() => new NestedOnce());
        public static pb::MessageParser<NestedOnce> Parser { get { return _parser; } }

        private static readonly string[] _fieldNames = new string[] {  };
        private static readonly uint[] _fieldTags = new uint[] {  };
        public static pbr::MessageDescriptor Descriptor {
          get { return global::UnitTest.Issues.TestProtos.Issue307.Descriptor.NestedTypes[0]; }
        }

        pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
          get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307_NestedOnce__FieldAccessorTable; }
        }

        private bool _frozen = false;
        public bool IsFrozen { get { return _frozen; } }

        public NestedOnce() {
          OnConstruction();
        }

        partial void OnConstruction();

        public NestedOnce(NestedOnce other) : this() {
        }

        public NestedOnce Clone() {
          return new NestedOnce(this);
        }

        public void Freeze() {
          if (IsFrozen) {
            return;
          }
          _frozen = true;
        }

        public override bool Equals(object other) {
          return Equals(other as NestedOnce);
        }

        public bool Equals(NestedOnce other) {
          if (ReferenceEquals(other, null)) {
            return false;
          }
          if (ReferenceEquals(other, this)) {
            return true;
          }
          return true;
        }

        public override int GetHashCode() {
          int hash = 1;
          return hash;
        }

        public override string ToString() {
          return pb::JsonFormatter.Default.Format(this);
        }

        public void WriteTo(pb::CodedOutputStream output) {
        }

        public int CalculateSize() {
          int size = 0;
          return size;
        }

        public void MergeFrom(NestedOnce other) {
          if (other == null) {
            return;
          }
        }

        public void MergeFrom(pb::CodedInputStream input) {
          uint tag;
          while (input.ReadTag(out tag)) {
            switch(tag) {
              case 0:
                throw pb::InvalidProtocolBufferException.InvalidTag();
              default:
                if (pb::WireFormat.IsEndGroupTag(tag)) {
                  return;
                }
                break;
            }
          }
        }

        #region Nested types
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public static partial class Types {
          [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
          public sealed partial class NestedTwice : pb::IMessage<NestedTwice> {
            private static readonly pb::MessageParser<NestedTwice> _parser = new pb::MessageParser<NestedTwice>(() => new NestedTwice());
            public static pb::MessageParser<NestedTwice> Parser { get { return _parser; } }

            private static readonly string[] _fieldNames = new string[] {  };
            private static readonly uint[] _fieldTags = new uint[] {  };
            public static pbr::MessageDescriptor Descriptor {
              get { return global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Descriptor.NestedTypes[0]; }
            }

            pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
              get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_Issue307_NestedOnce_NestedTwice__FieldAccessorTable; }
            }

            private bool _frozen = false;
            public bool IsFrozen { get { return _frozen; } }

            public NestedTwice() {
              OnConstruction();
            }

            partial void OnConstruction();

            public NestedTwice(NestedTwice other) : this() {
            }

            public NestedTwice Clone() {
              return new NestedTwice(this);
            }

            public void Freeze() {
              if (IsFrozen) {
                return;
              }
              _frozen = true;
            }

            public override bool Equals(object other) {
              return Equals(other as NestedTwice);
            }

            public bool Equals(NestedTwice other) {
              if (ReferenceEquals(other, null)) {
                return false;
              }
              if (ReferenceEquals(other, this)) {
                return true;
              }
              return true;
            }

            public override int GetHashCode() {
              int hash = 1;
              return hash;
            }

            public override string ToString() {
              return pb::JsonFormatter.Default.Format(this);
            }

            public void WriteTo(pb::CodedOutputStream output) {
            }

            public int CalculateSize() {
              int size = 0;
              return size;
            }

            public void MergeFrom(NestedTwice other) {
              if (other == null) {
                return;
              }
            }

            public void MergeFrom(pb::CodedInputStream input) {
              uint tag;
              while (input.ReadTag(out tag)) {
                switch(tag) {
                  case 0:
                    throw pb::InvalidProtocolBufferException.InvalidTag();
                  default:
                    if (pb::WireFormat.IsEndGroupTag(tag)) {
                      return;
                    }
                    break;
                }
              }
            }

          }

        }
        #endregion

      }

    }
    #endregion

  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class NegativeEnumMessage : pb::IMessage<NegativeEnumMessage> {
    private static readonly pb::MessageParser<NegativeEnumMessage> _parser = new pb::MessageParser<NegativeEnumMessage>(() => new NegativeEnumMessage());
    public static pb::MessageParser<NegativeEnumMessage> Parser { get { return _parser; } }

    private static readonly string[] _fieldNames = new string[] { "packed_values", "value", "values" };
    private static readonly uint[] _fieldTags = new uint[] { 26, 8, 16 };
    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[1]; }
    }

    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable; }
    }

    private bool _frozen = false;
    public bool IsFrozen { get { return _frozen; } }

    public NegativeEnumMessage() {
      OnConstruction();
    }

    partial void OnConstruction();

    public NegativeEnumMessage(NegativeEnumMessage other) : this() {
      value_ = other.value_;
      values_ = other.values_.Clone();
      packedValues_ = other.packedValues_.Clone();
    }

    public NegativeEnumMessage Clone() {
      return new NegativeEnumMessage(this);
    }

    public void Freeze() {
      if (IsFrozen) {
        return;
      }
      _frozen = true;
      values_.Freeze();
      packedValues_.Freeze();
    }

    public const int ValueFieldNumber = 1;
    private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO;
    public global::UnitTest.Issues.TestProtos.NegativeEnum Value {
      get { return value_; }
      set {
        pb::Freezable.CheckMutable(this);
        value_ = value;
      }
    }

    public const int ValuesFieldNumber = 2;
    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.NegativeEnum> _repeated_values_codec
        = pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> values_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> Values {
      get { return values_; }
    }

    public const int PackedValuesFieldNumber = 3;
    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.NegativeEnum> _repeated_packedValues_codec
        = pb::FieldCodec.ForEnum(26, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> packedValues_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> PackedValues {
      get { return packedValues_; }
    }

    public override bool Equals(object other) {
      return Equals(other as NegativeEnumMessage);
    }

    public bool Equals(NegativeEnumMessage other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Value != other.Value) return false;
      if(!values_.Equals(other.values_)) return false;
      if(!packedValues_.Equals(other.packedValues_)) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) hash ^= Value.GetHashCode();
      hash ^= values_.GetHashCode();
      hash ^= packedValues_.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) {
        output.WriteRawTag(8);
        output.WriteEnum((int) Value);
      }
      values_.WriteTo(output, _repeated_values_codec);
      packedValues_.WriteTo(output, _repeated_packedValues_codec);
    }

    public int CalculateSize() {
      int size = 0;
      if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value);
      }
      size += values_.CalculateSize(_repeated_values_codec);
      size += packedValues_.CalculateSize(_repeated_packedValues_codec);
      return size;
    }

    public void MergeFrom(NegativeEnumMessage other) {
      if (other == null) {
        return;
      }
      if (other.Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) {
        Value = other.Value;
      }
      values_.Add(other.values_);
      packedValues_.Add(other.packedValues_);
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 8: {
            value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
            break;
          }
          case 18:
          case 16: {
            values_.AddEntriesFrom(input, _repeated_values_codec);
            break;
          }
          case 26:
          case 24: {
            packedValues_.AddEntriesFrom(input, _repeated_packedValues_codec);
            break;
          }
        }
      }
    }

  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class DeprecatedChild : pb::IMessage<DeprecatedChild> {
    private static readonly pb::MessageParser<DeprecatedChild> _parser = new pb::MessageParser<DeprecatedChild>(() => new DeprecatedChild());
    public static pb::MessageParser<DeprecatedChild> Parser { get { return _parser; } }

    private static readonly string[] _fieldNames = new string[] {  };
    private static readonly uint[] _fieldTags = new uint[] {  };
    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[2]; }
    }

    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable; }
    }

    private bool _frozen = false;
    public bool IsFrozen { get { return _frozen; } }

    public DeprecatedChild() {
      OnConstruction();
    }

    partial void OnConstruction();

    public DeprecatedChild(DeprecatedChild other) : this() {
    }

    public DeprecatedChild Clone() {
      return new DeprecatedChild(this);
    }

    public void Freeze() {
      if (IsFrozen) {
        return;
      }
      _frozen = true;
    }

    public override bool Equals(object other) {
      return Equals(other as DeprecatedChild);
    }

    public bool Equals(DeprecatedChild other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
    }

    public int CalculateSize() {
      int size = 0;
      return size;
    }

    public void MergeFrom(DeprecatedChild other) {
      if (other == null) {
        return;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
        }
      }
    }

  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class DeprecatedFieldsMessage : pb::IMessage<DeprecatedFieldsMessage> {
    private static readonly pb::MessageParser<DeprecatedFieldsMessage> _parser = new pb::MessageParser<DeprecatedFieldsMessage>(() => new DeprecatedFieldsMessage());
    public static pb::MessageParser<DeprecatedFieldsMessage> Parser { get { return _parser; } }

    private static readonly string[] _fieldNames = new string[] { "EnumArray", "EnumValue", "MessageArray", "MessageValue", "PrimitiveArray", "PrimitiveValue" };
    private static readonly uint[] _fieldTags = new uint[] { 50, 40, 34, 26, 18, 8 };
    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[3]; }
    }

    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable; }
    }

    private bool _frozen = false;
    public bool IsFrozen { get { return _frozen; } }

    public DeprecatedFieldsMessage() {
      OnConstruction();
    }

    partial void OnConstruction();

    public DeprecatedFieldsMessage(DeprecatedFieldsMessage other) : this() {
      primitiveValue_ = other.primitiveValue_;
      primitiveArray_ = other.primitiveArray_.Clone();
      MessageValue = other.messageValue_ != null ? other.MessageValue.Clone() : null;
      messageArray_ = other.messageArray_.Clone();
      enumValue_ = other.enumValue_;
      enumArray_ = other.enumArray_.Clone();
    }

    public DeprecatedFieldsMessage Clone() {
      return new DeprecatedFieldsMessage(this);
    }

    public void Freeze() {
      if (IsFrozen) {
        return;
      }
      _frozen = true;
      primitiveArray_.Freeze();
      if (messageValue_ != null) MessageValue.Freeze();
      messageArray_.Freeze();
      enumArray_.Freeze();
    }

    public const int PrimitiveValueFieldNumber = 1;
    private int primitiveValue_;
    [global::System.ObsoleteAttribute()]
    public int PrimitiveValue {
      get { return primitiveValue_; }
      set {
        pb::Freezable.CheckMutable(this);
        primitiveValue_ = value;
      }
    }

    public const int PrimitiveArrayFieldNumber = 2;
    private static readonly pb::FieldCodec<int> _repeated_primitiveArray_codec
        = pb::FieldCodec.ForInt32(18);
    private readonly pbc::RepeatedField<int> primitiveArray_ = new pbc::RepeatedField<int>();
    [global::System.ObsoleteAttribute()]
    public pbc::RepeatedField<int> PrimitiveArray {
      get { return primitiveArray_; }
    }

    public const int MessageValueFieldNumber = 3;
    private global::UnitTest.Issues.TestProtos.DeprecatedChild messageValue_;
    [global::System.ObsoleteAttribute()]
    public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue {
      get { return messageValue_; }
      set {
        pb::Freezable.CheckMutable(this);
        messageValue_ = value;
      }
    }

    public const int MessageArrayFieldNumber = 4;
    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.DeprecatedChild> _repeated_messageArray_codec
        = pb::FieldCodec.ForMessage(34, global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser);
    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild> messageArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild>();
    [global::System.ObsoleteAttribute()]
    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild> MessageArray {
      get { return messageArray_; }
    }

    public const int EnumValueFieldNumber = 5;
    private global::UnitTest.Issues.TestProtos.DeprecatedEnum enumValue_ = global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO;
    [global::System.ObsoleteAttribute()]
    public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue {
      get { return enumValue_; }
      set {
        pb::Freezable.CheckMutable(this);
        enumValue_ = value;
      }
    }

    public const int EnumArrayFieldNumber = 6;
    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.DeprecatedEnum> _repeated_enumArray_codec
        = pb::FieldCodec.ForEnum(50, x => (int) x, x => (global::UnitTest.Issues.TestProtos.DeprecatedEnum) x);private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> enumArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum>();
    [global::System.ObsoleteAttribute()]
    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArray {
      get { return enumArray_; }
    }

    public override bool Equals(object other) {
      return Equals(other as DeprecatedFieldsMessage);
    }

    public bool Equals(DeprecatedFieldsMessage other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (PrimitiveValue != other.PrimitiveValue) return false;
      if(!primitiveArray_.Equals(other.primitiveArray_)) return false;
      if (!object.Equals(MessageValue, other.MessageValue)) return false;
      if(!messageArray_.Equals(other.messageArray_)) return false;
      if (EnumValue != other.EnumValue) return false;
      if(!enumArray_.Equals(other.enumArray_)) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (PrimitiveValue != 0) hash ^= PrimitiveValue.GetHashCode();
      hash ^= primitiveArray_.GetHashCode();
      if (messageValue_ != null) hash ^= MessageValue.GetHashCode();
      hash ^= messageArray_.GetHashCode();
      if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) hash ^= EnumValue.GetHashCode();
      hash ^= enumArray_.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (PrimitiveValue != 0) {
        output.WriteRawTag(8);
        output.WriteInt32(PrimitiveValue);
      }
      primitiveArray_.WriteTo(output, _repeated_primitiveArray_codec);
      if (messageValue_ != null) {
        output.WriteRawTag(26);
        output.WriteMessage(MessageValue);
      }
      messageArray_.WriteTo(output, _repeated_messageArray_codec);
      if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) {
        output.WriteRawTag(40);
        output.WriteEnum((int) EnumValue);
      }
      enumArray_.WriteTo(output, _repeated_enumArray_codec);
    }

    public int CalculateSize() {
      int size = 0;
      if (PrimitiveValue != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveValue);
      }
      size += primitiveArray_.CalculateSize(_repeated_primitiveArray_codec);
      if (messageValue_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageValue);
      }
      size += messageArray_.CalculateSize(_repeated_messageArray_codec);
      if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumValue);
      }
      size += enumArray_.CalculateSize(_repeated_enumArray_codec);
      return size;
    }

    public void MergeFrom(DeprecatedFieldsMessage other) {
      if (other == null) {
        return;
      }
      if (other.PrimitiveValue != 0) {
        PrimitiveValue = other.PrimitiveValue;
      }
      primitiveArray_.Add(other.primitiveArray_);
      if (other.messageValue_ != null) {
        if (messageValue_ == null) {
          messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
        }
        MessageValue.MergeFrom(other.MessageValue);
      }
      messageArray_.Add(other.messageArray_);
      if (other.EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) {
        EnumValue = other.EnumValue;
      }
      enumArray_.Add(other.enumArray_);
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 8: {
            PrimitiveValue = input.ReadInt32();
            break;
          }
          case 18:
          case 16: {
            primitiveArray_.AddEntriesFrom(input, _repeated_primitiveArray_codec);
            break;
          }
          case 26: {
            if (messageValue_ == null) {
              messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
            }
            input.ReadMessage(messageValue_);
            break;
          }
          case 34: {
            messageArray_.AddEntriesFrom(input, _repeated_messageArray_codec);
            break;
          }
          case 40: {
            enumValue_ = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum();
            break;
          }
          case 50:
          case 48: {
            enumArray_.AddEntriesFrom(input, _repeated_enumArray_codec);
            break;
          }
        }
      }
    }

  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class ItemField : pb::IMessage<ItemField> {
    private static readonly pb::MessageParser<ItemField> _parser = new pb::MessageParser<ItemField>(() => new ItemField());
    public static pb::MessageParser<ItemField> Parser { get { return _parser; } }

    private static readonly string[] _fieldNames = new string[] { "item" };
    private static readonly uint[] _fieldTags = new uint[] { 8 };
    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[4]; }
    }

    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_ItemField__FieldAccessorTable; }
    }

    private bool _frozen = false;
    public bool IsFrozen { get { return _frozen; } }

    public ItemField() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ItemField(ItemField other) : this() {
      item_ = other.item_;
    }

    public ItemField Clone() {
      return new ItemField(this);
    }

    public void Freeze() {
      if (IsFrozen) {
        return;
      }
      _frozen = true;
    }

    public const int ItemFieldNumber = 1;
    private int item_;
    public int Item {
      get { return item_; }
      set {
        pb::Freezable.CheckMutable(this);
        item_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as ItemField);
    }

    public bool Equals(ItemField other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Item != other.Item) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Item != 0) hash ^= Item.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (Item != 0) {
        output.WriteRawTag(8);
        output.WriteInt32(Item);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Item != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Item);
      }
      return size;
    }

    public void MergeFrom(ItemField other) {
      if (other == null) {
        return;
      }
      if (other.Item != 0) {
        Item = other.Item;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 8: {
            Item = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
