// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: src/proto/grpc/testing/messages.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code

using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Grpc.Testing {

  /// <summary>Holder for reflection information generated from src/proto/grpc/testing/messages.proto</summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  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",
            "LnRlc3RpbmciQAoHUGF5bG9hZBInCgR0eXBlGAEgASgOMhkuZ3JwYy50ZXN0",
            "aW5nLlBheWxvYWRUeXBlEgwKBGJvZHkYAiABKAwiKwoKRWNob1N0YXR1cxIM",
            "CgRjb2RlGAEgASgFEg8KB21lc3NhZ2UYAiABKAkioQIKDVNpbXBsZVJlcXVl",
            "c3QSMAoNcmVzcG9uc2VfdHlwZRgBIAEoDjIZLmdycGMudGVzdGluZy5QYXls",
            "b2FkVHlwZRIVCg1yZXNwb25zZV9zaXplGAIgASgFEiYKB3BheWxvYWQYAyAB",
            "KAsyFS5ncnBjLnRlc3RpbmcuUGF5bG9hZBIVCg1maWxsX3VzZXJuYW1lGAQg",
            "ASgIEhgKEGZpbGxfb2F1dGhfc2NvcGUYBSABKAgSOwoUcmVzcG9uc2VfY29t",
            "cHJlc3Npb24YBiABKA4yHS5ncnBjLnRlc3RpbmcuQ29tcHJlc3Npb25UeXBl",
            "EjEKD3Jlc3BvbnNlX3N0YXR1cxgHIAEoCzIYLmdycGMudGVzdGluZy5FY2hv",
            "U3RhdHVzIl8KDlNpbXBsZVJlc3BvbnNlEiYKB3BheWxvYWQYASABKAsyFS5n",
            "cnBjLnRlc3RpbmcuUGF5bG9hZBIQCgh1c2VybmFtZRgCIAEoCRITCgtvYXV0",
            "aF9zY29wZRgDIAEoCSJDChlTdHJlYW1pbmdJbnB1dENhbGxSZXF1ZXN0EiYK",
            "B3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3RpbmcuUGF5bG9hZCI9ChpTdHJl",
            "YW1pbmdJbnB1dENhbGxSZXNwb25zZRIfChdhZ2dyZWdhdGVkX3BheWxvYWRf",
            "c2l6ZRgBIAEoBSI3ChJSZXNwb25zZVBhcmFtZXRlcnMSDAoEc2l6ZRgBIAEo",
            "BRITCgtpbnRlcnZhbF91cxgCIAEoBSKlAgoaU3RyZWFtaW5nT3V0cHV0Q2Fs",
            "bFJlcXVlc3QSMAoNcmVzcG9uc2VfdHlwZRgBIAEoDjIZLmdycGMudGVzdGlu",
            "Zy5QYXlsb2FkVHlwZRI9ChNyZXNwb25zZV9wYXJhbWV0ZXJzGAIgAygLMiAu",
            "Z3JwYy50ZXN0aW5nLlJlc3BvbnNlUGFyYW1ldGVycxImCgdwYXlsb2FkGAMg",
            "ASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxvYWQSOwoUcmVzcG9uc2VfY29tcHJl",
            "c3Npb24YBiABKA4yHS5ncnBjLnRlc3RpbmcuQ29tcHJlc3Npb25UeXBlEjEK",
            "D3Jlc3BvbnNlX3N0YXR1cxgHIAEoCzIYLmdycGMudGVzdGluZy5FY2hvU3Rh",
            "dHVzIkUKG1N0cmVhbWluZ091dHB1dENhbGxSZXNwb25zZRImCgdwYXlsb2Fk",
            "GAEgASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxvYWQiMwoNUmVjb25uZWN0SW5m",
            "bxIOCgZwYXNzZWQYASABKAgSEgoKYmFja29mZl9tcxgCIAMoBSo/CgtQYXls",
            "b2FkVHlwZRIQCgxDT01QUkVTU0FCTEUQABISCg5VTkNPTVBSRVNTQUJMRRAB",
            "EgoKBlJBTkRPTRACKjIKD0NvbXByZXNzaW9uVHlwZRIICgROT05FEAASCAoE",
            "R1pJUBABEgsKB0RFRkxBVEUQAmIGcHJvdG8z"));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { },
          new pbr::GeneratedCodeInfo(new[] {typeof(global::Grpc.Testing.PayloadType), typeof(global::Grpc.Testing.CompressionType), }, new pbr::GeneratedCodeInfo[] {
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Payload), global::Grpc.Testing.Payload.Parser, new[]{ "Type", "Body" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.EchoStatus), global::Grpc.Testing.EchoStatus.Parser, new[]{ "Code", "Message" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleRequest), global::Grpc.Testing.SimpleRequest.Parser, new[]{ "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope", "ResponseCompression", "ResponseStatus" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleResponse), global::Grpc.Testing.SimpleResponse.Parser, new[]{ "Payload", "Username", "OauthScope" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingInputCallRequest), global::Grpc.Testing.StreamingInputCallRequest.Parser, new[]{ "Payload" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingInputCallResponse), global::Grpc.Testing.StreamingInputCallResponse.Parser, new[]{ "AggregatedPayloadSize" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ResponseParameters), global::Grpc.Testing.ResponseParameters.Parser, new[]{ "Size", "IntervalUs" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingOutputCallRequest), global::Grpc.Testing.StreamingOutputCallRequest.Parser, new[]{ "ResponseType", "ResponseParameters", "Payload", "ResponseCompression", "ResponseStatus" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingOutputCallResponse), global::Grpc.Testing.StreamingOutputCallResponse.Parser, new[]{ "Payload" }, null, null, null),
            new pbr::GeneratedCodeInfo(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>
    COMPRESSABLE = 0,
    /// <summary>
    ///  Uncompressable binary format.
    /// </summary>
    UNCOMPRESSABLE = 1,
    /// <summary>
    ///  Randomly chosen from all other formats defined in this enum.
    /// </summary>
    RANDOM = 2,
  }

  /// <summary>
  ///  Compression algorithms
  /// </summary>
  public enum CompressionType {
    /// <summary>
    ///  No compression
    /// </summary>
    NONE = 0,
    GZIP = 1,
    DEFLATE = 2,
  }

  #endregion

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

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

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

    public Payload() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Payload(Payload other) : this() {
      type_ = other.type_;
      body_ = other.body_;
    }

    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_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
    /// <summary>
    ///  The type of data in body.
    /// </summary>
    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>
    public pb::ByteString Body {
      get { return body_; }
      set {
        body_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

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

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

    public override int GetHashCode() {
      int hash = 1;
      if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= Type.GetHashCode();
      if (Body.Length != 0) hash ^= Body.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
        output.WriteRawTag(8);
        output.WriteEnum((int) Type);
      }
      if (Body.Length != 0) {
        output.WriteRawTag(18);
        output.WriteBytes(Body);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
      }
      if (Body.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Body);
      }
      return size;
    }

    public void MergeFrom(Payload other) {
      if (other == null) {
        return;
      }
      if (other.Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
        Type = other.Type;
      }
      if (other.Body.Length != 0) {
        Body = other.Body;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            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>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class EchoStatus : pb::IMessage<EchoStatus> {
    private static readonly pb::MessageParser<EchoStatus> _parser = new pb::MessageParser<EchoStatus>(() => new EchoStatus());
    public static pb::MessageParser<EchoStatus> Parser { get { return _parser; } }

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

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

    public EchoStatus() {
      OnConstruction();
    }

    partial void OnConstruction();

    public EchoStatus(EchoStatus other) : this() {
      code_ = other.code_;
      message_ = other.message_;
    }

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

    /// <summary>Field number for the "code" field.</summary>
    public const int CodeFieldNumber = 1;
    private int code_;
    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_ = "";
    public string Message {
      get { return message_; }
      set {
        message_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

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

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

    public override int GetHashCode() {
      int hash = 1;
      if (Code != 0) hash ^= Code.GetHashCode();
      if (Message.Length != 0) hash ^= Message.GetHashCode();
      return hash;
    }

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

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

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

    public void MergeFrom(EchoStatus other) {
      if (other == null) {
        return;
      }
      if (other.Code != 0) {
        Code = other.Code;
      }
      if (other.Message.Length != 0) {
        Message = other.Message;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            Code = input.ReadInt32();
            break;
          }
          case 18: {
            Message = input.ReadString();
            break;
          }
        }
      }
    }

  }

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

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

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

    public SimpleRequest() {
      OnConstruction();
    }

    partial void OnConstruction();

    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_;
      responseCompression_ = other.responseCompression_;
      ResponseStatus = other.responseStatus_ != null ? other.ResponseStatus.Clone() : null;
    }

    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_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
    /// <summary>
    ///  Desired payload type in the response from the server.
    ///  If response_type is RANDOM, server randomly chooses one from other formats.
    /// </summary>
    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.
    ///  If response_type is COMPRESSABLE, this denotes the size before compression.
    /// </summary>
    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>
    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>
    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>
    public bool FillOauthScope {
      get { return fillOauthScope_; }
      set {
        fillOauthScope_ = value;
      }
    }

    /// <summary>Field number for the "response_compression" field.</summary>
    public const int ResponseCompressionFieldNumber = 6;
    private global::Grpc.Testing.CompressionType responseCompression_ = global::Grpc.Testing.CompressionType.NONE;
    /// <summary>
    ///  Compression algorithm to be used by the server for the response (stream)
    /// </summary>
    public global::Grpc.Testing.CompressionType ResponseCompression {
      get { return responseCompression_; }
      set {
        responseCompression_ = 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>
    public global::Grpc.Testing.EchoStatus ResponseStatus {
      get { return responseStatus_; }
      set {
        responseStatus_ = value;
      }
    }

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

    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 (ResponseCompression != other.ResponseCompression) return false;
      if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) 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 (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) hash ^= ResponseCompression.GetHashCode();
      if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
        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 (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
        output.WriteRawTag(48);
        output.WriteEnum((int) ResponseCompression);
      }
      if (responseStatus_ != null) {
        output.WriteRawTag(58);
        output.WriteMessage(ResponseStatus);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
        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 (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseCompression);
      }
      if (responseStatus_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseStatus);
      }
      return size;
    }

    public void MergeFrom(SimpleRequest other) {
      if (other == null) {
        return;
      }
      if (other.ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
        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.ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
        ResponseCompression = other.ResponseCompression;
      }
      if (other.responseStatus_ != null) {
        if (responseStatus_ == null) {
          responseStatus_ = new global::Grpc.Testing.EchoStatus();
        }
        ResponseStatus.MergeFrom(other.ResponseStatus);
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            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 48: {
            responseCompression_ = (global::Grpc.Testing.CompressionType) input.ReadEnum();
            break;
          }
          case 58: {
            if (responseStatus_ == null) {
              responseStatus_ = new global::Grpc.Testing.EchoStatus();
            }
            input.ReadMessage(responseStatus_);
            break;
          }
        }
      }
    }

  }

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

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

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

    public SimpleResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    public SimpleResponse(SimpleResponse other) : this() {
      Payload = other.payload_ != null ? other.Payload.Clone() : null;
      username_ = other.username_;
      oauthScope_ = other.oauthScope_;
    }

    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>
    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>
    public string Username {
      get { return username_; }
      set {
        username_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

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

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

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

    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();
      return hash;
    }

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

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

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

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

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            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>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class StreamingInputCallRequest : pb::IMessage<StreamingInputCallRequest> {
    private static readonly pb::MessageParser<StreamingInputCallRequest> _parser = new pb::MessageParser<StreamingInputCallRequest>(() => new StreamingInputCallRequest());
    public static pb::MessageParser<StreamingInputCallRequest> Parser { get { return _parser; } }

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

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

    public StreamingInputCallRequest() {
      OnConstruction();
    }

    partial void OnConstruction();

    public StreamingInputCallRequest(StreamingInputCallRequest other) : this() {
      Payload = other.payload_ != null ? other.Payload.Clone() : null;
    }

    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>
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

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

    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;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (payload_ != null) hash ^= Payload.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (payload_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Payload);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (payload_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
      }
      return size;
    }

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

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            if (payload_ == null) {
              payload_ = new global::Grpc.Testing.Payload();
            }
            input.ReadMessage(payload_);
            break;
          }
        }
      }
    }

  }

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

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

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

    public StreamingInputCallResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    public StreamingInputCallResponse(StreamingInputCallResponse other) : this() {
      aggregatedPayloadSize_ = other.aggregatedPayloadSize_;
    }

    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>
    public int AggregatedPayloadSize {
      get { return aggregatedPayloadSize_; }
      set {
        aggregatedPayloadSize_ = value;
      }
    }

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

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

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

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

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

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

    public void MergeFrom(StreamingInputCallResponse other) {
      if (other == null) {
        return;
      }
      if (other.AggregatedPayloadSize != 0) {
        AggregatedPayloadSize = other.AggregatedPayloadSize;
      }
    }

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

  }

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

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

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

    public ResponseParameters() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ResponseParameters(ResponseParameters other) : this() {
      size_ = other.size_;
      intervalUs_ = other.intervalUs_;
    }

    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.
    ///  If response_type is COMPRESSABLE, this denotes the size before compression.
    /// </summary>
    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>
    public int IntervalUs {
      get { return intervalUs_; }
      set {
        intervalUs_ = value;
      }
    }

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

    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;
      return true;
    }

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

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

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

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

    public void MergeFrom(ResponseParameters other) {
      if (other == null) {
        return;
      }
      if (other.Size != 0) {
        Size = other.Size;
      }
      if (other.IntervalUs != 0) {
        IntervalUs = other.IntervalUs;
      }
    }

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

  }

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

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

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

    public StreamingOutputCallRequest() {
      OnConstruction();
    }

    partial void OnConstruction();

    public StreamingOutputCallRequest(StreamingOutputCallRequest other) : this() {
      responseType_ = other.responseType_;
      responseParameters_ = other.responseParameters_.Clone();
      Payload = other.payload_ != null ? other.Payload.Clone() : null;
      responseCompression_ = other.responseCompression_;
      ResponseStatus = other.responseStatus_ != null ? other.ResponseStatus.Clone() : null;
    }

    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_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
    /// <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>
    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>
    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>
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

    /// <summary>Field number for the "response_compression" field.</summary>
    public const int ResponseCompressionFieldNumber = 6;
    private global::Grpc.Testing.CompressionType responseCompression_ = global::Grpc.Testing.CompressionType.NONE;
    /// <summary>
    ///  Compression algorithm to be used by the server for the response (stream)
    /// </summary>
    public global::Grpc.Testing.CompressionType ResponseCompression {
      get { return responseCompression_; }
      set {
        responseCompression_ = 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>
    public global::Grpc.Testing.EchoStatus ResponseStatus {
      get { return responseStatus_; }
      set {
        responseStatus_ = value;
      }
    }

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

    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 (ResponseCompression != other.ResponseCompression) return false;
      if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= ResponseType.GetHashCode();
      hash ^= responseParameters_.GetHashCode();
      if (payload_ != null) hash ^= Payload.GetHashCode();
      if (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) hash ^= ResponseCompression.GetHashCode();
      if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
        output.WriteRawTag(8);
        output.WriteEnum((int) ResponseType);
      }
      responseParameters_.WriteTo(output, _repeated_responseParameters_codec);
      if (payload_ != null) {
        output.WriteRawTag(26);
        output.WriteMessage(Payload);
      }
      if (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
        output.WriteRawTag(48);
        output.WriteEnum((int) ResponseCompression);
      }
      if (responseStatus_ != null) {
        output.WriteRawTag(58);
        output.WriteMessage(ResponseStatus);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType);
      }
      size += responseParameters_.CalculateSize(_repeated_responseParameters_codec);
      if (payload_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
      }
      if (ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseCompression);
      }
      if (responseStatus_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseStatus);
      }
      return size;
    }

    public void MergeFrom(StreamingOutputCallRequest other) {
      if (other == null) {
        return;
      }
      if (other.ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) {
        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.ResponseCompression != global::Grpc.Testing.CompressionType.NONE) {
        ResponseCompression = other.ResponseCompression;
      }
      if (other.responseStatus_ != null) {
        if (responseStatus_ == null) {
          responseStatus_ = new global::Grpc.Testing.EchoStatus();
        }
        ResponseStatus.MergeFrom(other.ResponseStatus);
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            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 48: {
            responseCompression_ = (global::Grpc.Testing.CompressionType) input.ReadEnum();
            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>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class StreamingOutputCallResponse : pb::IMessage<StreamingOutputCallResponse> {
    private static readonly pb::MessageParser<StreamingOutputCallResponse> _parser = new pb::MessageParser<StreamingOutputCallResponse>(() => new StreamingOutputCallResponse());
    public static pb::MessageParser<StreamingOutputCallResponse> Parser { get { return _parser; } }

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

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

    public StreamingOutputCallResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    public StreamingOutputCallResponse(StreamingOutputCallResponse other) : this() {
      Payload = other.payload_ != null ? other.Payload.Clone() : null;
    }

    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>
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

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

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

    public override int GetHashCode() {
      int hash = 1;
      if (payload_ != null) hash ^= Payload.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (payload_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Payload);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (payload_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
      }
      return size;
    }

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

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            if (payload_ == null) {
              payload_ = new global::Grpc.Testing.Payload();
            }
            input.ReadMessage(payload_);
            break;
          }
        }
      }
    }

  }

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

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

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

    public ReconnectInfo() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ReconnectInfo(ReconnectInfo other) : this() {
      passed_ = other.passed_;
      backoffMs_ = other.backoffMs_.Clone();
    }

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

    /// <summary>Field number for the "passed" field.</summary>
    public const int PassedFieldNumber = 1;
    private bool passed_;
    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>();
    public pbc::RepeatedField<int> BackoffMs {
      get { return backoffMs_; }
    }

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

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

    public override int GetHashCode() {
      int hash = 1;
      if (Passed != false) hash ^= Passed.GetHashCode();
      hash ^= backoffMs_.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Passed != false) {
        output.WriteRawTag(8);
        output.WriteBool(Passed);
      }
      backoffMs_.WriteTo(output, _repeated_backoffMs_codec);
    }

    public int CalculateSize() {
      int size = 0;
      if (Passed != false) {
        size += 1 + 1;
      }
      size += backoffMs_.CalculateSize(_repeated_backoffMs_codec);
      return size;
    }

    public void MergeFrom(ReconnectInfo other) {
      if (other == null) {
        return;
      }
      if (other.Passed != false) {
        Passed = other.Passed;
      }
      backoffMs_.Add(other.backoffMs_);
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            Passed = input.ReadBool();
            break;
          }
          case 18:
          case 16: {
            backoffMs_.AddEntriesFrom(input, _repeated_backoffMs_codec);
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
