// <auto-generated>
//     Generated by the protocol buffer compiler.  DO NOT EDIT!
//     source: src/proto/grpc/testing/messages.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.Testing {

  /// <summary>Holder for reflection information generated from src/proto/grpc/testing/messages.proto</summary>
  public static partial class MessagesReflection {

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

    static MessagesReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "CiVzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL21lc3NhZ2VzLnByb3RvEgxncnBj",
            "LnRlc3RpbmciGgoJQm9vbFZhbHVlEg0KBXZhbHVlGAEgASgIIkAKB1BheWxv",
            "YWQSJwoEdHlwZRgBIAEoDjIZLmdycGMudGVzdGluZy5QYXlsb2FkVHlwZRIM",
            "CgRib2R5GAIgASgMIisKCkVjaG9TdGF0dXMSDAoEY29kZRgBIAEoBRIPCgdt",
            "ZXNzYWdlGAIgASgJIs4CCg1TaW1wbGVSZXF1ZXN0EjAKDXJlc3BvbnNlX3R5",
            "cGUYASABKA4yGS5ncnBjLnRlc3RpbmcuUGF5bG9hZFR5cGUSFQoNcmVzcG9u",
            "c2Vfc2l6ZRgCIAEoBRImCgdwYXlsb2FkGAMgASgLMhUuZ3JwYy50ZXN0aW5n",
            "LlBheWxvYWQSFQoNZmlsbF91c2VybmFtZRgEIAEoCBIYChBmaWxsX29hdXRo",
            "X3Njb3BlGAUgASgIEjQKE3Jlc3BvbnNlX2NvbXByZXNzZWQYBiABKAsyFy5n",
            "cnBjLnRlc3RpbmcuQm9vbFZhbHVlEjEKD3Jlc3BvbnNlX3N0YXR1cxgHIAEo",
            "CzIYLmdycGMudGVzdGluZy5FY2hvU3RhdHVzEjIKEWV4cGVjdF9jb21wcmVz",
            "c2VkGAggASgLMhcuZ3JwYy50ZXN0aW5nLkJvb2xWYWx1ZSJfCg5TaW1wbGVS",
            "ZXNwb25zZRImCgdwYXlsb2FkGAEgASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxv",
            "YWQSEAoIdXNlcm5hbWUYAiABKAkSEwoLb2F1dGhfc2NvcGUYAyABKAkidwoZ",
            "U3RyZWFtaW5nSW5wdXRDYWxsUmVxdWVzdBImCgdwYXlsb2FkGAEgASgLMhUu",
            "Z3JwYy50ZXN0aW5nLlBheWxvYWQSMgoRZXhwZWN0X2NvbXByZXNzZWQYAiAB",
            "KAsyFy5ncnBjLnRlc3RpbmcuQm9vbFZhbHVlIj0KGlN0cmVhbWluZ0lucHV0",
            "Q2FsbFJlc3BvbnNlEh8KF2FnZ3JlZ2F0ZWRfcGF5bG9hZF9zaXplGAEgASgF",
            "ImQKElJlc3BvbnNlUGFyYW1ldGVycxIMCgRzaXplGAEgASgFEhMKC2ludGVy",
            "dmFsX3VzGAIgASgFEisKCmNvbXByZXNzZWQYAyABKAsyFy5ncnBjLnRlc3Rp",
            "bmcuQm9vbFZhbHVlIugBChpTdHJlYW1pbmdPdXRwdXRDYWxsUmVxdWVzdBIw",
            "Cg1yZXNwb25zZV90eXBlGAEgASgOMhkuZ3JwYy50ZXN0aW5nLlBheWxvYWRU",
            "eXBlEj0KE3Jlc3BvbnNlX3BhcmFtZXRlcnMYAiADKAsyIC5ncnBjLnRlc3Rp",
            "bmcuUmVzcG9uc2VQYXJhbWV0ZXJzEiYKB3BheWxvYWQYAyABKAsyFS5ncnBj",
            "LnRlc3RpbmcuUGF5bG9hZBIxCg9yZXNwb25zZV9zdGF0dXMYByABKAsyGC5n",
            "cnBjLnRlc3RpbmcuRWNob1N0YXR1cyJFChtTdHJlYW1pbmdPdXRwdXRDYWxs",
            "UmVzcG9uc2USJgoHcGF5bG9hZBgBIAEoCzIVLmdycGMudGVzdGluZy5QYXls",
            "b2FkIjMKD1JlY29ubmVjdFBhcmFtcxIgChhtYXhfcmVjb25uZWN0X2JhY2tv",
            "ZmZfbXMYASABKAUiMwoNUmVjb25uZWN0SW5mbxIOCgZwYXNzZWQYASABKAgS",
            "EgoKYmFja29mZl9tcxgCIAMoBSofCgtQYXlsb2FkVHlwZRIQCgxDT01QUkVT",
            "U0FCTEUQAGIGcHJvdG8z"));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { },
          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.PayloadType), }, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.BoolValue), global::Grpc.Testing.BoolValue.Parser, new[]{ "Value" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Payload), global::Grpc.Testing.Payload.Parser, new[]{ "Type", "Body" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoStatus), global::Grpc.Testing.EchoStatus.Parser, new[]{ "Code", "Message" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleRequest), global::Grpc.Testing.SimpleRequest.Parser, new[]{ "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope", "ResponseCompressed", "ResponseStatus", "ExpectCompressed" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleResponse), global::Grpc.Testing.SimpleResponse.Parser, new[]{ "Payload", "Username", "OauthScope" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingInputCallRequest), global::Grpc.Testing.StreamingInputCallRequest.Parser, new[]{ "Payload", "ExpectCompressed" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingInputCallResponse), global::Grpc.Testing.StreamingInputCallResponse.Parser, new[]{ "AggregatedPayloadSize" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ResponseParameters), global::Grpc.Testing.ResponseParameters.Parser, new[]{ "Size", "IntervalUs", "Compressed" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingOutputCallRequest), global::Grpc.Testing.StreamingOutputCallRequest.Parser, new[]{ "ResponseType", "ResponseParameters", "Payload", "ResponseStatus" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingOutputCallResponse), global::Grpc.Testing.StreamingOutputCallResponse.Parser, new[]{ "Payload" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ReconnectParams), global::Grpc.Testing.ReconnectParams.Parser, new[]{ "MaxReconnectBackoffMs" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ReconnectInfo), global::Grpc.Testing.ReconnectInfo.Parser, new[]{ "Passed", "BackoffMs" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Enums
  /// <summary>
  /// The type of payload that should be returned.
  /// </summary>
  public enum PayloadType {
    /// <summary>
    /// Compressable text format.
    /// </summary>
    [pbr::OriginalName("COMPRESSABLE")] Compressable = 0,
  }

  #endregion

  #region Messages
  /// <summary>
  /// TODO(dgq): Go back to using well-known types once
  /// https://github.com/grpc/grpc/issues/6980 has been fixed.
  /// import "google/protobuf/wrappers.proto";
  /// </summary>
  public sealed partial class BoolValue : pb::IMessage<BoolValue> {
    private static readonly pb::MessageParser<BoolValue> _parser = new pb::MessageParser<BoolValue>(() => new BoolValue());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<BoolValue> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public BoolValue(BoolValue other) : this() {
      value_ = other.value_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "value" field.</summary>
    public const int ValueFieldNumber = 1;
    private bool value_;
    /// <summary>
    /// The bool value.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Value {
      get { return value_; }
      set {
        value_ = value;
      }
    }

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

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(BoolValue other) {
      if (other == null) {
        return;
      }
      if (other.Value != false) {
        Value = other.Value;
      }
      _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: {
            Value = input.ReadBool();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// A block of data, to simply increase gRPC message size.
  /// </summary>
  public sealed partial class Payload : pb::IMessage<Payload> {
    private static readonly pb::MessageParser<Payload> _parser = new pb::MessageParser<Payload>(() => new Payload());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<Payload> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Payload(Payload other) : this() {
      type_ = other.type_;
      body_ = other.body_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "type" field.</summary>
    public const int TypeFieldNumber = 1;
    private global::Grpc.Testing.PayloadType type_ = 0;
    /// <summary>
    /// The type of data in body.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.PayloadType Type {
      get { return type_; }
      set {
        type_ = value;
      }
    }

    /// <summary>Field number for the "body" field.</summary>
    public const int BodyFieldNumber = 2;
    private pb::ByteString body_ = pb::ByteString.Empty;
    /// <summary>
    /// Primary contents of payload.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pb::ByteString Body {
      get { return body_; }
      set {
        body_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

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

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(Payload other) {
      if (other == null) {
        return;
      }
      if (other.Type != 0) {
        Type = other.Type;
      }
      if (other.Body.Length != 0) {
        Body = other.Body;
      }
      _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: {
            type_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
            break;
          }
          case 18: {
            Body = input.ReadBytes();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// A protobuf representation for grpc status. This is used by test
  /// clients to specify a status that the server should attempt to return.
  /// </summary>
  public sealed partial class EchoStatus : pb::IMessage<EchoStatus> {
    private static readonly pb::MessageParser<EchoStatus> _parser = new pb::MessageParser<EchoStatus>(() => new EchoStatus());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<EchoStatus> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EchoStatus(EchoStatus other) : this() {
      code_ = other.code_;
      message_ = other.message_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "code" field.</summary>
    public const int CodeFieldNumber = 1;
    private int code_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Code {
      get { return code_; }
      set {
        code_ = value;
      }
    }

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

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

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(EchoStatus other) {
      if (other == null) {
        return;
      }
      if (other.Code != 0) {
        Code = other.Code;
      }
      if (other.Message.Length != 0) {
        Message = other.Message;
      }
      _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: {
            Code = input.ReadInt32();
            break;
          }
          case 18: {
            Message = input.ReadString();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Unary request.
  /// </summary>
  public sealed partial class SimpleRequest : pb::IMessage<SimpleRequest> {
    private static readonly pb::MessageParser<SimpleRequest> _parser = new pb::MessageParser<SimpleRequest>(() => new SimpleRequest());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<SimpleRequest> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public SimpleRequest(SimpleRequest other) : this() {
      responseType_ = other.responseType_;
      responseSize_ = other.responseSize_;
      payload_ = other.payload_ != null ? other.payload_.Clone() : null;
      fillUsername_ = other.fillUsername_;
      fillOauthScope_ = other.fillOauthScope_;
      responseCompressed_ = other.responseCompressed_ != null ? other.responseCompressed_.Clone() : null;
      responseStatus_ = other.responseStatus_ != null ? other.responseStatus_.Clone() : null;
      expectCompressed_ = other.expectCompressed_ != null ? other.expectCompressed_.Clone() : null;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "response_type" field.</summary>
    public const int ResponseTypeFieldNumber = 1;
    private global::Grpc.Testing.PayloadType responseType_ = 0;
    /// <summary>
    /// Desired payload type in the response from the server.
    /// If response_type is RANDOM, server randomly chooses one from other formats.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.PayloadType ResponseType {
      get { return responseType_; }
      set {
        responseType_ = value;
      }
    }

    /// <summary>Field number for the "response_size" field.</summary>
    public const int ResponseSizeFieldNumber = 2;
    private int responseSize_;
    /// <summary>
    /// Desired payload size in the response from the server.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ResponseSize {
      get { return responseSize_; }
      set {
        responseSize_ = value;
      }
    }

    /// <summary>Field number for the "payload" field.</summary>
    public const int PayloadFieldNumber = 3;
    private global::Grpc.Testing.Payload payload_;
    /// <summary>
    /// Optional input payload sent along with the request.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

    /// <summary>Field number for the "fill_username" field.</summary>
    public const int FillUsernameFieldNumber = 4;
    private bool fillUsername_;
    /// <summary>
    /// Whether SimpleResponse should include username.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool FillUsername {
      get { return fillUsername_; }
      set {
        fillUsername_ = value;
      }
    }

    /// <summary>Field number for the "fill_oauth_scope" field.</summary>
    public const int FillOauthScopeFieldNumber = 5;
    private bool fillOauthScope_;
    /// <summary>
    /// Whether SimpleResponse should include OAuth scope.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool FillOauthScope {
      get { return fillOauthScope_; }
      set {
        fillOauthScope_ = value;
      }
    }

    /// <summary>Field number for the "response_compressed" field.</summary>
    public const int ResponseCompressedFieldNumber = 6;
    private global::Grpc.Testing.BoolValue responseCompressed_;
    /// <summary>
    /// Whether to request the server to compress the response. This field is
    /// "nullable" in order to interoperate seamlessly with clients not able to
    /// implement the full compression tests by introspecting the call to verify
    /// the response's compression status.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.BoolValue ResponseCompressed {
      get { return responseCompressed_; }
      set {
        responseCompressed_ = value;
      }
    }

    /// <summary>Field number for the "response_status" field.</summary>
    public const int ResponseStatusFieldNumber = 7;
    private global::Grpc.Testing.EchoStatus responseStatus_;
    /// <summary>
    /// Whether server should return a given status
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.EchoStatus ResponseStatus {
      get { return responseStatus_; }
      set {
        responseStatus_ = value;
      }
    }

    /// <summary>Field number for the "expect_compressed" field.</summary>
    public const int ExpectCompressedFieldNumber = 8;
    private global::Grpc.Testing.BoolValue expectCompressed_;
    /// <summary>
    /// Whether the server should expect this request to be compressed.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.BoolValue ExpectCompressed {
      get { return expectCompressed_; }
      set {
        expectCompressed_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(SimpleRequest other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ResponseType != other.ResponseType) return false;
      if (ResponseSize != other.ResponseSize) return false;
      if (!object.Equals(Payload, other.Payload)) return false;
      if (FillUsername != other.FillUsername) return false;
      if (FillOauthScope != other.FillOauthScope) return false;
      if (!object.Equals(ResponseCompressed, other.ResponseCompressed)) return false;
      if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false;
      if (!object.Equals(ExpectCompressed, other.ExpectCompressed)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ResponseType != 0) hash ^= ResponseType.GetHashCode();
      if (ResponseSize != 0) hash ^= ResponseSize.GetHashCode();
      if (payload_ != null) hash ^= Payload.GetHashCode();
      if (FillUsername != false) hash ^= FillUsername.GetHashCode();
      if (FillOauthScope != false) hash ^= FillOauthScope.GetHashCode();
      if (responseCompressed_ != null) hash ^= ResponseCompressed.GetHashCode();
      if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode();
      if (expectCompressed_ != null) hash ^= ExpectCompressed.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 (ResponseType != 0) {
        output.WriteRawTag(8);
        output.WriteEnum((int) ResponseType);
      }
      if (ResponseSize != 0) {
        output.WriteRawTag(16);
        output.WriteInt32(ResponseSize);
      }
      if (payload_ != null) {
        output.WriteRawTag(26);
        output.WriteMessage(Payload);
      }
      if (FillUsername != false) {
        output.WriteRawTag(32);
        output.WriteBool(FillUsername);
      }
      if (FillOauthScope != false) {
        output.WriteRawTag(40);
        output.WriteBool(FillOauthScope);
      }
      if (responseCompressed_ != null) {
        output.WriteRawTag(50);
        output.WriteMessage(ResponseCompressed);
      }
      if (responseStatus_ != null) {
        output.WriteRawTag(58);
        output.WriteMessage(ResponseStatus);
      }
      if (expectCompressed_ != null) {
        output.WriteRawTag(66);
        output.WriteMessage(ExpectCompressed);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (ResponseType != 0) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType);
      }
      if (ResponseSize != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResponseSize);
      }
      if (payload_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
      }
      if (FillUsername != false) {
        size += 1 + 1;
      }
      if (FillOauthScope != false) {
        size += 1 + 1;
      }
      if (responseCompressed_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseCompressed);
      }
      if (responseStatus_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseStatus);
      }
      if (expectCompressed_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectCompressed);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(SimpleRequest other) {
      if (other == null) {
        return;
      }
      if (other.ResponseType != 0) {
        ResponseType = other.ResponseType;
      }
      if (other.ResponseSize != 0) {
        ResponseSize = other.ResponseSize;
      }
      if (other.payload_ != null) {
        if (payload_ == null) {
          payload_ = new global::Grpc.Testing.Payload();
        }
        Payload.MergeFrom(other.Payload);
      }
      if (other.FillUsername != false) {
        FillUsername = other.FillUsername;
      }
      if (other.FillOauthScope != false) {
        FillOauthScope = other.FillOauthScope;
      }
      if (other.responseCompressed_ != null) {
        if (responseCompressed_ == null) {
          responseCompressed_ = new global::Grpc.Testing.BoolValue();
        }
        ResponseCompressed.MergeFrom(other.ResponseCompressed);
      }
      if (other.responseStatus_ != null) {
        if (responseStatus_ == null) {
          responseStatus_ = new global::Grpc.Testing.EchoStatus();
        }
        ResponseStatus.MergeFrom(other.ResponseStatus);
      }
      if (other.expectCompressed_ != null) {
        if (expectCompressed_ == null) {
          expectCompressed_ = new global::Grpc.Testing.BoolValue();
        }
        ExpectCompressed.MergeFrom(other.ExpectCompressed);
      }
      _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: {
            responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
            break;
          }
          case 16: {
            ResponseSize = input.ReadInt32();
            break;
          }
          case 26: {
            if (payload_ == null) {
              payload_ = new global::Grpc.Testing.Payload();
            }
            input.ReadMessage(payload_);
            break;
          }
          case 32: {
            FillUsername = input.ReadBool();
            break;
          }
          case 40: {
            FillOauthScope = input.ReadBool();
            break;
          }
          case 50: {
            if (responseCompressed_ == null) {
              responseCompressed_ = new global::Grpc.Testing.BoolValue();
            }
            input.ReadMessage(responseCompressed_);
            break;
          }
          case 58: {
            if (responseStatus_ == null) {
              responseStatus_ = new global::Grpc.Testing.EchoStatus();
            }
            input.ReadMessage(responseStatus_);
            break;
          }
          case 66: {
            if (expectCompressed_ == null) {
              expectCompressed_ = new global::Grpc.Testing.BoolValue();
            }
            input.ReadMessage(expectCompressed_);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Unary response, as configured by the request.
  /// </summary>
  public sealed partial class SimpleResponse : pb::IMessage<SimpleResponse> {
    private static readonly pb::MessageParser<SimpleResponse> _parser = new pb::MessageParser<SimpleResponse>(() => new SimpleResponse());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<SimpleResponse> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public SimpleResponse(SimpleResponse other) : this() {
      payload_ = other.payload_ != null ? other.payload_.Clone() : null;
      username_ = other.username_;
      oauthScope_ = other.oauthScope_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "payload" field.</summary>
    public const int PayloadFieldNumber = 1;
    private global::Grpc.Testing.Payload payload_;
    /// <summary>
    /// Payload to increase message size.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

    /// <summary>Field number for the "username" field.</summary>
    public const int UsernameFieldNumber = 2;
    private string username_ = "";
    /// <summary>
    /// The user the request came from, for verifying authentication was
    /// successful when the client expected it.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Username {
      get { return username_; }
      set {
        username_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "oauth_scope" field.</summary>
    public const int OauthScopeFieldNumber = 3;
    private string oauthScope_ = "";
    /// <summary>
    /// OAuth scope.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string OauthScope {
      get { return oauthScope_; }
      set {
        oauthScope_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(SimpleResponse other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Payload, other.Payload)) return false;
      if (Username != other.Username) return false;
      if (OauthScope != other.OauthScope) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (payload_ != null) hash ^= Payload.GetHashCode();
      if (Username.Length != 0) hash ^= Username.GetHashCode();
      if (OauthScope.Length != 0) hash ^= OauthScope.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 (payload_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Payload);
      }
      if (Username.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(Username);
      }
      if (OauthScope.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(OauthScope);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(SimpleResponse other) {
      if (other == null) {
        return;
      }
      if (other.payload_ != null) {
        if (payload_ == null) {
          payload_ = new global::Grpc.Testing.Payload();
        }
        Payload.MergeFrom(other.Payload);
      }
      if (other.Username.Length != 0) {
        Username = other.Username;
      }
      if (other.OauthScope.Length != 0) {
        OauthScope = other.OauthScope;
      }
      _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: {
            if (payload_ == null) {
              payload_ = new global::Grpc.Testing.Payload();
            }
            input.ReadMessage(payload_);
            break;
          }
          case 18: {
            Username = input.ReadString();
            break;
          }
          case 26: {
            OauthScope = input.ReadString();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Client-streaming request.
  /// </summary>
  public sealed partial class StreamingInputCallRequest : pb::IMessage<StreamingInputCallRequest> {
    private static readonly pb::MessageParser<StreamingInputCallRequest> _parser = new pb::MessageParser<StreamingInputCallRequest>(() => new StreamingInputCallRequest());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<StreamingInputCallRequest> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public StreamingInputCallRequest(StreamingInputCallRequest other) : this() {
      payload_ = other.payload_ != null ? other.payload_.Clone() : null;
      expectCompressed_ = other.expectCompressed_ != null ? other.expectCompressed_.Clone() : null;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "payload" field.</summary>
    public const int PayloadFieldNumber = 1;
    private global::Grpc.Testing.Payload payload_;
    /// <summary>
    /// Optional input payload sent along with the request.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

    /// <summary>Field number for the "expect_compressed" field.</summary>
    public const int ExpectCompressedFieldNumber = 2;
    private global::Grpc.Testing.BoolValue expectCompressed_;
    /// <summary>
    /// Whether the server should expect this request to be compressed. This field
    /// is "nullable" in order to interoperate seamlessly with servers not able to
    /// implement the full compression tests by introspecting the call to verify
    /// the request's compression status.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.BoolValue ExpectCompressed {
      get { return expectCompressed_; }
      set {
        expectCompressed_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(StreamingInputCallRequest other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Payload, other.Payload)) return false;
      if (!object.Equals(ExpectCompressed, other.ExpectCompressed)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (payload_ != null) hash ^= Payload.GetHashCode();
      if (expectCompressed_ != null) hash ^= ExpectCompressed.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 (payload_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Payload);
      }
      if (expectCompressed_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(ExpectCompressed);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (payload_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
      }
      if (expectCompressed_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectCompressed);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(StreamingInputCallRequest other) {
      if (other == null) {
        return;
      }
      if (other.payload_ != null) {
        if (payload_ == null) {
          payload_ = new global::Grpc.Testing.Payload();
        }
        Payload.MergeFrom(other.Payload);
      }
      if (other.expectCompressed_ != null) {
        if (expectCompressed_ == null) {
          expectCompressed_ = new global::Grpc.Testing.BoolValue();
        }
        ExpectCompressed.MergeFrom(other.ExpectCompressed);
      }
      _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: {
            if (payload_ == null) {
              payload_ = new global::Grpc.Testing.Payload();
            }
            input.ReadMessage(payload_);
            break;
          }
          case 18: {
            if (expectCompressed_ == null) {
              expectCompressed_ = new global::Grpc.Testing.BoolValue();
            }
            input.ReadMessage(expectCompressed_);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Client-streaming response.
  /// </summary>
  public sealed partial class StreamingInputCallResponse : pb::IMessage<StreamingInputCallResponse> {
    private static readonly pb::MessageParser<StreamingInputCallResponse> _parser = new pb::MessageParser<StreamingInputCallResponse>(() => new StreamingInputCallResponse());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<StreamingInputCallResponse> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public StreamingInputCallResponse(StreamingInputCallResponse other) : this() {
      aggregatedPayloadSize_ = other.aggregatedPayloadSize_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "aggregated_payload_size" field.</summary>
    public const int AggregatedPayloadSizeFieldNumber = 1;
    private int aggregatedPayloadSize_;
    /// <summary>
    /// Aggregated size of payloads received from the client.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int AggregatedPayloadSize {
      get { return aggregatedPayloadSize_; }
      set {
        aggregatedPayloadSize_ = value;
      }
    }

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

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(StreamingInputCallResponse other) {
      if (other == null) {
        return;
      }
      if (other.AggregatedPayloadSize != 0) {
        AggregatedPayloadSize = other.AggregatedPayloadSize;
      }
      _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: {
            AggregatedPayloadSize = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Configuration for a particular response.
  /// </summary>
  public sealed partial class ResponseParameters : pb::IMessage<ResponseParameters> {
    private static readonly pb::MessageParser<ResponseParameters> _parser = new pb::MessageParser<ResponseParameters>(() => new ResponseParameters());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ResponseParameters> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ResponseParameters(ResponseParameters other) : this() {
      size_ = other.size_;
      intervalUs_ = other.intervalUs_;
      compressed_ = other.compressed_ != null ? other.compressed_.Clone() : null;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "size" field.</summary>
    public const int SizeFieldNumber = 1;
    private int size_;
    /// <summary>
    /// Desired payload sizes in responses from the server.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Size {
      get { return size_; }
      set {
        size_ = value;
      }
    }

    /// <summary>Field number for the "interval_us" field.</summary>
    public const int IntervalUsFieldNumber = 2;
    private int intervalUs_;
    /// <summary>
    /// Desired interval between consecutive responses in the response stream in
    /// microseconds.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int IntervalUs {
      get { return intervalUs_; }
      set {
        intervalUs_ = value;
      }
    }

    /// <summary>Field number for the "compressed" field.</summary>
    public const int CompressedFieldNumber = 3;
    private global::Grpc.Testing.BoolValue compressed_;
    /// <summary>
    /// Whether to request the server to compress the response. This field is
    /// "nullable" in order to interoperate seamlessly with clients not able to
    /// implement the full compression tests by introspecting the call to verify
    /// the response's compression status.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.BoolValue Compressed {
      get { return compressed_; }
      set {
        compressed_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ResponseParameters other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Size != other.Size) return false;
      if (IntervalUs != other.IntervalUs) return false;
      if (!object.Equals(Compressed, other.Compressed)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Size != 0) hash ^= Size.GetHashCode();
      if (IntervalUs != 0) hash ^= IntervalUs.GetHashCode();
      if (compressed_ != null) hash ^= Compressed.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 (Size != 0) {
        output.WriteRawTag(8);
        output.WriteInt32(Size);
      }
      if (IntervalUs != 0) {
        output.WriteRawTag(16);
        output.WriteInt32(IntervalUs);
      }
      if (compressed_ != null) {
        output.WriteRawTag(26);
        output.WriteMessage(Compressed);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Size != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Size);
      }
      if (IntervalUs != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntervalUs);
      }
      if (compressed_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Compressed);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ResponseParameters other) {
      if (other == null) {
        return;
      }
      if (other.Size != 0) {
        Size = other.Size;
      }
      if (other.IntervalUs != 0) {
        IntervalUs = other.IntervalUs;
      }
      if (other.compressed_ != null) {
        if (compressed_ == null) {
          compressed_ = new global::Grpc.Testing.BoolValue();
        }
        Compressed.MergeFrom(other.Compressed);
      }
      _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: {
            Size = input.ReadInt32();
            break;
          }
          case 16: {
            IntervalUs = input.ReadInt32();
            break;
          }
          case 26: {
            if (compressed_ == null) {
              compressed_ = new global::Grpc.Testing.BoolValue();
            }
            input.ReadMessage(compressed_);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Server-streaming request.
  /// </summary>
  public sealed partial class StreamingOutputCallRequest : pb::IMessage<StreamingOutputCallRequest> {
    private static readonly pb::MessageParser<StreamingOutputCallRequest> _parser = new pb::MessageParser<StreamingOutputCallRequest>(() => new StreamingOutputCallRequest());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<StreamingOutputCallRequest> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[8]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public StreamingOutputCallRequest(StreamingOutputCallRequest other) : this() {
      responseType_ = other.responseType_;
      responseParameters_ = other.responseParameters_.Clone();
      payload_ = other.payload_ != null ? other.payload_.Clone() : null;
      responseStatus_ = other.responseStatus_ != null ? other.responseStatus_.Clone() : null;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "response_type" field.</summary>
    public const int ResponseTypeFieldNumber = 1;
    private global::Grpc.Testing.PayloadType responseType_ = 0;
    /// <summary>
    /// Desired payload type in the response from the server.
    /// If response_type is RANDOM, the payload from each response in the stream
    /// might be of different types. This is to simulate a mixed type of payload
    /// stream.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.PayloadType ResponseType {
      get { return responseType_; }
      set {
        responseType_ = value;
      }
    }

    /// <summary>Field number for the "response_parameters" field.</summary>
    public const int ResponseParametersFieldNumber = 2;
    private static readonly pb::FieldCodec<global::Grpc.Testing.ResponseParameters> _repeated_responseParameters_codec
        = pb::FieldCodec.ForMessage(18, global::Grpc.Testing.ResponseParameters.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.ResponseParameters> responseParameters_ = new pbc::RepeatedField<global::Grpc.Testing.ResponseParameters>();
    /// <summary>
    /// Configuration for each expected response message.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.ResponseParameters> ResponseParameters {
      get { return responseParameters_; }
    }

    /// <summary>Field number for the "payload" field.</summary>
    public const int PayloadFieldNumber = 3;
    private global::Grpc.Testing.Payload payload_;
    /// <summary>
    /// Optional input payload sent along with the request.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

    /// <summary>Field number for the "response_status" field.</summary>
    public const int ResponseStatusFieldNumber = 7;
    private global::Grpc.Testing.EchoStatus responseStatus_;
    /// <summary>
    /// Whether server should return a given status
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.EchoStatus ResponseStatus {
      get { return responseStatus_; }
      set {
        responseStatus_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(StreamingOutputCallRequest other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ResponseType != other.ResponseType) return false;
      if(!responseParameters_.Equals(other.responseParameters_)) return false;
      if (!object.Equals(Payload, other.Payload)) return false;
      if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ResponseType != 0) hash ^= ResponseType.GetHashCode();
      hash ^= responseParameters_.GetHashCode();
      if (payload_ != null) hash ^= Payload.GetHashCode();
      if (responseStatus_ != null) hash ^= ResponseStatus.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 (ResponseType != 0) {
        output.WriteRawTag(8);
        output.WriteEnum((int) ResponseType);
      }
      responseParameters_.WriteTo(output, _repeated_responseParameters_codec);
      if (payload_ != null) {
        output.WriteRawTag(26);
        output.WriteMessage(Payload);
      }
      if (responseStatus_ != null) {
        output.WriteRawTag(58);
        output.WriteMessage(ResponseStatus);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (ResponseType != 0) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType);
      }
      size += responseParameters_.CalculateSize(_repeated_responseParameters_codec);
      if (payload_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
      }
      if (responseStatus_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseStatus);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(StreamingOutputCallRequest other) {
      if (other == null) {
        return;
      }
      if (other.ResponseType != 0) {
        ResponseType = other.ResponseType;
      }
      responseParameters_.Add(other.responseParameters_);
      if (other.payload_ != null) {
        if (payload_ == null) {
          payload_ = new global::Grpc.Testing.Payload();
        }
        Payload.MergeFrom(other.Payload);
      }
      if (other.responseStatus_ != null) {
        if (responseStatus_ == null) {
          responseStatus_ = new global::Grpc.Testing.EchoStatus();
        }
        ResponseStatus.MergeFrom(other.ResponseStatus);
      }
      _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: {
            responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
            break;
          }
          case 18: {
            responseParameters_.AddEntriesFrom(input, _repeated_responseParameters_codec);
            break;
          }
          case 26: {
            if (payload_ == null) {
              payload_ = new global::Grpc.Testing.Payload();
            }
            input.ReadMessage(payload_);
            break;
          }
          case 58: {
            if (responseStatus_ == null) {
              responseStatus_ = new global::Grpc.Testing.EchoStatus();
            }
            input.ReadMessage(responseStatus_);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Server-streaming response, as configured by the request and parameters.
  /// </summary>
  public sealed partial class StreamingOutputCallResponse : pb::IMessage<StreamingOutputCallResponse> {
    private static readonly pb::MessageParser<StreamingOutputCallResponse> _parser = new pb::MessageParser<StreamingOutputCallResponse>(() => new StreamingOutputCallResponse());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<StreamingOutputCallResponse> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[9]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public StreamingOutputCallResponse(StreamingOutputCallResponse other) : this() {
      payload_ = other.payload_ != null ? other.payload_.Clone() : null;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "payload" field.</summary>
    public const int PayloadFieldNumber = 1;
    private global::Grpc.Testing.Payload payload_;
    /// <summary>
    /// Payload to increase response size.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

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

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(StreamingOutputCallResponse other) {
      if (other == null) {
        return;
      }
      if (other.payload_ != null) {
        if (payload_ == null) {
          payload_ = new global::Grpc.Testing.Payload();
        }
        Payload.MergeFrom(other.Payload);
      }
      _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: {
            if (payload_ == null) {
              payload_ = new global::Grpc.Testing.Payload();
            }
            input.ReadMessage(payload_);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// For reconnect interop test only.
  /// Client tells server what reconnection parameters it used.
  /// </summary>
  public sealed partial class ReconnectParams : pb::IMessage<ReconnectParams> {
    private static readonly pb::MessageParser<ReconnectParams> _parser = new pb::MessageParser<ReconnectParams>(() => new ReconnectParams());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ReconnectParams> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[10]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ReconnectParams(ReconnectParams other) : this() {
      maxReconnectBackoffMs_ = other.maxReconnectBackoffMs_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "max_reconnect_backoff_ms" field.</summary>
    public const int MaxReconnectBackoffMsFieldNumber = 1;
    private int maxReconnectBackoffMs_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int MaxReconnectBackoffMs {
      get { return maxReconnectBackoffMs_; }
      set {
        maxReconnectBackoffMs_ = value;
      }
    }

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

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ReconnectParams other) {
      if (other == null) {
        return;
      }
      if (other.MaxReconnectBackoffMs != 0) {
        MaxReconnectBackoffMs = other.MaxReconnectBackoffMs;
      }
      _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: {
            MaxReconnectBackoffMs = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// For reconnect interop test only.
  /// Server tells client whether its reconnects are following the spec and the
  /// reconnect backoffs it saw.
  /// </summary>
  public sealed partial class ReconnectInfo : pb::IMessage<ReconnectInfo> {
    private static readonly pb::MessageParser<ReconnectInfo> _parser = new pb::MessageParser<ReconnectInfo>(() => new ReconnectInfo());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ReconnectInfo> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[11]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ReconnectInfo(ReconnectInfo other) : this() {
      passed_ = other.passed_;
      backoffMs_ = other.backoffMs_.Clone();
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "passed" field.</summary>
    public const int PassedFieldNumber = 1;
    private bool passed_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Passed {
      get { return passed_; }
      set {
        passed_ = value;
      }
    }

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Passed != false) hash ^= Passed.GetHashCode();
      hash ^= backoffMs_.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 (Passed != false) {
        output.WriteRawTag(8);
        output.WriteBool(Passed);
      }
      backoffMs_.WriteTo(output, _repeated_backoffMs_codec);
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Passed != false) {
        size += 1 + 1;
      }
      size += backoffMs_.CalculateSize(_repeated_backoffMs_codec);
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ReconnectInfo other) {
      if (other == null) {
        return;
      }
      if (other.Passed != false) {
        Passed = other.Passed;
      }
      backoffMs_.Add(other.backoffMs_);
      _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: {
            Passed = input.ReadBool();
            break;
          }
          case 18:
          case 16: {
            backoffMs_.AddEntriesFrom(input, _repeated_backoffMs_codec);
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
