// <auto-generated>
//     Generated by the protocol buffer compiler.  DO NOT EDIT!
//     source: grpc/reflection/v1alpha/reflection.proto
// </auto-generated>
#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());
    private pb::UnknownFieldSet _unknownFields;
    [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;
      }

      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [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 Equals(_unknownFields, other._unknownFields);
    }

    [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_;
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (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);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [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);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      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:
          if (FileContainingExtension == null) {
            FileContainingExtension = new global::Grpc.Reflection.V1Alpha.ExtensionRequest();
          }
          FileContainingExtension.MergeFrom(other.FileContainingExtension);
          break;
        case MessageRequestOneofCase.AllExtensionNumbersOfType:
          AllExtensionNumbersOfType = other.AllExtensionNumbersOfType;
          break;
        case MessageRequestOneofCase.ListServices:
          ListServices = other.ListServices;
          break;
      }

      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            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());
    private pb::UnknownFieldSet _unknownFields;
    [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_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [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 Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ContainingType.Length != 0) hash ^= ContainingType.GetHashCode();
      if (ExtensionNumber != 0) hash ^= ExtensionNumber.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [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);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      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;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            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());
    private pb::UnknownFieldSet _unknownFields;
    [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;
      }

      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [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 Equals(_unknownFields, other._unknownFields);
    }

    [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_;
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (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);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [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);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      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:
          if (FileDescriptorResponse == null) {
            FileDescriptorResponse = new global::Grpc.Reflection.V1Alpha.FileDescriptorResponse();
          }
          FileDescriptorResponse.MergeFrom(other.FileDescriptorResponse);
          break;
        case MessageResponseOneofCase.AllExtensionNumbersResponse:
          if (AllExtensionNumbersResponse == null) {
            AllExtensionNumbersResponse = new global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse();
          }
          AllExtensionNumbersResponse.MergeFrom(other.AllExtensionNumbersResponse);
          break;
        case MessageResponseOneofCase.ListServicesResponse:
          if (ListServicesResponse == null) {
            ListServicesResponse = new global::Grpc.Reflection.V1Alpha.ListServiceResponse();
          }
          ListServicesResponse.MergeFrom(other.ListServicesResponse);
          break;
        case MessageResponseOneofCase.ErrorResponse:
          if (ErrorResponse == null) {
            ErrorResponse = new global::Grpc.Reflection.V1Alpha.ErrorResponse();
          }
          ErrorResponse.MergeFrom(other.ErrorResponse);
          break;
      }

      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            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());
    private pb::UnknownFieldSet _unknownFields;
    [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();
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [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 Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= fileDescriptorProto_.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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);
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            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());
    private pb::UnknownFieldSet _unknownFields;
    [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();
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [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 Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (BaseTypeName.Length != 0) hash ^= BaseTypeName.GetHashCode();
      hash ^= extensionNumber_.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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);
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [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);
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      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_);
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            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());
    private pb::UnknownFieldSet _unknownFields;
    [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();
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [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 Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= service_.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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);
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            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());
    private pb::UnknownFieldSet _unknownFields;
    [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_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [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 Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Name.Length != 0) hash ^= Name.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            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());
    private pb::UnknownFieldSet _unknownFields;
    [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_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [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 Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ErrorCode != 0) hash ^= ErrorCode.GetHashCode();
      if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [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);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      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;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

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

  }

  #endregion

}

#endregion Designer generated code
