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

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

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

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

    static StatsReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "CiJzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3N0YXRzLnByb3RvEgxncnBjLnRl",
            "c3RpbmcaH3NyYy9wcm90by9ncnBjL2NvcmUvc3RhdHMucHJvdG8itwEKC1Nl",
            "cnZlclN0YXRzEhQKDHRpbWVfZWxhcHNlZBgBIAEoARIRCgl0aW1lX3VzZXIY",
            "AiABKAESEwoLdGltZV9zeXN0ZW0YAyABKAESFgoOdG90YWxfY3B1X3RpbWUY",
            "BCABKAQSFQoNaWRsZV9jcHVfdGltZRgFIAEoBBIVCg1jcV9wb2xsX2NvdW50",
            "GAYgASgEEiQKCmNvcmVfc3RhdHMYByABKAsyEC5ncnBjLmNvcmUuU3RhdHMi",
            "OwoPSGlzdG9ncmFtUGFyYW1zEhIKCnJlc29sdXRpb24YASABKAESFAoMbWF4",
            "X3Bvc3NpYmxlGAIgASgBIncKDUhpc3RvZ3JhbURhdGESDgoGYnVja2V0GAEg",
            "AygNEhAKCG1pbl9zZWVuGAIgASgBEhAKCG1heF9zZWVuGAMgASgBEgsKA3N1",
            "bRgEIAEoARIWCg5zdW1fb2Zfc3F1YXJlcxgFIAEoARINCgVjb3VudBgGIAEo",
            "ASI4ChJSZXF1ZXN0UmVzdWx0Q291bnQSEwoLc3RhdHVzX2NvZGUYASABKAUS",
            "DQoFY291bnQYAiABKAMi8wEKC0NsaWVudFN0YXRzEi4KCWxhdGVuY2llcxgB",
            "IAEoCzIbLmdycGMudGVzdGluZy5IaXN0b2dyYW1EYXRhEhQKDHRpbWVfZWxh",
            "cHNlZBgCIAEoARIRCgl0aW1lX3VzZXIYAyABKAESEwoLdGltZV9zeXN0ZW0Y",
            "BCABKAESOQoPcmVxdWVzdF9yZXN1bHRzGAUgAygLMiAuZ3JwYy50ZXN0aW5n",
            "LlJlcXVlc3RSZXN1bHRDb3VudBIVCg1jcV9wb2xsX2NvdW50GAYgASgEEiQK",
            "CmNvcmVfc3RhdHMYByABKAsyEC5ncnBjLmNvcmUuU3RhdHNiBnByb3RvMw=="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { global::Grpc.Core.StatsReflection.Descriptor, },
          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStats), global::Grpc.Testing.ServerStats.Parser, new[]{ "TimeElapsed", "TimeUser", "TimeSystem", "TotalCpuTime", "IdleCpuTime", "CqPollCount", "CoreStats" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.HistogramParams), global::Grpc.Testing.HistogramParams.Parser, new[]{ "Resolution", "MaxPossible" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.HistogramData), global::Grpc.Testing.HistogramData.Parser, new[]{ "Bucket", "MinSeen", "MaxSeen", "Sum", "SumOfSquares", "Count" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.RequestResultCount), global::Grpc.Testing.RequestResultCount.Parser, new[]{ "StatusCode", "Count" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStats), global::Grpc.Testing.ClientStats.Parser, new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem", "RequestResults", "CqPollCount", "CoreStats" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Messages
  public sealed partial class ServerStats : pb::IMessage<ServerStats> {
    private static readonly pb::MessageParser<ServerStats> _parser = new pb::MessageParser<ServerStats>(() => new ServerStats());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ServerStats> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerStats(ServerStats other) : this() {
      timeElapsed_ = other.timeElapsed_;
      timeUser_ = other.timeUser_;
      timeSystem_ = other.timeSystem_;
      totalCpuTime_ = other.totalCpuTime_;
      idleCpuTime_ = other.idleCpuTime_;
      cqPollCount_ = other.cqPollCount_;
      coreStats_ = other.coreStats_ != null ? other.coreStats_.Clone() : null;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "time_elapsed" field.</summary>
    public const int TimeElapsedFieldNumber = 1;
    private double timeElapsed_;
    /// <summary>
    /// wall clock time change in seconds since last reset
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double TimeElapsed {
      get { return timeElapsed_; }
      set {
        timeElapsed_ = value;
      }
    }

    /// <summary>Field number for the "time_user" field.</summary>
    public const int TimeUserFieldNumber = 2;
    private double timeUser_;
    /// <summary>
    /// change in user time (in seconds) used by the server since last reset
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double TimeUser {
      get { return timeUser_; }
      set {
        timeUser_ = value;
      }
    }

    /// <summary>Field number for the "time_system" field.</summary>
    public const int TimeSystemFieldNumber = 3;
    private double timeSystem_;
    /// <summary>
    /// change in server time (in seconds) used by the server process and all
    /// threads since last reset
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double TimeSystem {
      get { return timeSystem_; }
      set {
        timeSystem_ = value;
      }
    }

    /// <summary>Field number for the "total_cpu_time" field.</summary>
    public const int TotalCpuTimeFieldNumber = 4;
    private ulong totalCpuTime_;
    /// <summary>
    /// change in total cpu time of the server (data from proc/stat)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ulong TotalCpuTime {
      get { return totalCpuTime_; }
      set {
        totalCpuTime_ = value;
      }
    }

    /// <summary>Field number for the "idle_cpu_time" field.</summary>
    public const int IdleCpuTimeFieldNumber = 5;
    private ulong idleCpuTime_;
    /// <summary>
    /// change in idle time of the server (data from proc/stat)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ulong IdleCpuTime {
      get { return idleCpuTime_; }
      set {
        idleCpuTime_ = value;
      }
    }

    /// <summary>Field number for the "cq_poll_count" field.</summary>
    public const int CqPollCountFieldNumber = 6;
    private ulong cqPollCount_;
    /// <summary>
    /// Number of polls called inside completion queue
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ulong CqPollCount {
      get { return cqPollCount_; }
      set {
        cqPollCount_ = value;
      }
    }

    /// <summary>Field number for the "core_stats" field.</summary>
    public const int CoreStatsFieldNumber = 7;
    private global::Grpc.Core.Stats coreStats_;
    /// <summary>
    /// Core library stats
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Core.Stats CoreStats {
      get { return coreStats_; }
      set {
        coreStats_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ServerStats other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeElapsed, other.TimeElapsed)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeUser, other.TimeUser)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeSystem, other.TimeSystem)) return false;
      if (TotalCpuTime != other.TotalCpuTime) return false;
      if (IdleCpuTime != other.IdleCpuTime) return false;
      if (CqPollCount != other.CqPollCount) return false;
      if (!object.Equals(CoreStats, other.CoreStats)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (TimeElapsed != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeElapsed);
      if (TimeUser != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeUser);
      if (TimeSystem != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeSystem);
      if (TotalCpuTime != 0UL) hash ^= TotalCpuTime.GetHashCode();
      if (IdleCpuTime != 0UL) hash ^= IdleCpuTime.GetHashCode();
      if (CqPollCount != 0UL) hash ^= CqPollCount.GetHashCode();
      if (coreStats_ != null) hash ^= CoreStats.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (TimeElapsed != 0D) {
        output.WriteRawTag(9);
        output.WriteDouble(TimeElapsed);
      }
      if (TimeUser != 0D) {
        output.WriteRawTag(17);
        output.WriteDouble(TimeUser);
      }
      if (TimeSystem != 0D) {
        output.WriteRawTag(25);
        output.WriteDouble(TimeSystem);
      }
      if (TotalCpuTime != 0UL) {
        output.WriteRawTag(32);
        output.WriteUInt64(TotalCpuTime);
      }
      if (IdleCpuTime != 0UL) {
        output.WriteRawTag(40);
        output.WriteUInt64(IdleCpuTime);
      }
      if (CqPollCount != 0UL) {
        output.WriteRawTag(48);
        output.WriteUInt64(CqPollCount);
      }
      if (coreStats_ != null) {
        output.WriteRawTag(58);
        output.WriteMessage(CoreStats);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (TimeElapsed != 0D) {
        size += 1 + 8;
      }
      if (TimeUser != 0D) {
        size += 1 + 8;
      }
      if (TimeSystem != 0D) {
        size += 1 + 8;
      }
      if (TotalCpuTime != 0UL) {
        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(TotalCpuTime);
      }
      if (IdleCpuTime != 0UL) {
        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(IdleCpuTime);
      }
      if (CqPollCount != 0UL) {
        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(CqPollCount);
      }
      if (coreStats_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(CoreStats);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ServerStats other) {
      if (other == null) {
        return;
      }
      if (other.TimeElapsed != 0D) {
        TimeElapsed = other.TimeElapsed;
      }
      if (other.TimeUser != 0D) {
        TimeUser = other.TimeUser;
      }
      if (other.TimeSystem != 0D) {
        TimeSystem = other.TimeSystem;
      }
      if (other.TotalCpuTime != 0UL) {
        TotalCpuTime = other.TotalCpuTime;
      }
      if (other.IdleCpuTime != 0UL) {
        IdleCpuTime = other.IdleCpuTime;
      }
      if (other.CqPollCount != 0UL) {
        CqPollCount = other.CqPollCount;
      }
      if (other.coreStats_ != null) {
        if (coreStats_ == null) {
          CoreStats = new global::Grpc.Core.Stats();
        }
        CoreStats.MergeFrom(other.CoreStats);
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 9: {
            TimeElapsed = input.ReadDouble();
            break;
          }
          case 17: {
            TimeUser = input.ReadDouble();
            break;
          }
          case 25: {
            TimeSystem = input.ReadDouble();
            break;
          }
          case 32: {
            TotalCpuTime = input.ReadUInt64();
            break;
          }
          case 40: {
            IdleCpuTime = input.ReadUInt64();
            break;
          }
          case 48: {
            CqPollCount = input.ReadUInt64();
            break;
          }
          case 58: {
            if (coreStats_ == null) {
              CoreStats = new global::Grpc.Core.Stats();
            }
            input.ReadMessage(CoreStats);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Histogram params based on grpc/support/histogram.c
  /// </summary>
  public sealed partial class HistogramParams : pb::IMessage<HistogramParams> {
    private static readonly pb::MessageParser<HistogramParams> _parser = new pb::MessageParser<HistogramParams>(() => new HistogramParams());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<HistogramParams> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

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

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

    /// <summary>Field number for the "resolution" field.</summary>
    public const int ResolutionFieldNumber = 1;
    private double resolution_;
    /// <summary>
    /// first bucket is [0, 1 + resolution)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Resolution {
      get { return resolution_; }
      set {
        resolution_ = value;
      }
    }

    /// <summary>Field number for the "max_possible" field.</summary>
    public const int MaxPossibleFieldNumber = 2;
    private double maxPossible_;
    /// <summary>
    /// use enough buckets to allow this value
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double MaxPossible {
      get { return maxPossible_; }
      set {
        maxPossible_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(HistogramParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Resolution, other.Resolution)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MaxPossible, other.MaxPossible)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Resolution != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Resolution);
      if (MaxPossible != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MaxPossible);
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Resolution != 0D) {
        output.WriteRawTag(9);
        output.WriteDouble(Resolution);
      }
      if (MaxPossible != 0D) {
        output.WriteRawTag(17);
        output.WriteDouble(MaxPossible);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(HistogramParams other) {
      if (other == null) {
        return;
      }
      if (other.Resolution != 0D) {
        Resolution = other.Resolution;
      }
      if (other.MaxPossible != 0D) {
        MaxPossible = other.MaxPossible;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 9: {
            Resolution = input.ReadDouble();
            break;
          }
          case 17: {
            MaxPossible = input.ReadDouble();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Histogram data based on grpc/support/histogram.c
  /// </summary>
  public sealed partial class HistogramData : pb::IMessage<HistogramData> {
    private static readonly pb::MessageParser<HistogramData> _parser = new pb::MessageParser<HistogramData>(() => new HistogramData());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<HistogramData> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public HistogramData(HistogramData other) : this() {
      bucket_ = other.bucket_.Clone();
      minSeen_ = other.minSeen_;
      maxSeen_ = other.maxSeen_;
      sum_ = other.sum_;
      sumOfSquares_ = other.sumOfSquares_;
      count_ = other.count_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "bucket" field.</summary>
    public const int BucketFieldNumber = 1;
    private static readonly pb::FieldCodec<uint> _repeated_bucket_codec
        = pb::FieldCodec.ForUInt32(10);
    private readonly pbc::RepeatedField<uint> bucket_ = new pbc::RepeatedField<uint>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<uint> Bucket {
      get { return bucket_; }
    }

    /// <summary>Field number for the "min_seen" field.</summary>
    public const int MinSeenFieldNumber = 2;
    private double minSeen_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double MinSeen {
      get { return minSeen_; }
      set {
        minSeen_ = value;
      }
    }

    /// <summary>Field number for the "max_seen" field.</summary>
    public const int MaxSeenFieldNumber = 3;
    private double maxSeen_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double MaxSeen {
      get { return maxSeen_; }
      set {
        maxSeen_ = value;
      }
    }

    /// <summary>Field number for the "sum" field.</summary>
    public const int SumFieldNumber = 4;
    private double sum_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Sum {
      get { return sum_; }
      set {
        sum_ = value;
      }
    }

    /// <summary>Field number for the "sum_of_squares" field.</summary>
    public const int SumOfSquaresFieldNumber = 5;
    private double sumOfSquares_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double SumOfSquares {
      get { return sumOfSquares_; }
      set {
        sumOfSquares_ = value;
      }
    }

    /// <summary>Field number for the "count" field.</summary>
    public const int CountFieldNumber = 6;
    private double count_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Count {
      get { return count_; }
      set {
        count_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(HistogramData other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if(!bucket_.Equals(other.bucket_)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MinSeen, other.MinSeen)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MaxSeen, other.MaxSeen)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Sum, other.Sum)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(SumOfSquares, other.SumOfSquares)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Count, other.Count)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= bucket_.GetHashCode();
      if (MinSeen != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MinSeen);
      if (MaxSeen != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MaxSeen);
      if (Sum != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Sum);
      if (SumOfSquares != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(SumOfSquares);
      if (Count != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Count);
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      bucket_.WriteTo(output, _repeated_bucket_codec);
      if (MinSeen != 0D) {
        output.WriteRawTag(17);
        output.WriteDouble(MinSeen);
      }
      if (MaxSeen != 0D) {
        output.WriteRawTag(25);
        output.WriteDouble(MaxSeen);
      }
      if (Sum != 0D) {
        output.WriteRawTag(33);
        output.WriteDouble(Sum);
      }
      if (SumOfSquares != 0D) {
        output.WriteRawTag(41);
        output.WriteDouble(SumOfSquares);
      }
      if (Count != 0D) {
        output.WriteRawTag(49);
        output.WriteDouble(Count);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      size += bucket_.CalculateSize(_repeated_bucket_codec);
      if (MinSeen != 0D) {
        size += 1 + 8;
      }
      if (MaxSeen != 0D) {
        size += 1 + 8;
      }
      if (Sum != 0D) {
        size += 1 + 8;
      }
      if (SumOfSquares != 0D) {
        size += 1 + 8;
      }
      if (Count != 0D) {
        size += 1 + 8;
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(HistogramData other) {
      if (other == null) {
        return;
      }
      bucket_.Add(other.bucket_);
      if (other.MinSeen != 0D) {
        MinSeen = other.MinSeen;
      }
      if (other.MaxSeen != 0D) {
        MaxSeen = other.MaxSeen;
      }
      if (other.Sum != 0D) {
        Sum = other.Sum;
      }
      if (other.SumOfSquares != 0D) {
        SumOfSquares = other.SumOfSquares;
      }
      if (other.Count != 0D) {
        Count = other.Count;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10:
          case 8: {
            bucket_.AddEntriesFrom(input, _repeated_bucket_codec);
            break;
          }
          case 17: {
            MinSeen = input.ReadDouble();
            break;
          }
          case 25: {
            MaxSeen = input.ReadDouble();
            break;
          }
          case 33: {
            Sum = input.ReadDouble();
            break;
          }
          case 41: {
            SumOfSquares = input.ReadDouble();
            break;
          }
          case 49: {
            Count = input.ReadDouble();
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

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

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

    /// <summary>Field number for the "status_code" field.</summary>
    public const int StatusCodeFieldNumber = 1;
    private int statusCode_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int StatusCode {
      get { return statusCode_; }
      set {
        statusCode_ = value;
      }
    }

    /// <summary>Field number for the "count" field.</summary>
    public const int CountFieldNumber = 2;
    private long count_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public long Count {
      get { return count_; }
      set {
        count_ = value;
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (StatusCode != 0) hash ^= StatusCode.GetHashCode();
      if (Count != 0L) hash ^= Count.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (StatusCode != 0) {
        output.WriteRawTag(8);
        output.WriteInt32(StatusCode);
      }
      if (Count != 0L) {
        output.WriteRawTag(16);
        output.WriteInt64(Count);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(RequestResultCount other) {
      if (other == null) {
        return;
      }
      if (other.StatusCode != 0) {
        StatusCode = other.StatusCode;
      }
      if (other.Count != 0L) {
        Count = other.Count;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

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

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientStats(ClientStats other) : this() {
      latencies_ = other.latencies_ != null ? other.latencies_.Clone() : null;
      timeElapsed_ = other.timeElapsed_;
      timeUser_ = other.timeUser_;
      timeSystem_ = other.timeSystem_;
      requestResults_ = other.requestResults_.Clone();
      cqPollCount_ = other.cqPollCount_;
      coreStats_ = other.coreStats_ != null ? other.coreStats_.Clone() : null;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "latencies" field.</summary>
    public const int LatenciesFieldNumber = 1;
    private global::Grpc.Testing.HistogramData latencies_;
    /// <summary>
    /// Latency histogram. Data points are in nanoseconds.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.HistogramData Latencies {
      get { return latencies_; }
      set {
        latencies_ = value;
      }
    }

    /// <summary>Field number for the "time_elapsed" field.</summary>
    public const int TimeElapsedFieldNumber = 2;
    private double timeElapsed_;
    /// <summary>
    /// See ServerStats for details.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double TimeElapsed {
      get { return timeElapsed_; }
      set {
        timeElapsed_ = value;
      }
    }

    /// <summary>Field number for the "time_user" field.</summary>
    public const int TimeUserFieldNumber = 3;
    private double timeUser_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double TimeUser {
      get { return timeUser_; }
      set {
        timeUser_ = value;
      }
    }

    /// <summary>Field number for the "time_system" field.</summary>
    public const int TimeSystemFieldNumber = 4;
    private double timeSystem_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double TimeSystem {
      get { return timeSystem_; }
      set {
        timeSystem_ = value;
      }
    }

    /// <summary>Field number for the "request_results" field.</summary>
    public const int RequestResultsFieldNumber = 5;
    private static readonly pb::FieldCodec<global::Grpc.Testing.RequestResultCount> _repeated_requestResults_codec
        = pb::FieldCodec.ForMessage(42, global::Grpc.Testing.RequestResultCount.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> requestResults_ = new pbc::RepeatedField<global::Grpc.Testing.RequestResultCount>();
    /// <summary>
    /// Number of failed requests (one row per status code seen)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> RequestResults {
      get { return requestResults_; }
    }

    /// <summary>Field number for the "cq_poll_count" field.</summary>
    public const int CqPollCountFieldNumber = 6;
    private ulong cqPollCount_;
    /// <summary>
    /// Number of polls called inside completion queue
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ulong CqPollCount {
      get { return cqPollCount_; }
      set {
        cqPollCount_ = value;
      }
    }

    /// <summary>Field number for the "core_stats" field.</summary>
    public const int CoreStatsFieldNumber = 7;
    private global::Grpc.Core.Stats coreStats_;
    /// <summary>
    /// Core library stats
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Core.Stats CoreStats {
      get { return coreStats_; }
      set {
        coreStats_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ClientStats other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Latencies, other.Latencies)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeElapsed, other.TimeElapsed)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeUser, other.TimeUser)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeSystem, other.TimeSystem)) return false;
      if(!requestResults_.Equals(other.requestResults_)) return false;
      if (CqPollCount != other.CqPollCount) return false;
      if (!object.Equals(CoreStats, other.CoreStats)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (latencies_ != null) hash ^= Latencies.GetHashCode();
      if (TimeElapsed != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeElapsed);
      if (TimeUser != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeUser);
      if (TimeSystem != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeSystem);
      hash ^= requestResults_.GetHashCode();
      if (CqPollCount != 0UL) hash ^= CqPollCount.GetHashCode();
      if (coreStats_ != null) hash ^= CoreStats.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (latencies_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Latencies);
      }
      if (TimeElapsed != 0D) {
        output.WriteRawTag(17);
        output.WriteDouble(TimeElapsed);
      }
      if (TimeUser != 0D) {
        output.WriteRawTag(25);
        output.WriteDouble(TimeUser);
      }
      if (TimeSystem != 0D) {
        output.WriteRawTag(33);
        output.WriteDouble(TimeSystem);
      }
      requestResults_.WriteTo(output, _repeated_requestResults_codec);
      if (CqPollCount != 0UL) {
        output.WriteRawTag(48);
        output.WriteUInt64(CqPollCount);
      }
      if (coreStats_ != null) {
        output.WriteRawTag(58);
        output.WriteMessage(CoreStats);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (latencies_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies);
      }
      if (TimeElapsed != 0D) {
        size += 1 + 8;
      }
      if (TimeUser != 0D) {
        size += 1 + 8;
      }
      if (TimeSystem != 0D) {
        size += 1 + 8;
      }
      size += requestResults_.CalculateSize(_repeated_requestResults_codec);
      if (CqPollCount != 0UL) {
        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(CqPollCount);
      }
      if (coreStats_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(CoreStats);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ClientStats other) {
      if (other == null) {
        return;
      }
      if (other.latencies_ != null) {
        if (latencies_ == null) {
          Latencies = new global::Grpc.Testing.HistogramData();
        }
        Latencies.MergeFrom(other.Latencies);
      }
      if (other.TimeElapsed != 0D) {
        TimeElapsed = other.TimeElapsed;
      }
      if (other.TimeUser != 0D) {
        TimeUser = other.TimeUser;
      }
      if (other.TimeSystem != 0D) {
        TimeSystem = other.TimeSystem;
      }
      requestResults_.Add(other.requestResults_);
      if (other.CqPollCount != 0UL) {
        CqPollCount = other.CqPollCount;
      }
      if (other.coreStats_ != null) {
        if (coreStats_ == null) {
          CoreStats = new global::Grpc.Core.Stats();
        }
        CoreStats.MergeFrom(other.CoreStats);
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            if (latencies_ == null) {
              Latencies = new global::Grpc.Testing.HistogramData();
            }
            input.ReadMessage(Latencies);
            break;
          }
          case 17: {
            TimeElapsed = input.ReadDouble();
            break;
          }
          case 25: {
            TimeUser = input.ReadDouble();
            break;
          }
          case 33: {
            TimeSystem = input.ReadDouble();
            break;
          }
          case 42: {
            requestResults_.AddEntriesFrom(input, _repeated_requestResults_codec);
            break;
          }
          case 48: {
            CqPollCount = input.ReadUInt64();
            break;
          }
          case 58: {
            if (coreStats_ == null) {
              CoreStats = new global::Grpc.Core.Stats();
            }
            input.ReadMessage(CoreStats);
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
