// <auto-generated>
//     Generated by the protocol buffer compiler.  DO NOT EDIT!
//     source: google/protobuf/json/json_enumval_custom_string.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021, 8981
#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 JsonEnumvalCustomString {

  /// <summary>Holder for reflection information generated from google/protobuf/json/json_enumval_custom_string.proto</summary>
  public static partial class JsonEnumvalCustomStringReflection {

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

    static JsonEnumvalCustomStringReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "CjVnb29nbGUvcHJvdG9idWYvanNvbi9qc29uX2VudW12YWxfY3VzdG9tX3N0",
            "cmluZy5wcm90bxIaanNvbl9lbnVtdmFsX2N1c3RvbV9zdHJpbmcaImdvb2ds",
            "ZS9wcm90b2J1Zi9qc29uX29wdGlvbnMucHJvdG8ihgIKBktuaWdodBIwCgVh",
            "cm1vchgBIAEoDjIhLmpzb25fZW51bXZhbF9jdXN0b21fc3RyaW5nLkFybW9y",
            "EjEKBmFybW9ycxgCIAMoDjIhLmpzb25fZW51bXZhbF9jdXN0b21fc3RyaW5n",
            "LkFybW9yEkMKCWFybW9yX21hcBgDIAMoCzIwLmpzb25fZW51bXZhbF9jdXN0",
            "b21fc3RyaW5nLktuaWdodC5Bcm1vck1hcEVudHJ5GlIKDUFybW9yTWFwRW50",
            "cnkSCwoDa2V5GAEgASgJEjAKBXZhbHVlGAIgASgOMiEuanNvbl9lbnVtdmFs",
            "X2N1c3RvbV9zdHJpbmcuQXJtb3I6AjgBKtgCCgVBcm1vchIRCg1BUk1PUl9V",
            "TktOT1dOEAASIwoQQVJNT1JfR1JFQVRfSEVMTRABGg2yPgoKCGdyOCBoZWxt",
            "EhAKDEFSTU9SX0dPUkdFVBACEhwKDkFSTU9SX0dBVU5UTEVUEAMaCLI+BQoD",
            "YSJiEh0KC0FSTU9SX1BMQVRFEAQaDLI+CQoHInBsYXRlIhIVCgpBUk1PUl9D",
            "T0lGEAUaBbI+AgoAEiMKDkFSTU9SX1BBVUxEUk9OEAYaD7I+DAoKcAlhdWwK",
            "ZHJvbhIfCg1BUk1PUl9TQUJBVE9OEAcaDLI+CQoHc2FiYXRvbhIgCg5BUk1P",
            "Ul9TT0xMRVJFVBAHGgyyPgkKB3NhYmF0b24SHgoSQVJNT1JfSEFDSElfTUFJ",
            "X0RPEAgaBrI+AwoBOBIlCg1BUk1PUl9HUkVBVkVTEAkaErI+DwoNQVJNT1Jf",
            "R1JFQVZFUxoCEAFiCGVkaXRpb25zcOoH"));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { global::Pb.JsonOptionsReflection.Descriptor, },
          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::JsonEnumvalCustomString.Armor), }, null, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::JsonEnumvalCustomString.Knight), global::JsonEnumvalCustomString.Knight.Parser, new[]{ "Armor", "Armors", "ArmorMap" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, })
          }));
    }
    #endregion

  }
  #region Enums
  public enum Armor {
    [pbr::OriginalName("ARMOR_UNKNOWN")] Unknown = 0,
    [pbr::OriginalName("ARMOR_GREAT_HELM")] GreatHelm = 1,
    [pbr::OriginalName("ARMOR_GORGET")] Gorget = 2,
    [pbr::OriginalName("ARMOR_GAUNTLET")] Gauntlet = 3,
    [pbr::OriginalName("ARMOR_PLATE")] Plate = 4,
    [pbr::OriginalName("ARMOR_COIF")] Coif = 5,
    [pbr::OriginalName("ARMOR_PAULDRON")] Pauldron = 6,
    [pbr::OriginalName("ARMOR_SABATON")] Sabaton = 7,
    [pbr::OriginalName("ARMOR_SOLLERET", PreferredAlias = false)] Solleret = 7,
    [pbr::OriginalName("ARMOR_HACHI_MAI_DO")] HachiMaiDo = 8,
    [pbr::OriginalName("ARMOR_GREAVES")] Greaves = 9,
  }

  #endregion

  #region Messages
  [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
  public sealed partial class Knight : pb::IMessage<Knight>
  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
      , pb::IBufferMessage
  #endif
  {
    private static readonly pb::MessageParser<Knight> _parser = new pb::MessageParser<Knight>(() => new Knight());
    private pb::UnknownFieldSet _unknownFields;
    private int _hasBits0;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public static pb::MessageParser<Knight> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::JsonEnumvalCustomString.JsonEnumvalCustomStringReflection.Descriptor.MessageTypes[0]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public Knight() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public Knight(Knight other) : this() {
      _hasBits0 = other._hasBits0;
      armor_ = other.armor_;
      armors_ = other.armors_.Clone();
      armorMap_ = other.armorMap_.Clone();
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public Knight Clone() {
      return new Knight(this);
    }

    /// <summary>Field number for the "armor" field.</summary>
    public const int ArmorFieldNumber = 1;
    private readonly static global::JsonEnumvalCustomString.Armor ArmorDefaultValue = global::JsonEnumvalCustomString.Armor.Unknown;

    private global::JsonEnumvalCustomString.Armor armor_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public global::JsonEnumvalCustomString.Armor Armor {
      get { if ((_hasBits0 & 1) != 0) { return armor_; } else { return ArmorDefaultValue; } }
      set {
        _hasBits0 |= 1;
        armor_ = value;
      }
    }
    /// <summary>Gets whether the "armor" field is set</summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public bool HasArmor {
      get { return (_hasBits0 & 1) != 0; }
    }
    /// <summary>Clears the value of the "armor" field</summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public void ClearArmor() {
      _hasBits0 &= ~1;
    }

    /// <summary>Field number for the "armors" field.</summary>
    public const int ArmorsFieldNumber = 2;
    private static readonly pb::FieldCodec<global::JsonEnumvalCustomString.Armor> _repeated_armors_codec
        = pb::FieldCodec.ForEnum(18, x => (int) x, x => (global::JsonEnumvalCustomString.Armor) x);
    private readonly pbc::RepeatedField<global::JsonEnumvalCustomString.Armor> armors_ = new pbc::RepeatedField<global::JsonEnumvalCustomString.Armor>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public pbc::RepeatedField<global::JsonEnumvalCustomString.Armor> Armors {
      get { return armors_; }
    }

    /// <summary>Field number for the "armor_map" field.</summary>
    public const int ArmorMapFieldNumber = 3;
    private static readonly pbc::MapField<string, global::JsonEnumvalCustomString.Armor>.Codec _map_armorMap_codec
        = new pbc::MapField<string, global::JsonEnumvalCustomString.Armor>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::JsonEnumvalCustomString.Armor) x, global::JsonEnumvalCustomString.Armor.Unknown), 26);
    private readonly pbc::MapField<string, global::JsonEnumvalCustomString.Armor> armorMap_ = new pbc::MapField<string, global::JsonEnumvalCustomString.Armor>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public pbc::MapField<string, global::JsonEnumvalCustomString.Armor> ArmorMap {
      get { return armorMap_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public override bool Equals(object other) {
      return Equals(other as Knight);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public bool Equals(Knight other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Armor != other.Armor) return false;
      if(!armors_.Equals(other.armors_)) return false;
      if (!ArmorMap.Equals(other.ArmorMap)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public override int GetHashCode() {
      int hash = 1;
      if (HasArmor) hash ^= Armor.GetHashCode();
      hash ^= armors_.GetHashCode();
      hash ^= ArmorMap.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public void WriteTo(pb::CodedOutputStream output) {
    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
      output.WriteRawMessage(this);
    #else
      if (HasArmor) {
        output.WriteRawTag(8);
        output.WriteEnum((int) Armor);
      }
      armors_.WriteTo(output, _repeated_armors_codec);
      armorMap_.WriteTo(output, _map_armorMap_codec);
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    #endif
    }

    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
      if (HasArmor) {
        output.WriteRawTag(8);
        output.WriteEnum((int) Armor);
      }
      armors_.WriteTo(ref output, _repeated_armors_codec);
      armorMap_.WriteTo(ref output, _map_armorMap_codec);
      if (_unknownFields != null) {
        _unknownFields.WriteTo(ref output);
      }
    }
    #endif

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public int CalculateSize() {
      int size = 0;
      if (HasArmor) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Armor);
      }
      size += armors_.CalculateSize(_repeated_armors_codec);
      size += armorMap_.CalculateSize(_map_armorMap_codec);
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public void MergeFrom(Knight other) {
      if (other == null) {
        return;
      }
      if (other.HasArmor) {
        Armor = other.Armor;
      }
      armors_.Add(other.armors_);
      armorMap_.MergeFrom(other.armorMap_);
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public void MergeFrom(pb::CodedInputStream input) {
    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
      input.ReadRawMessage(this);
    #else
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
      if ((tag & 7) == 4) {
        // Abort on any end group tag.
        return;
      }
      switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 8: {
            Armor = (global::JsonEnumvalCustomString.Armor) input.ReadEnum();
            break;
          }
          case 18:
          case 16: {
            armors_.AddEntriesFrom(input, _repeated_armors_codec);
            break;
          }
          case 26: {
            armorMap_.AddEntriesFrom(input, _map_armorMap_codec);
            break;
          }
        }
      }
    #endif
    }

    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
      if ((tag & 7) == 4) {
        // Abort on any end group tag.
        return;
      }
      switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
            break;
          case 8: {
            Armor = (global::JsonEnumvalCustomString.Armor) input.ReadEnum();
            break;
          }
          case 18:
          case 16: {
            armors_.AddEntriesFrom(ref input, _repeated_armors_codec);
            break;
          }
          case 26: {
            armorMap_.AddEntriesFrom(ref input, _map_armorMap_codec);
            break;
          }
        }
      }
    }
    #endif

  }

  #endregion

}

#endregion Designer generated code
