// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: grpc/reflection/v1alpha/reflection.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 Grpc.Reflection.V1Alpha {

  /// <summary>Holder for reflection information generated from grpc/reflection/v1alpha/reflection.proto</summary>
  public static partial class ReflectionReflection {

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

    static ReflectionReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "CihncnBjL3JlZmxlY3Rpb24vdjFhbHBoYS9yZWZsZWN0aW9uLnByb3RvEhdn",
            "cnBjLnJlZmxlY3Rpb24udjFhbHBoYSKKAgoXU2VydmVyUmVmbGVjdGlvblJl",
            "cXVlc3QSDAoEaG9zdBgBIAEoCRIaChBmaWxlX2J5X2ZpbGVuYW1lGAMgASgJ",
            "SAASIAoWZmlsZV9jb250YWluaW5nX3N5bWJvbBgEIAEoCUgAEk4KGWZpbGVf",
            "Y29udGFpbmluZ19leHRlbnNpb24YBSABKAsyKS5ncnBjLnJlZmxlY3Rpb24u",
            "djFhbHBoYS5FeHRlbnNpb25SZXF1ZXN0SAASJwodYWxsX2V4dGVuc2lvbl9u",
            "dW1iZXJzX29mX3R5cGUYBiABKAlIABIXCg1saXN0X3NlcnZpY2VzGAcgASgJ",
            "SABCEQoPbWVzc2FnZV9yZXF1ZXN0IkUKEEV4dGVuc2lvblJlcXVlc3QSFwoP",
            "Y29udGFpbmluZ190eXBlGAEgASgJEhgKEGV4dGVuc2lvbl9udW1iZXIYAiAB",
            "KAUi0QMKGFNlcnZlclJlZmxlY3Rpb25SZXNwb25zZRISCgp2YWxpZF9ob3N0",
            "GAEgASgJEkoKEG9yaWdpbmFsX3JlcXVlc3QYAiABKAsyMC5ncnBjLnJlZmxl",
            "Y3Rpb24udjFhbHBoYS5TZXJ2ZXJSZWZsZWN0aW9uUmVxdWVzdBJTChhmaWxl",
            "X2Rlc2NyaXB0b3JfcmVzcG9uc2UYBCABKAsyLy5ncnBjLnJlZmxlY3Rpb24u",
            "djFhbHBoYS5GaWxlRGVzY3JpcHRvclJlc3BvbnNlSAASWgoeYWxsX2V4dGVu",
            "c2lvbl9udW1iZXJzX3Jlc3BvbnNlGAUgASgLMjAuZ3JwYy5yZWZsZWN0aW9u",
            "LnYxYWxwaGEuRXh0ZW5zaW9uTnVtYmVyUmVzcG9uc2VIABJOChZsaXN0X3Nl",
            "cnZpY2VzX3Jlc3BvbnNlGAYgASgLMiwuZ3JwYy5yZWZsZWN0aW9uLnYxYWxw",
            "aGEuTGlzdFNlcnZpY2VSZXNwb25zZUgAEkAKDmVycm9yX3Jlc3BvbnNlGAcg",
            "ASgLMiYuZ3JwYy5yZWZsZWN0aW9uLnYxYWxwaGEuRXJyb3JSZXNwb25zZUgA",
            "QhIKEG1lc3NhZ2VfcmVzcG9uc2UiNwoWRmlsZURlc2NyaXB0b3JSZXNwb25z",
            "ZRIdChVmaWxlX2Rlc2NyaXB0b3JfcHJvdG8YASADKAwiSwoXRXh0ZW5zaW9u",
            "TnVtYmVyUmVzcG9uc2USFgoOYmFzZV90eXBlX25hbWUYASABKAkSGAoQZXh0",
            "ZW5zaW9uX251bWJlchgCIAMoBSJQChNMaXN0U2VydmljZVJlc3BvbnNlEjkK",
            "B3NlcnZpY2UYASADKAsyKC5ncnBjLnJlZmxlY3Rpb24udjFhbHBoYS5TZXJ2",
            "aWNlUmVzcG9uc2UiHwoPU2VydmljZVJlc3BvbnNlEgwKBG5hbWUYASABKAki",
            "OgoNRXJyb3JSZXNwb25zZRISCgplcnJvcl9jb2RlGAEgASgFEhUKDWVycm9y",
            "X21lc3NhZ2UYAiABKAkykwEKEFNlcnZlclJlZmxlY3Rpb24SfwoUU2VydmVy",
            "UmVmbGVjdGlvbkluZm8SMC5ncnBjLnJlZmxlY3Rpb24udjFhbHBoYS5TZXJ2",
            "ZXJSZWZsZWN0aW9uUmVxdWVzdBoxLmdycGMucmVmbGVjdGlvbi52MWFscGhh",
            "LlNlcnZlclJlZmxlY3Rpb25SZXNwb25zZSgBMAFiBnByb3RvMw=="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { },
          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServerReflectionRequest), global::Grpc.Reflection.V1Alpha.ServerReflectionRequest.Parser, new[]{ "Host", "FileByFilename", "FileContainingSymbol", "FileContainingExtension", "AllExtensionNumbersOfType", "ListServices" }, new[]{ "MessageRequest" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ExtensionRequest), global::Grpc.Reflection.V1Alpha.ExtensionRequest.Parser, new[]{ "ContainingType", "ExtensionNumber" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServerReflectionResponse), global::Grpc.Reflection.V1Alpha.ServerReflectionResponse.Parser, new[]{ "ValidHost", "OriginalRequest", "FileDescriptorResponse", "AllExtensionNumbersResponse", "ListServicesResponse", "ErrorResponse" }, new[]{ "MessageResponse" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.FileDescriptorResponse), global::Grpc.Reflection.V1Alpha.FileDescriptorResponse.Parser, new[]{ "FileDescriptorProto" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse), global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse.Parser, new[]{ "BaseTypeName", "ExtensionNumber" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ListServiceResponse), global::Grpc.Reflection.V1Alpha.ListServiceResponse.Parser, new[]{ "Service" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServiceResponse), global::Grpc.Reflection.V1Alpha.ServiceResponse.Parser, new[]{ "Name" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ErrorResponse), global::Grpc.Reflection.V1Alpha.ErrorResponse.Parser, new[]{ "ErrorCode", "ErrorMessage" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Messages
  /// <summary>
  /// The message sent by the client when calling ServerReflectionInfo method.
  /// </summary>
  public sealed partial class ServerReflectionRequest : pb::IMessage<ServerReflectionRequest> {
    private static readonly pb::MessageParser<ServerReflectionRequest> _parser = new pb::MessageParser<ServerReflectionRequest>(() => new ServerReflectionRequest());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ServerReflectionRequest> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[0]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerReflectionRequest() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerReflectionRequest(ServerReflectionRequest other) : this() {
      host_ = other.host_;
      switch (other.MessageRequestCase) {
        case MessageRequestOneofCase.FileByFilename:
          FileByFilename = other.FileByFilename;
          break;
        case MessageRequestOneofCase.FileContainingSymbol:
          FileContainingSymbol = other.FileContainingSymbol;
          break;
        case MessageRequestOneofCase.FileContainingExtension:
          FileContainingExtension = other.FileContainingExtension.Clone();
          break;
        case MessageRequestOneofCase.AllExtensionNumbersOfType:
          AllExtensionNumbersOfType = other.AllExtensionNumbersOfType;
          break;
        case MessageRequestOneofCase.ListServices:
          ListServices = other.ListServices;
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerReflectionRequest Clone() {
      return new ServerReflectionRequest(this);
    }

    /// <summary>Field number for the "host" field.</summary>
    public const int HostFieldNumber = 1;
    private string host_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Host {
      get { return host_; }
      set {
        host_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "file_by_filename" field.</summary>
    public const int FileByFilenameFieldNumber = 3;
    /// <summary>
    /// Find a proto file by the file name.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string FileByFilename {
      get { return messageRequestCase_ == MessageRequestOneofCase.FileByFilename ? (string) messageRequest_ : ""; }
      set {
        messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        messageRequestCase_ = MessageRequestOneofCase.FileByFilename;
      }
    }

    /// <summary>Field number for the "file_containing_symbol" field.</summary>
    public const int FileContainingSymbolFieldNumber = 4;
    /// <summary>
    /// Find the proto file that declares the given fully-qualified symbol name.
    /// This field should be a fully-qualified symbol name
    /// (e.g. &lt;package>.&lt;service>[.&lt;method>] or &lt;package>.&lt;type>).
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string FileContainingSymbol {
      get { return messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol ? (string) messageRequest_ : ""; }
      set {
        messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        messageRequestCase_ = MessageRequestOneofCase.FileContainingSymbol;
      }
    }

    /// <summary>Field number for the "file_containing_extension" field.</summary>
    public const int FileContainingExtensionFieldNumber = 5;
    /// <summary>
    /// Find the proto file which defines an extension extending the given
    /// message type with the given field number.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Reflection.V1Alpha.ExtensionRequest FileContainingExtension {
      get { return messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension ? (global::Grpc.Reflection.V1Alpha.ExtensionRequest) messageRequest_ : null; }
      set {
        messageRequest_ = value;
        messageRequestCase_ = value == null ? MessageRequestOneofCase.None : MessageRequestOneofCase.FileContainingExtension;
      }
    }

    /// <summary>Field number for the "all_extension_numbers_of_type" field.</summary>
    public const int AllExtensionNumbersOfTypeFieldNumber = 6;
    /// <summary>
    /// Finds the tag numbers used by all known extensions of the given message
    /// type, and appends them to ExtensionNumberResponse in an undefined order.
    /// Its corresponding method is best-effort: it's not guaranteed that the
    /// reflection service will implement this method, and it's not guaranteed
    /// that this method will provide all extensions. Returns
    /// StatusCode::UNIMPLEMENTED if it's not implemented.
    /// This field should be a fully-qualified type name. The format is
    /// &lt;package>.&lt;type>
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string AllExtensionNumbersOfType {
      get { return messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType ? (string) messageRequest_ : ""; }
      set {
        messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        messageRequestCase_ = MessageRequestOneofCase.AllExtensionNumbersOfType;
      }
    }

    /// <summary>Field number for the "list_services" field.</summary>
    public const int ListServicesFieldNumber = 7;
    /// <summary>
    /// List the full names of registered services. The content will not be
    /// checked.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ListServices {
      get { return messageRequestCase_ == MessageRequestOneofCase.ListServices ? (string) messageRequest_ : ""; }
      set {
        messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        messageRequestCase_ = MessageRequestOneofCase.ListServices;
      }
    }

    private object messageRequest_;
    /// <summary>Enum of possible cases for the "message_request" oneof.</summary>
    public enum MessageRequestOneofCase {
      None = 0,
      FileByFilename = 3,
      FileContainingSymbol = 4,
      FileContainingExtension = 5,
      AllExtensionNumbersOfType = 6,
      ListServices = 7,
    }
    private MessageRequestOneofCase messageRequestCase_ = MessageRequestOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public MessageRequestOneofCase MessageRequestCase {
      get { return messageRequestCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearMessageRequest() {
      messageRequestCase_ = MessageRequestOneofCase.None;
      messageRequest_ = null;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ServerReflectionRequest);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ServerReflectionRequest other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Host != other.Host) return false;
      if (FileByFilename != other.FileByFilename) return false;
      if (FileContainingSymbol != other.FileContainingSymbol) return false;
      if (!object.Equals(FileContainingExtension, other.FileContainingExtension)) return false;
      if (AllExtensionNumbersOfType != other.AllExtensionNumbersOfType) return false;
      if (ListServices != other.ListServices) return false;
      if (MessageRequestCase != other.MessageRequestCase) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Host.Length != 0) hash ^= Host.GetHashCode();
      if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) hash ^= FileByFilename.GetHashCode();
      if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) hash ^= FileContainingSymbol.GetHashCode();
      if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) hash ^= FileContainingExtension.GetHashCode();
      if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) hash ^= AllExtensionNumbersOfType.GetHashCode();
      if (messageRequestCase_ == MessageRequestOneofCase.ListServices) hash ^= ListServices.GetHashCode();
      hash ^= (int) messageRequestCase_;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Host.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Host);
      }
      if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) {
        output.WriteRawTag(26);
        output.WriteString(FileByFilename);
      }
      if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) {
        output.WriteRawTag(34);
        output.WriteString(FileContainingSymbol);
      }
      if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) {
        output.WriteRawTag(42);
        output.WriteMessage(FileContainingExtension);
      }
      if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) {
        output.WriteRawTag(50);
        output.WriteString(AllExtensionNumbersOfType);
      }
      if (messageRequestCase_ == MessageRequestOneofCase.ListServices) {
        output.WriteRawTag(58);
        output.WriteString(ListServices);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Host.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Host);
      }
      if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(FileByFilename);
      }
      if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(FileContainingSymbol);
      }
      if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(FileContainingExtension);
      }
      if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(AllExtensionNumbersOfType);
      }
      if (messageRequestCase_ == MessageRequestOneofCase.ListServices) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ListServices);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ServerReflectionRequest other) {
      if (other == null) {
        return;
      }
      if (other.Host.Length != 0) {
        Host = other.Host;
      }
      switch (other.MessageRequestCase) {
        case MessageRequestOneofCase.FileByFilename:
          FileByFilename = other.FileByFilename;
          break;
        case MessageRequestOneofCase.FileContainingSymbol:
          FileContainingSymbol = other.FileContainingSymbol;
          break;
        case MessageRequestOneofCase.FileContainingExtension:
          FileContainingExtension = other.FileContainingExtension;
          break;
        case MessageRequestOneofCase.AllExtensionNumbersOfType:
          AllExtensionNumbersOfType = other.AllExtensionNumbersOfType;
          break;
        case MessageRequestOneofCase.ListServices:
          ListServices = other.ListServices;
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            Host = input.ReadString();
            break;
          }
          case 26: {
            FileByFilename = input.ReadString();
            break;
          }
          case 34: {
            FileContainingSymbol = input.ReadString();
            break;
          }
          case 42: {
            global::Grpc.Reflection.V1Alpha.ExtensionRequest subBuilder = new global::Grpc.Reflection.V1Alpha.ExtensionRequest();
            if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) {
              subBuilder.MergeFrom(FileContainingExtension);
            }
            input.ReadMessage(subBuilder);
            FileContainingExtension = subBuilder;
            break;
          }
          case 50: {
            AllExtensionNumbersOfType = input.ReadString();
            break;
          }
          case 58: {
            ListServices = input.ReadString();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// The type name and extension number sent by the client when requesting
  /// file_containing_extension.
  /// </summary>
  public sealed partial class ExtensionRequest : pb::IMessage<ExtensionRequest> {
    private static readonly pb::MessageParser<ExtensionRequest> _parser = new pb::MessageParser<ExtensionRequest>(() => new ExtensionRequest());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ExtensionRequest> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[1]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ExtensionRequest() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ExtensionRequest(ExtensionRequest other) : this() {
      containingType_ = other.containingType_;
      extensionNumber_ = other.extensionNumber_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ExtensionRequest Clone() {
      return new ExtensionRequest(this);
    }

    /// <summary>Field number for the "containing_type" field.</summary>
    public const int ContainingTypeFieldNumber = 1;
    private string containingType_ = "";
    /// <summary>
    /// Fully-qualified type name. The format should be &lt;package>.&lt;type>
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ContainingType {
      get { return containingType_; }
      set {
        containingType_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "extension_number" field.</summary>
    public const int ExtensionNumberFieldNumber = 2;
    private int extensionNumber_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ExtensionNumber {
      get { return extensionNumber_; }
      set {
        extensionNumber_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ExtensionRequest);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ExtensionRequest other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ContainingType != other.ContainingType) return false;
      if (ExtensionNumber != other.ExtensionNumber) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ContainingType.Length != 0) hash ^= ContainingType.GetHashCode();
      if (ExtensionNumber != 0) hash ^= ExtensionNumber.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (ContainingType.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(ContainingType);
      }
      if (ExtensionNumber != 0) {
        output.WriteRawTag(16);
        output.WriteInt32(ExtensionNumber);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (ContainingType.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ContainingType);
      }
      if (ExtensionNumber != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ExtensionNumber);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ExtensionRequest other) {
      if (other == null) {
        return;
      }
      if (other.ContainingType.Length != 0) {
        ContainingType = other.ContainingType;
      }
      if (other.ExtensionNumber != 0) {
        ExtensionNumber = other.ExtensionNumber;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            ContainingType = input.ReadString();
            break;
          }
          case 16: {
            ExtensionNumber = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// The message sent by the server to answer ServerReflectionInfo method.
  /// </summary>
  public sealed partial class ServerReflectionResponse : pb::IMessage<ServerReflectionResponse> {
    private static readonly pb::MessageParser<ServerReflectionResponse> _parser = new pb::MessageParser<ServerReflectionResponse>(() => new ServerReflectionResponse());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ServerReflectionResponse> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[2]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerReflectionResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerReflectionResponse(ServerReflectionResponse other) : this() {
      validHost_ = other.validHost_;
      OriginalRequest = other.originalRequest_ != null ? other.OriginalRequest.Clone() : null;
      switch (other.MessageResponseCase) {
        case MessageResponseOneofCase.FileDescriptorResponse:
          FileDescriptorResponse = other.FileDescriptorResponse.Clone();
          break;
        case MessageResponseOneofCase.AllExtensionNumbersResponse:
          AllExtensionNumbersResponse = other.AllExtensionNumbersResponse.Clone();
          break;
        case MessageResponseOneofCase.ListServicesResponse:
          ListServicesResponse = other.ListServicesResponse.Clone();
          break;
        case MessageResponseOneofCase.ErrorResponse:
          ErrorResponse = other.ErrorResponse.Clone();
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerReflectionResponse Clone() {
      return new ServerReflectionResponse(this);
    }

    /// <summary>Field number for the "valid_host" field.</summary>
    public const int ValidHostFieldNumber = 1;
    private string validHost_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ValidHost {
      get { return validHost_; }
      set {
        validHost_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "original_request" field.</summary>
    public const int OriginalRequestFieldNumber = 2;
    private global::Grpc.Reflection.V1Alpha.ServerReflectionRequest originalRequest_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Reflection.V1Alpha.ServerReflectionRequest OriginalRequest {
      get { return originalRequest_; }
      set {
        originalRequest_ = value;
      }
    }

    /// <summary>Field number for the "file_descriptor_response" field.</summary>
    public const int FileDescriptorResponseFieldNumber = 4;
    /// <summary>
    /// This message is used to answer file_by_filename, file_containing_symbol,
    /// file_containing_extension requests with transitive dependencies. As
    /// the repeated label is not allowed in oneof fields, we use a
    /// FileDescriptorResponse message to encapsulate the repeated fields.
    /// The reflection service is allowed to avoid sending FileDescriptorProtos
    /// that were previously sent in response to earlier requests in the stream.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Reflection.V1Alpha.FileDescriptorResponse FileDescriptorResponse {
      get { return messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse ? (global::Grpc.Reflection.V1Alpha.FileDescriptorResponse) messageResponse_ : null; }
      set {
        messageResponse_ = value;
        messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.FileDescriptorResponse;
      }
    }

    /// <summary>Field number for the "all_extension_numbers_response" field.</summary>
    public const int AllExtensionNumbersResponseFieldNumber = 5;
    /// <summary>
    /// This message is used to answer all_extension_numbers_of_type requst.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse AllExtensionNumbersResponse {
      get { return messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse ? (global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse) messageResponse_ : null; }
      set {
        messageResponse_ = value;
        messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.AllExtensionNumbersResponse;
      }
    }

    /// <summary>Field number for the "list_services_response" field.</summary>
    public const int ListServicesResponseFieldNumber = 6;
    /// <summary>
    /// This message is used to answer list_services request.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Reflection.V1Alpha.ListServiceResponse ListServicesResponse {
      get { return messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse ? (global::Grpc.Reflection.V1Alpha.ListServiceResponse) messageResponse_ : null; }
      set {
        messageResponse_ = value;
        messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.ListServicesResponse;
      }
    }

    /// <summary>Field number for the "error_response" field.</summary>
    public const int ErrorResponseFieldNumber = 7;
    /// <summary>
    /// This message is used when an error occurs.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Reflection.V1Alpha.ErrorResponse ErrorResponse {
      get { return messageResponseCase_ == MessageResponseOneofCase.ErrorResponse ? (global::Grpc.Reflection.V1Alpha.ErrorResponse) messageResponse_ : null; }
      set {
        messageResponse_ = value;
        messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.ErrorResponse;
      }
    }

    private object messageResponse_;
    /// <summary>Enum of possible cases for the "message_response" oneof.</summary>
    public enum MessageResponseOneofCase {
      None = 0,
      FileDescriptorResponse = 4,
      AllExtensionNumbersResponse = 5,
      ListServicesResponse = 6,
      ErrorResponse = 7,
    }
    private MessageResponseOneofCase messageResponseCase_ = MessageResponseOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public MessageResponseOneofCase MessageResponseCase {
      get { return messageResponseCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearMessageResponse() {
      messageResponseCase_ = MessageResponseOneofCase.None;
      messageResponse_ = null;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ServerReflectionResponse);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ServerReflectionResponse other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ValidHost != other.ValidHost) return false;
      if (!object.Equals(OriginalRequest, other.OriginalRequest)) return false;
      if (!object.Equals(FileDescriptorResponse, other.FileDescriptorResponse)) return false;
      if (!object.Equals(AllExtensionNumbersResponse, other.AllExtensionNumbersResponse)) return false;
      if (!object.Equals(ListServicesResponse, other.ListServicesResponse)) return false;
      if (!object.Equals(ErrorResponse, other.ErrorResponse)) return false;
      if (MessageResponseCase != other.MessageResponseCase) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ValidHost.Length != 0) hash ^= ValidHost.GetHashCode();
      if (originalRequest_ != null) hash ^= OriginalRequest.GetHashCode();
      if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) hash ^= FileDescriptorResponse.GetHashCode();
      if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) hash ^= AllExtensionNumbersResponse.GetHashCode();
      if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) hash ^= ListServicesResponse.GetHashCode();
      if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) hash ^= ErrorResponse.GetHashCode();
      hash ^= (int) messageResponseCase_;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (ValidHost.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(ValidHost);
      }
      if (originalRequest_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(OriginalRequest);
      }
      if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) {
        output.WriteRawTag(34);
        output.WriteMessage(FileDescriptorResponse);
      }
      if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) {
        output.WriteRawTag(42);
        output.WriteMessage(AllExtensionNumbersResponse);
      }
      if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) {
        output.WriteRawTag(50);
        output.WriteMessage(ListServicesResponse);
      }
      if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) {
        output.WriteRawTag(58);
        output.WriteMessage(ErrorResponse);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (ValidHost.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ValidHost);
      }
      if (originalRequest_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(OriginalRequest);
      }
      if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(FileDescriptorResponse);
      }
      if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(AllExtensionNumbersResponse);
      }
      if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ListServicesResponse);
      }
      if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ErrorResponse);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ServerReflectionResponse other) {
      if (other == null) {
        return;
      }
      if (other.ValidHost.Length != 0) {
        ValidHost = other.ValidHost;
      }
      if (other.originalRequest_ != null) {
        if (originalRequest_ == null) {
          originalRequest_ = new global::Grpc.Reflection.V1Alpha.ServerReflectionRequest();
        }
        OriginalRequest.MergeFrom(other.OriginalRequest);
      }
      switch (other.MessageResponseCase) {
        case MessageResponseOneofCase.FileDescriptorResponse:
          FileDescriptorResponse = other.FileDescriptorResponse;
          break;
        case MessageResponseOneofCase.AllExtensionNumbersResponse:
          AllExtensionNumbersResponse = other.AllExtensionNumbersResponse;
          break;
        case MessageResponseOneofCase.ListServicesResponse:
          ListServicesResponse = other.ListServicesResponse;
          break;
        case MessageResponseOneofCase.ErrorResponse:
          ErrorResponse = other.ErrorResponse;
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            ValidHost = input.ReadString();
            break;
          }
          case 18: {
            if (originalRequest_ == null) {
              originalRequest_ = new global::Grpc.Reflection.V1Alpha.ServerReflectionRequest();
            }
            input.ReadMessage(originalRequest_);
            break;
          }
          case 34: {
            global::Grpc.Reflection.V1Alpha.FileDescriptorResponse subBuilder = new global::Grpc.Reflection.V1Alpha.FileDescriptorResponse();
            if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) {
              subBuilder.MergeFrom(FileDescriptorResponse);
            }
            input.ReadMessage(subBuilder);
            FileDescriptorResponse = subBuilder;
            break;
          }
          case 42: {
            global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse();
            if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) {
              subBuilder.MergeFrom(AllExtensionNumbersResponse);
            }
            input.ReadMessage(subBuilder);
            AllExtensionNumbersResponse = subBuilder;
            break;
          }
          case 50: {
            global::Grpc.Reflection.V1Alpha.ListServiceResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ListServiceResponse();
            if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) {
              subBuilder.MergeFrom(ListServicesResponse);
            }
            input.ReadMessage(subBuilder);
            ListServicesResponse = subBuilder;
            break;
          }
          case 58: {
            global::Grpc.Reflection.V1Alpha.ErrorResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ErrorResponse();
            if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) {
              subBuilder.MergeFrom(ErrorResponse);
            }
            input.ReadMessage(subBuilder);
            ErrorResponse = subBuilder;
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Serialized FileDescriptorProto messages sent by the server answering
  /// a file_by_filename, file_containing_symbol, or file_containing_extension
  /// request.
  /// </summary>
  public sealed partial class FileDescriptorResponse : pb::IMessage<FileDescriptorResponse> {
    private static readonly pb::MessageParser<FileDescriptorResponse> _parser = new pb::MessageParser<FileDescriptorResponse>(() => new FileDescriptorResponse());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<FileDescriptorResponse> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[3]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public FileDescriptorResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public FileDescriptorResponse(FileDescriptorResponse other) : this() {
      fileDescriptorProto_ = other.fileDescriptorProto_.Clone();
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public FileDescriptorResponse Clone() {
      return new FileDescriptorResponse(this);
    }

    /// <summary>Field number for the "file_descriptor_proto" field.</summary>
    public const int FileDescriptorProtoFieldNumber = 1;
    private static readonly pb::FieldCodec<pb::ByteString> _repeated_fileDescriptorProto_codec
        = pb::FieldCodec.ForBytes(10);
    private readonly pbc::RepeatedField<pb::ByteString> fileDescriptorProto_ = new pbc::RepeatedField<pb::ByteString>();
    /// <summary>
    /// Serialized FileDescriptorProto messages. We avoid taking a dependency on
    /// descriptor.proto, which uses proto2 only features, by making them opaque
    /// bytes instead.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<pb::ByteString> FileDescriptorProto {
      get { return fileDescriptorProto_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as FileDescriptorResponse);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(FileDescriptorResponse other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if(!fileDescriptorProto_.Equals(other.fileDescriptorProto_)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= fileDescriptorProto_.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      fileDescriptorProto_.WriteTo(output, _repeated_fileDescriptorProto_codec);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      size += fileDescriptorProto_.CalculateSize(_repeated_fileDescriptorProto_codec);
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(FileDescriptorResponse other) {
      if (other == null) {
        return;
      }
      fileDescriptorProto_.Add(other.fileDescriptorProto_);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            fileDescriptorProto_.AddEntriesFrom(input, _repeated_fileDescriptorProto_codec);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// A list of extension numbers sent by the server answering
  /// all_extension_numbers_of_type request.
  /// </summary>
  public sealed partial class ExtensionNumberResponse : pb::IMessage<ExtensionNumberResponse> {
    private static readonly pb::MessageParser<ExtensionNumberResponse> _parser = new pb::MessageParser<ExtensionNumberResponse>(() => new ExtensionNumberResponse());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ExtensionNumberResponse> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[4]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ExtensionNumberResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ExtensionNumberResponse(ExtensionNumberResponse other) : this() {
      baseTypeName_ = other.baseTypeName_;
      extensionNumber_ = other.extensionNumber_.Clone();
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ExtensionNumberResponse Clone() {
      return new ExtensionNumberResponse(this);
    }

    /// <summary>Field number for the "base_type_name" field.</summary>
    public const int BaseTypeNameFieldNumber = 1;
    private string baseTypeName_ = "";
    /// <summary>
    /// Full name of the base type, including the package name. The format
    /// is &lt;package>.&lt;type>
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string BaseTypeName {
      get { return baseTypeName_; }
      set {
        baseTypeName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "extension_number" field.</summary>
    public const int ExtensionNumberFieldNumber = 2;
    private static readonly pb::FieldCodec<int> _repeated_extensionNumber_codec
        = pb::FieldCodec.ForInt32(18);
    private readonly pbc::RepeatedField<int> extensionNumber_ = new pbc::RepeatedField<int>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<int> ExtensionNumber {
      get { return extensionNumber_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ExtensionNumberResponse);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ExtensionNumberResponse other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (BaseTypeName != other.BaseTypeName) return false;
      if(!extensionNumber_.Equals(other.extensionNumber_)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (BaseTypeName.Length != 0) hash ^= BaseTypeName.GetHashCode();
      hash ^= extensionNumber_.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (BaseTypeName.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(BaseTypeName);
      }
      extensionNumber_.WriteTo(output, _repeated_extensionNumber_codec);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (BaseTypeName.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(BaseTypeName);
      }
      size += extensionNumber_.CalculateSize(_repeated_extensionNumber_codec);
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ExtensionNumberResponse other) {
      if (other == null) {
        return;
      }
      if (other.BaseTypeName.Length != 0) {
        BaseTypeName = other.BaseTypeName;
      }
      extensionNumber_.Add(other.extensionNumber_);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            BaseTypeName = input.ReadString();
            break;
          }
          case 18:
          case 16: {
            extensionNumber_.AddEntriesFrom(input, _repeated_extensionNumber_codec);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// A list of ServiceResponse sent by the server answering list_services request.
  /// </summary>
  public sealed partial class ListServiceResponse : pb::IMessage<ListServiceResponse> {
    private static readonly pb::MessageParser<ListServiceResponse> _parser = new pb::MessageParser<ListServiceResponse>(() => new ListServiceResponse());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ListServiceResponse> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[5]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ListServiceResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ListServiceResponse(ListServiceResponse other) : this() {
      service_ = other.service_.Clone();
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ListServiceResponse Clone() {
      return new ListServiceResponse(this);
    }

    /// <summary>Field number for the "service" field.</summary>
    public const int ServiceFieldNumber = 1;
    private static readonly pb::FieldCodec<global::Grpc.Reflection.V1Alpha.ServiceResponse> _repeated_service_codec
        = pb::FieldCodec.ForMessage(10, global::Grpc.Reflection.V1Alpha.ServiceResponse.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Reflection.V1Alpha.ServiceResponse> service_ = new pbc::RepeatedField<global::Grpc.Reflection.V1Alpha.ServiceResponse>();
    /// <summary>
    /// The information of each service may be expanded in the future, so we use
    /// ServiceResponse message to encapsulate it.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Reflection.V1Alpha.ServiceResponse> Service {
      get { return service_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ListServiceResponse);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ListServiceResponse other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if(!service_.Equals(other.service_)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= service_.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      service_.WriteTo(output, _repeated_service_codec);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      size += service_.CalculateSize(_repeated_service_codec);
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ListServiceResponse other) {
      if (other == null) {
        return;
      }
      service_.Add(other.service_);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            service_.AddEntriesFrom(input, _repeated_service_codec);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// The information of a single service used by ListServiceResponse to answer
  /// list_services request.
  /// </summary>
  public sealed partial class ServiceResponse : pb::IMessage<ServiceResponse> {
    private static readonly pb::MessageParser<ServiceResponse> _parser = new pb::MessageParser<ServiceResponse>(() => new ServiceResponse());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ServiceResponse> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[6]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServiceResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServiceResponse(ServiceResponse other) : this() {
      name_ = other.name_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServiceResponse Clone() {
      return new ServiceResponse(this);
    }

    /// <summary>Field number for the "name" field.</summary>
    public const int NameFieldNumber = 1;
    private string name_ = "";
    /// <summary>
    /// Full name of a registered service, including its package name. The format
    /// is &lt;package>.&lt;service>
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Name {
      get { return name_; }
      set {
        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ServiceResponse);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ServiceResponse other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Name != other.Name) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Name.Length != 0) hash ^= Name.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Name.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Name);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Name.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ServiceResponse other) {
      if (other == null) {
        return;
      }
      if (other.Name.Length != 0) {
        Name = other.Name;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            Name = input.ReadString();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// The error code and error message sent by the server when an error occurs.
  /// </summary>
  public sealed partial class ErrorResponse : pb::IMessage<ErrorResponse> {
    private static readonly pb::MessageParser<ErrorResponse> _parser = new pb::MessageParser<ErrorResponse>(() => new ErrorResponse());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ErrorResponse> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[7]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ErrorResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ErrorResponse(ErrorResponse other) : this() {
      errorCode_ = other.errorCode_;
      errorMessage_ = other.errorMessage_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ErrorResponse Clone() {
      return new ErrorResponse(this);
    }

    /// <summary>Field number for the "error_code" field.</summary>
    public const int ErrorCodeFieldNumber = 1;
    private int errorCode_;
    /// <summary>
    /// This field uses the error codes defined in grpc::StatusCode.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ErrorCode {
      get { return errorCode_; }
      set {
        errorCode_ = value;
      }
    }

    /// <summary>Field number for the "error_message" field.</summary>
    public const int ErrorMessageFieldNumber = 2;
    private string errorMessage_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ErrorMessage {
      get { return errorMessage_; }
      set {
        errorMessage_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ErrorResponse);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ErrorResponse other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ErrorCode != other.ErrorCode) return false;
      if (ErrorMessage != other.ErrorMessage) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ErrorCode != 0) hash ^= ErrorCode.GetHashCode();
      if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (ErrorCode != 0) {
        output.WriteRawTag(8);
        output.WriteInt32(ErrorCode);
      }
      if (ErrorMessage.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(ErrorMessage);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (ErrorCode != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ErrorCode);
      }
      if (ErrorMessage.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ErrorMessage);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ErrorResponse other) {
      if (other == null) {
        return;
      }
      if (other.ErrorCode != 0) {
        ErrorCode = other.ErrorCode;
      }
      if (other.ErrorMessage.Length != 0) {
        ErrorMessage = other.ErrorMessage;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            ErrorCode = input.ReadInt32();
            break;
          }
          case 18: {
            ErrorMessage = input.ReadString();
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
