// 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 {

  /// <summary>Holder for reflection information generated from unittest_issues.proto</summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public static partial class UnittestIssuesReflection {

    #region Descriptor
    /// <summary>File descriptor for unittest_issues.proto</summary>
    public static pbr::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbr::FileDescriptor descriptor;

    static UnittestIssuesReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcyInCghJ",
            "c3N1ZTMwNxobCgpOZXN0ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdh",
            "dGl2ZUVudW1NZXNzYWdlEiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNz",
            "dWVzLk5lZ2F0aXZlRW51bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9p",
            "c3N1ZXMuTmVnYXRpdmVFbnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygO",
            "Mh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVj",
            "YXRlZENoaWxkIrkCChdEZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5Qcmlt",
            "aXRpdmVWYWx1ZRgBIAEoBUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVC",
            "AhgBEjoKDE1lc3NhZ2VWYWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E",
            "ZXByZWNhdGVkQ2hpbGRCAhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVu",
            "aXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1",
            "ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAES",
            "NgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0",
            "ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNl",
            "cnZlZE5hbWVzEg0KBXR5cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUa",
            "EAoOU29tZU5lc3RlZFR5cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxIT",
            "CgtwbGFpbl9pbnQzMhgEIAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghv",
            "MV9pbnQzMhgFIAEoBUgAEhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9p",
            "bnQzMhgGIAEoBUgBEhMKCW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8y",
            "KlUKDE5lZ2F0aXZlRW51bRIWChJORUdBVElWRV9FTlVNX1pFUk8QABIWCglG",
            "aXZlQmVsb3cQ+///////////ARIVCghNaW51c09uZRD///////////8BKi4K",
            "DkRlcHJlY2F0ZWRFbnVtEhMKD0RFUFJFQ0FURURfWkVSTxAAEgcKA29uZRAB",
            "Qh9IAaoCGlVuaXRUZXN0Lklzc3Vlcy5UZXN0UHJvdG9zYgZwcm90bzM="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { },
          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307), global::UnitTest.Issues.TestProtos.Issue307.Parser, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Parser, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice.Parser, null, null, null, null)})}),
            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Parser, new[]{ "Value", "Values", "PackedValues" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser, null, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Parser, new[]{ "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ItemField), global::UnitTest.Issues.TestProtos.ItemField.Parser, new[]{ "Item" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), global::UnitTest.Issues.TestProtos.ReservedNames.Parser, new[]{ "Types_", "Descriptor_" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType.Parser, null, null, null, null)}),
            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering), global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering.Parser, new[]{ "PlainInt32", "O1String", "O1Int32", "PlainString", "O2Int32", "O2String" }, new[]{ "O1", "O2" }, null, null)
          }));
    }
    #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
  /// <summary>
  ///  Issue 307: when generating doubly-nested types, any references
  ///  should be of the form A.Types.B.Types.C.
  /// </summary>
  [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; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[0]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public Issue307() {
      OnConstruction();
    }

    partial void OnConstruction();

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

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

    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.ToDiagnosticString(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 ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
        }
      }
    }

    #region Nested types
    /// <summary>Container for nested types declared in the Issue307 message type.</summary>
    [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; } }

        public static pbr::MessageDescriptor Descriptor {
          get { return global::UnitTest.Issues.TestProtos.Issue307.Descriptor.NestedTypes[0]; }
        }

        pbr::MessageDescriptor pb::IMessage.Descriptor {
          get { return Descriptor; }
        }

        public NestedOnce() {
          OnConstruction();
        }

        partial void OnConstruction();

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

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

        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.ToDiagnosticString(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 ((tag = input.ReadTag()) != 0) {
            switch(tag) {
              default:
                input.SkipLastField();
                break;
            }
          }
        }

        #region Nested types
        /// <summary>Container for nested types declared in the NestedOnce message type.</summary>
        [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; } }

            public static pbr::MessageDescriptor Descriptor {
              get { return global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Descriptor.NestedTypes[0]; }
            }

            pbr::MessageDescriptor pb::IMessage.Descriptor {
              get { return Descriptor; }
            }

            public NestedTwice() {
              OnConstruction();
            }

            partial void OnConstruction();

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

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

            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.ToDiagnosticString(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 ((tag = input.ReadTag()) != 0) {
                switch(tag) {
                  default:
                    input.SkipLastField();
                    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; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[1]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    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);
    }

    /// <summary>Field number for the "value" field.</summary>
    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 {
        value_ = value;
      }
    }

    /// <summary>Field number for the "values" field.</summary>
    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_; }
    }

    /// <summary>Field number for the "packed_values" field.</summary>
    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.ToDiagnosticString(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 ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            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; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[2]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public DeprecatedChild() {
      OnConstruction();
    }

    partial void OnConstruction();

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

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

    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.ToDiagnosticString(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 ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            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; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[3]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    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);
    }

    /// <summary>Field number for the "PrimitiveValue" field.</summary>
    public const int PrimitiveValueFieldNumber = 1;
    private int primitiveValue_;
    [global::System.ObsoleteAttribute()]
    public int PrimitiveValue {
      get { return primitiveValue_; }
      set {
        primitiveValue_ = value;
      }
    }

    /// <summary>Field number for the "PrimitiveArray" field.</summary>
    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_; }
    }

    /// <summary>Field number for the "MessageValue" field.</summary>
    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 {
        messageValue_ = value;
      }
    }

    /// <summary>Field number for the "MessageArray" field.</summary>
    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_; }
    }

    /// <summary>Field number for the "EnumValue" field.</summary>
    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 {
        enumValue_ = value;
      }
    }

    /// <summary>Field number for the "EnumArray" field.</summary>
    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.ToDiagnosticString(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 ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            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;
          }
        }
      }
    }

  }

  /// <summary>
  ///  Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45
  /// </summary>
  [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; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[4]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public ItemField() {
      OnConstruction();
    }

    partial void OnConstruction();

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

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

    /// <summary>Field number for the "item" field.</summary>
    public const int ItemFieldNumber = 1;
    private int item_;
    public int Item {
      get { return item_; }
      set {
        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.ToDiagnosticString(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 ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            Item = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

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

    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[5]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public ReservedNames() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ReservedNames(ReservedNames other) : this() {
      types_ = other.types_;
      descriptor_ = other.descriptor_;
    }

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

    /// <summary>Field number for the "types" field.</summary>
    public const int Types_FieldNumber = 1;
    private int types_;
    public int Types_ {
      get { return types_; }
      set {
        types_ = value;
      }
    }

    /// <summary>Field number for the "descriptor" field.</summary>
    public const int Descriptor_FieldNumber = 2;
    private int descriptor_;
    public int Descriptor_ {
      get { return descriptor_; }
      set {
        descriptor_ = value;
      }
    }

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

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

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

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

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

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

    public void MergeFrom(ReservedNames other) {
      if (other == null) {
        return;
      }
      if (other.Types_ != 0) {
        Types_ = other.Types_;
      }
      if (other.Descriptor_ != 0) {
        Descriptor_ = other.Descriptor_;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            Types_ = input.ReadInt32();
            break;
          }
          case 16: {
            Descriptor_ = input.ReadInt32();
            break;
          }
        }
      }
    }

    #region Nested types
    /// <summary>Container for nested types declared in the ReservedNames message type.</summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      /// <summary>
      ///  Force a nested type called Types
      /// </summary>
      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      public sealed partial class SomeNestedType : pb::IMessage<SomeNestedType> {
        private static readonly pb::MessageParser<SomeNestedType> _parser = new pb::MessageParser<SomeNestedType>(() => new SomeNestedType());
        public static pb::MessageParser<SomeNestedType> Parser { get { return _parser; } }

        public static pbr::MessageDescriptor Descriptor {
          get { return global::UnitTest.Issues.TestProtos.ReservedNames.Descriptor.NestedTypes[0]; }
        }

        pbr::MessageDescriptor pb::IMessage.Descriptor {
          get { return Descriptor; }
        }

        public SomeNestedType() {
          OnConstruction();
        }

        partial void OnConstruction();

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

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

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

        public bool Equals(SomeNestedType 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.ToDiagnosticString(this);
        }

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

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

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

        public void MergeFrom(pb::CodedInputStream input) {
          uint tag;
          while ((tag = input.ReadTag()) != 0) {
            switch(tag) {
              default:
                input.SkipLastField();
                break;
            }
          }
        }

      }

    }
    #endregion

  }

  /// <summary>
  ///  These fields are deliberately not declared in numeric
  ///  order, and the oneof fields aren't contiguous either.
  ///  This allows for reasonably robust tests of JSON output
  ///  ordering.
  ///  TestFieldOrderings in unittest_proto3.proto is similar,
  ///  but doesn't include oneofs.
  ///  TODO: Consider adding oneofs to TestFieldOrderings, although
  ///  that will require fixing other tests in multiple platforms.
  ///  Alternatively, consider just adding this to
  ///  unittest_proto3.proto if multiple platforms want it.
  /// </summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class TestJsonFieldOrdering : pb::IMessage<TestJsonFieldOrdering> {
    private static readonly pb::MessageParser<TestJsonFieldOrdering> _parser = new pb::MessageParser<TestJsonFieldOrdering>(() => new TestJsonFieldOrdering());
    public static pb::MessageParser<TestJsonFieldOrdering> Parser { get { return _parser; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[6]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public TestJsonFieldOrdering() {
      OnConstruction();
    }

    partial void OnConstruction();

    public TestJsonFieldOrdering(TestJsonFieldOrdering other) : this() {
      plainInt32_ = other.plainInt32_;
      plainString_ = other.plainString_;
      switch (other.O1Case) {
        case O1OneofCase.O1String:
          O1String = other.O1String;
          break;
        case O1OneofCase.O1Int32:
          O1Int32 = other.O1Int32;
          break;
      }

      switch (other.O2Case) {
        case O2OneofCase.O2Int32:
          O2Int32 = other.O2Int32;
          break;
        case O2OneofCase.O2String:
          O2String = other.O2String;
          break;
      }

    }

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

    /// <summary>Field number for the "plain_int32" field.</summary>
    public const int PlainInt32FieldNumber = 4;
    private int plainInt32_;
    public int PlainInt32 {
      get { return plainInt32_; }
      set {
        plainInt32_ = value;
      }
    }

    /// <summary>Field number for the "o1_string" field.</summary>
    public const int O1StringFieldNumber = 2;
    public string O1String {
      get { return o1Case_ == O1OneofCase.O1String ? (string) o1_ : ""; }
      set {
        o1_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        o1Case_ = O1OneofCase.O1String;
      }
    }

    /// <summary>Field number for the "o1_int32" field.</summary>
    public const int O1Int32FieldNumber = 5;
    public int O1Int32 {
      get { return o1Case_ == O1OneofCase.O1Int32 ? (int) o1_ : 0; }
      set {
        o1_ = value;
        o1Case_ = O1OneofCase.O1Int32;
      }
    }

    /// <summary>Field number for the "plain_string" field.</summary>
    public const int PlainStringFieldNumber = 1;
    private string plainString_ = "";
    public string PlainString {
      get { return plainString_; }
      set {
        plainString_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "o2_int32" field.</summary>
    public const int O2Int32FieldNumber = 6;
    public int O2Int32 {
      get { return o2Case_ == O2OneofCase.O2Int32 ? (int) o2_ : 0; }
      set {
        o2_ = value;
        o2Case_ = O2OneofCase.O2Int32;
      }
    }

    /// <summary>Field number for the "o2_string" field.</summary>
    public const int O2StringFieldNumber = 3;
    public string O2String {
      get { return o2Case_ == O2OneofCase.O2String ? (string) o2_ : ""; }
      set {
        o2_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        o2Case_ = O2OneofCase.O2String;
      }
    }

    private object o1_;
    /// <summary>Enum of possible cases for the "o1" oneof.</summary>
    public enum O1OneofCase {
      None = 0,
      O1String = 2,
      O1Int32 = 5,
    }
    private O1OneofCase o1Case_ = O1OneofCase.None;
    public O1OneofCase O1Case {
      get { return o1Case_; }
    }

    public void ClearO1() {
      o1Case_ = O1OneofCase.None;
      o1_ = null;
    }

    private object o2_;
    /// <summary>Enum of possible cases for the "o2" oneof.</summary>
    public enum O2OneofCase {
      None = 0,
      O2Int32 = 6,
      O2String = 3,
    }
    private O2OneofCase o2Case_ = O2OneofCase.None;
    public O2OneofCase O2Case {
      get { return o2Case_; }
    }

    public void ClearO2() {
      o2Case_ = O2OneofCase.None;
      o2_ = null;
    }

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

    public bool Equals(TestJsonFieldOrdering other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (PlainInt32 != other.PlainInt32) return false;
      if (O1String != other.O1String) return false;
      if (O1Int32 != other.O1Int32) return false;
      if (PlainString != other.PlainString) return false;
      if (O2Int32 != other.O2Int32) return false;
      if (O2String != other.O2String) return false;
      if (O1Case != other.O1Case) return false;
      if (O2Case != other.O2Case) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (PlainInt32 != 0) hash ^= PlainInt32.GetHashCode();
      if (o1Case_ == O1OneofCase.O1String) hash ^= O1String.GetHashCode();
      if (o1Case_ == O1OneofCase.O1Int32) hash ^= O1Int32.GetHashCode();
      if (PlainString.Length != 0) hash ^= PlainString.GetHashCode();
      if (o2Case_ == O2OneofCase.O2Int32) hash ^= O2Int32.GetHashCode();
      if (o2Case_ == O2OneofCase.O2String) hash ^= O2String.GetHashCode();
      hash ^= (int) o1Case_;
      hash ^= (int) o2Case_;
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (PlainString.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(PlainString);
      }
      if (o1Case_ == O1OneofCase.O1String) {
        output.WriteRawTag(18);
        output.WriteString(O1String);
      }
      if (o2Case_ == O2OneofCase.O2String) {
        output.WriteRawTag(26);
        output.WriteString(O2String);
      }
      if (PlainInt32 != 0) {
        output.WriteRawTag(32);
        output.WriteInt32(PlainInt32);
      }
      if (o1Case_ == O1OneofCase.O1Int32) {
        output.WriteRawTag(40);
        output.WriteInt32(O1Int32);
      }
      if (o2Case_ == O2OneofCase.O2Int32) {
        output.WriteRawTag(48);
        output.WriteInt32(O2Int32);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (PlainInt32 != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(PlainInt32);
      }
      if (o1Case_ == O1OneofCase.O1String) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(O1String);
      }
      if (o1Case_ == O1OneofCase.O1Int32) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(O1Int32);
      }
      if (PlainString.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(PlainString);
      }
      if (o2Case_ == O2OneofCase.O2Int32) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(O2Int32);
      }
      if (o2Case_ == O2OneofCase.O2String) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(O2String);
      }
      return size;
    }

    public void MergeFrom(TestJsonFieldOrdering other) {
      if (other == null) {
        return;
      }
      if (other.PlainInt32 != 0) {
        PlainInt32 = other.PlainInt32;
      }
      if (other.PlainString.Length != 0) {
        PlainString = other.PlainString;
      }
      switch (other.O1Case) {
        case O1OneofCase.O1String:
          O1String = other.O1String;
          break;
        case O1OneofCase.O1Int32:
          O1Int32 = other.O1Int32;
          break;
      }

      switch (other.O2Case) {
        case O2OneofCase.O2Int32:
          O2Int32 = other.O2Int32;
          break;
        case O2OneofCase.O2String:
          O2String = other.O2String;
          break;
      }

    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            PlainString = input.ReadString();
            break;
          }
          case 18: {
            O1String = input.ReadString();
            break;
          }
          case 26: {
            O2String = input.ReadString();
            break;
          }
          case 32: {
            PlainInt32 = input.ReadInt32();
            break;
          }
          case 40: {
            O1Int32 = input.ReadInt32();
            break;
          }
          case 48: {
            O2Int32 = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
