// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: test/proto/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 {

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public static partial class Messages {

    #region Descriptor
    public static pbr::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbr::FileDescriptor descriptor;

    static Messages() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "Chl0ZXN0L3Byb3RvL21lc3NhZ2VzLnByb3RvEgxncnBjLnRlc3RpbmciQAoH", 
            "UGF5bG9hZBInCgR0eXBlGAEgASgOMhkuZ3JwYy50ZXN0aW5nLlBheWxvYWRU", 
            "eXBlEgwKBGJvZHkYAiABKAwiKwoKRWNob1N0YXR1cxIMCgRjb2RlGAEgASgF", 
            "Eg8KB21lc3NhZ2UYAiABKAkioQIKDVNpbXBsZVJlcXVlc3QSMAoNcmVzcG9u", 
            "c2VfdHlwZRgBIAEoDjIZLmdycGMudGVzdGluZy5QYXlsb2FkVHlwZRIVCg1y", 
            "ZXNwb25zZV9zaXplGAIgASgFEiYKB3BheWxvYWQYAyABKAsyFS5ncnBjLnRl", 
            "c3RpbmcuUGF5bG9hZBIVCg1maWxsX3VzZXJuYW1lGAQgASgIEhgKEGZpbGxf", 
            "b2F1dGhfc2NvcGUYBSABKAgSOwoUcmVzcG9uc2VfY29tcHJlc3Npb24YBiAB", 
            "KA4yHS5ncnBjLnRlc3RpbmcuQ29tcHJlc3Npb25UeXBlEjEKD3Jlc3BvbnNl", 
            "X3N0YXR1cxgHIAEoCzIYLmdycGMudGVzdGluZy5FY2hvU3RhdHVzIl8KDlNp", 
            "bXBsZVJlc3BvbnNlEiYKB3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3Rpbmcu", 
            "UGF5bG9hZBIQCgh1c2VybmFtZRgCIAEoCRITCgtvYXV0aF9zY29wZRgDIAEo", 
            "CSJDChlTdHJlYW1pbmdJbnB1dENhbGxSZXF1ZXN0EiYKB3BheWxvYWQYASAB", 
            "KAsyFS5ncnBjLnRlc3RpbmcuUGF5bG9hZCI9ChpTdHJlYW1pbmdJbnB1dENh", 
            "bGxSZXNwb25zZRIfChdhZ2dyZWdhdGVkX3BheWxvYWRfc2l6ZRgBIAEoBSI3", 
            "ChJSZXNwb25zZVBhcmFtZXRlcnMSDAoEc2l6ZRgBIAEoBRITCgtpbnRlcnZh", 
            "bF91cxgCIAEoBSKlAgoaU3RyZWFtaW5nT3V0cHV0Q2FsbFJlcXVlc3QSMAoN", 
            "cmVzcG9uc2VfdHlwZRgBIAEoDjIZLmdycGMudGVzdGluZy5QYXlsb2FkVHlw", 
            "ZRI9ChNyZXNwb25zZV9wYXJhbWV0ZXJzGAIgAygLMiAuZ3JwYy50ZXN0aW5n", 
            "LlJlc3BvbnNlUGFyYW1ldGVycxImCgdwYXlsb2FkGAMgASgLMhUuZ3JwYy50", 
            "ZXN0aW5nLlBheWxvYWQSOwoUcmVzcG9uc2VfY29tcHJlc3Npb24YBiABKA4y", 
            "HS5ncnBjLnRlc3RpbmcuQ29tcHJlc3Npb25UeXBlEjEKD3Jlc3BvbnNlX3N0", 
            "YXR1cxgHIAEoCzIYLmdycGMudGVzdGluZy5FY2hvU3RhdHVzIkUKG1N0cmVh", 
            "bWluZ091dHB1dENhbGxSZXNwb25zZRImCgdwYXlsb2FkGAEgASgLMhUuZ3Jw", 
            "Yy50ZXN0aW5nLlBheWxvYWQiMwoNUmVjb25uZWN0SW5mbxIOCgZwYXNzZWQY", 
            "ASABKAgSEgoKYmFja29mZl9tcxgCIAMoBSo/CgtQYXlsb2FkVHlwZRIQCgxD", 
            "T01QUkVTU0FCTEUQABISCg5VTkNPTVBSRVNTQUJMRRABEgoKBlJBTkRPTRAC", 
            "KjIKD0NvbXByZXNzaW9uVHlwZRIICgROT05FEAASCAoER1pJUBABEgsKB0RF", 
            "RkxBVEUQAmIGcHJvdG8z"));
      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(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), new[]{ "Type", "Body" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.EchoStatus), new[]{ "Code", "Message" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleRequest), new[]{ "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope", "ResponseCompression", "ResponseStatus" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleResponse), new[]{ "Payload", "Username", "OauthScope" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingInputCallRequest), new[]{ "Payload" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingInputCallResponse), new[]{ "AggregatedPayloadSize" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ResponseParameters), new[]{ "Size", "IntervalUs" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingOutputCallRequest), new[]{ "ResponseType", "ResponseParameters", "Payload", "ResponseCompression", "ResponseStatus" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingOutputCallResponse), new[]{ "Payload" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ReconnectInfo), new[]{ "Passed", "BackoffMs" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Enums
  public enum PayloadType {
    COMPRESSABLE = 0,
    UNCOMPRESSABLE = 1,
    RANDOM = 2,
  }

  public enum CompressionType {
    NONE = 0,
    GZIP = 1,
    DEFLATE = 2,
  }

  #endregion

  #region Messages
  [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.Messages.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);
    }

    public const int TypeFieldNumber = 1;
    private global::Grpc.Testing.PayloadType type_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
    public global::Grpc.Testing.PayloadType Type {
      get { return type_; }
      set {
        type_ = value;
      }
    }

    public const int BodyFieldNumber = 2;
    private pb::ByteString body_ = pb::ByteString.Empty;
    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.Default.Format(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;
          }
        }
      }
    }

  }

  [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.Messages.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);
    }

    public const int CodeFieldNumber = 1;
    private int code_;
    public int Code {
      get { return code_; }
      set {
        code_ = value;
      }
    }

    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.Default.Format(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;
          }
        }
      }
    }

  }

  [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.Messages.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);
    }

    public const int ResponseTypeFieldNumber = 1;
    private global::Grpc.Testing.PayloadType responseType_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
    public global::Grpc.Testing.PayloadType ResponseType {
      get { return responseType_; }
      set {
        responseType_ = value;
      }
    }

    public const int ResponseSizeFieldNumber = 2;
    private int responseSize_;
    public int ResponseSize {
      get { return responseSize_; }
      set {
        responseSize_ = value;
      }
    }

    public const int PayloadFieldNumber = 3;
    private global::Grpc.Testing.Payload payload_;
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

    public const int FillUsernameFieldNumber = 4;
    private bool fillUsername_;
    public bool FillUsername {
      get { return fillUsername_; }
      set {
        fillUsername_ = value;
      }
    }

    public const int FillOauthScopeFieldNumber = 5;
    private bool fillOauthScope_;
    public bool FillOauthScope {
      get { return fillOauthScope_; }
      set {
        fillOauthScope_ = value;
      }
    }

    public const int ResponseCompressionFieldNumber = 6;
    private global::Grpc.Testing.CompressionType responseCompression_ = global::Grpc.Testing.CompressionType.NONE;
    public global::Grpc.Testing.CompressionType ResponseCompression {
      get { return responseCompression_; }
      set {
        responseCompression_ = value;
      }
    }

    public const int ResponseStatusFieldNumber = 7;
    private global::Grpc.Testing.EchoStatus responseStatus_;
    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.Default.Format(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;
          }
        }
      }
    }

  }

  [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.Messages.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);
    }

    public const int PayloadFieldNumber = 1;
    private global::Grpc.Testing.Payload payload_;
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

    public const int UsernameFieldNumber = 2;
    private string username_ = "";
    public string Username {
      get { return username_; }
      set {
        username_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

    public const int OauthScopeFieldNumber = 3;
    private string oauthScope_ = "";
    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.Default.Format(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;
          }
        }
      }
    }

  }

  [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.Messages.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);
    }

    public const int PayloadFieldNumber = 1;
    private global::Grpc.Testing.Payload payload_;
    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.Default.Format(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;
          }
        }
      }
    }

  }

  [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.Messages.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);
    }

    public const int AggregatedPayloadSizeFieldNumber = 1;
    private int aggregatedPayloadSize_;
    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.Default.Format(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;
          }
        }
      }
    }

  }

  [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.Messages.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);
    }

    public const int SizeFieldNumber = 1;
    private int size_;
    public int Size {
      get { return size_; }
      set {
        size_ = value;
      }
    }

    public const int IntervalUsFieldNumber = 2;
    private int intervalUs_;
    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.Default.Format(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;
          }
        }
      }
    }

  }

  [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.Messages.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);
    }

    public const int ResponseTypeFieldNumber = 1;
    private global::Grpc.Testing.PayloadType responseType_ = global::Grpc.Testing.PayloadType.COMPRESSABLE;
    public global::Grpc.Testing.PayloadType ResponseType {
      get { return responseType_; }
      set {
        responseType_ = value;
      }
    }

    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>();
    public pbc::RepeatedField<global::Grpc.Testing.ResponseParameters> ResponseParameters {
      get { return responseParameters_; }
    }

    public const int PayloadFieldNumber = 3;
    private global::Grpc.Testing.Payload payload_;
    public global::Grpc.Testing.Payload Payload {
      get { return payload_; }
      set {
        payload_ = value;
      }
    }

    public const int ResponseCompressionFieldNumber = 6;
    private global::Grpc.Testing.CompressionType responseCompression_ = global::Grpc.Testing.CompressionType.NONE;
    public global::Grpc.Testing.CompressionType ResponseCompression {
      get { return responseCompression_; }
      set {
        responseCompression_ = value;
      }
    }

    public const int ResponseStatusFieldNumber = 7;
    private global::Grpc.Testing.EchoStatus responseStatus_;
    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.Default.Format(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;
          }
        }
      }
    }

  }

  [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.Messages.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);
    }

    public const int PayloadFieldNumber = 1;
    private global::Grpc.Testing.Payload payload_;
    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.Default.Format(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;
          }
        }
      }
    }

  }

  [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.Messages.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);
    }

    public const int PassedFieldNumber = 1;
    private bool passed_;
    public bool Passed {
      get { return passed_; }
      set {
        passed_ = value;
      }
    }

    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.Default.Format(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
