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

  namespace Proto {

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

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

      static Math() {
        byte[] descriptorData = global::System.Convert.FromBase64String(
            string.Concat(
              "CgptYXRoLnByb3RvEgRtYXRoIiwKB0RpdkFyZ3MSEAoIZGl2aWRlbmQYASAB", 
              "KAMSDwoHZGl2aXNvchgCIAEoAyIvCghEaXZSZXBseRIQCghxdW90aWVudBgB", 
              "IAEoAxIRCglyZW1haW5kZXIYAiABKAMiGAoHRmliQXJncxINCgVsaW1pdBgB", 
              "IAEoAyISCgNOdW0SCwoDbnVtGAEgASgDIhkKCEZpYlJlcGx5Eg0KBWNvdW50", 
              "GAEgASgDMqQBCgRNYXRoEiYKA0RpdhINLm1hdGguRGl2QXJncxoOLm1hdGgu", 
              "RGl2UmVwbHkiABIuCgdEaXZNYW55Eg0ubWF0aC5EaXZBcmdzGg4ubWF0aC5E", 
              "aXZSZXBseSIAKAEwARIjCgNGaWISDS5tYXRoLkZpYkFyZ3MaCS5tYXRoLk51", 
              "bSIAMAESHwoDU3VtEgkubWF0aC5OdW0aCS5tYXRoLk51bSIAKAFiBnByb3Rv", 
              "Mw=="));
        descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
            new pbr::FileDescriptor[] { },
            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
              new pbr::GeneratedCodeInfo(typeof(global::Math.DivArgs), new[]{ "Dividend", "Divisor" }, null, null, null),
              new pbr::GeneratedCodeInfo(typeof(global::Math.DivReply), new[]{ "Quotient", "Remainder" }, null, null, null),
              new pbr::GeneratedCodeInfo(typeof(global::Math.FibArgs), new[]{ "Limit" }, null, null, null),
              new pbr::GeneratedCodeInfo(typeof(global::Math.Num), new[]{ "Num_" }, null, null, null),
              new pbr::GeneratedCodeInfo(typeof(global::Math.FibReply), new[]{ "Count" }, null, null, null)
            }));
      }
      #endregion

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

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Math.Proto.Math.Descriptor.MessageTypes[0]; }
    }

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

    public DivArgs() {
      OnConstruction();
    }

    partial void OnConstruction();

    public DivArgs(DivArgs other) : this() {
      dividend_ = other.dividend_;
      divisor_ = other.divisor_;
    }

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

    public const int DividendFieldNumber = 1;
    private long dividend_;
    public long Dividend {
      get { return dividend_; }
      set {
        dividend_ = value;
      }
    }

    public const int DivisorFieldNumber = 2;
    private long divisor_;
    public long Divisor {
      get { return divisor_; }
      set {
        divisor_ = value;
      }
    }

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

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

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

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Dividend != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(Dividend);
      }
      if (Divisor != 0L) {
        output.WriteRawTag(16);
        output.WriteInt64(Divisor);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Dividend != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Dividend);
      }
      if (Divisor != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Divisor);
      }
      return size;
    }

    public void MergeFrom(DivArgs other) {
      if (other == null) {
        return;
      }
      if (other.Dividend != 0L) {
        Dividend = other.Dividend;
      }
      if (other.Divisor != 0L) {
        Divisor = other.Divisor;
      }
    }

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

  }

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

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Math.Proto.Math.Descriptor.MessageTypes[1]; }
    }

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

    public DivReply() {
      OnConstruction();
    }

    partial void OnConstruction();

    public DivReply(DivReply other) : this() {
      quotient_ = other.quotient_;
      remainder_ = other.remainder_;
    }

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

    public const int QuotientFieldNumber = 1;
    private long quotient_;
    public long Quotient {
      get { return quotient_; }
      set {
        quotient_ = value;
      }
    }

    public const int RemainderFieldNumber = 2;
    private long remainder_;
    public long Remainder {
      get { return remainder_; }
      set {
        remainder_ = value;
      }
    }

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

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

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

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Quotient != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(Quotient);
      }
      if (Remainder != 0L) {
        output.WriteRawTag(16);
        output.WriteInt64(Remainder);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Quotient != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Quotient);
      }
      if (Remainder != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Remainder);
      }
      return size;
    }

    public void MergeFrom(DivReply other) {
      if (other == null) {
        return;
      }
      if (other.Quotient != 0L) {
        Quotient = other.Quotient;
      }
      if (other.Remainder != 0L) {
        Remainder = other.Remainder;
      }
    }

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

  }

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

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Math.Proto.Math.Descriptor.MessageTypes[2]; }
    }

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

    public FibArgs() {
      OnConstruction();
    }

    partial void OnConstruction();

    public FibArgs(FibArgs other) : this() {
      limit_ = other.limit_;
    }

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

    public const int LimitFieldNumber = 1;
    private long limit_;
    public long Limit {
      get { return limit_; }
      set {
        limit_ = value;
      }
    }

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

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

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

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Limit != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(Limit);
      }
    }

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

    public void MergeFrom(FibArgs other) {
      if (other == null) {
        return;
      }
      if (other.Limit != 0L) {
        Limit = other.Limit;
      }
    }

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

  }

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

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Math.Proto.Math.Descriptor.MessageTypes[3]; }
    }

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

    public Num() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Num(Num other) : this() {
      num_ = other.num_;
    }

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

    public const int Num_FieldNumber = 1;
    private long num_;
    public long Num_ {
      get { return num_; }
      set {
        num_ = value;
      }
    }

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

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

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

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Num_ != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(Num_);
      }
    }

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

    public void MergeFrom(Num other) {
      if (other == null) {
        return;
      }
      if (other.Num_ != 0L) {
        Num_ = other.Num_;
      }
    }

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

  }

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

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Math.Proto.Math.Descriptor.MessageTypes[4]; }
    }

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

    public FibReply() {
      OnConstruction();
    }

    partial void OnConstruction();

    public FibReply(FibReply other) : this() {
      count_ = other.count_;
    }

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

    public const int CountFieldNumber = 1;
    private long count_;
    public long Count {
      get { return count_; }
      set {
        count_ = value;
      }
    }

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

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

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

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Count != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(Count);
      }
    }

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

    public void MergeFrom(FibReply other) {
      if (other == null) {
        return;
      }
      if (other.Count != 0L) {
        Count = other.Count;
      }
    }

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

  }

  #endregion

}

#endregion Designer generated code
