// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: google/protobuf/any.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 Google.Protobuf.WellKnownTypes {

  namespace Proto {

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

      #region Static variables
      internal static pbr::FieldAccessorTable internal__static_google_protobuf_Any__FieldAccessorTable;
      #endregion
      #region Descriptor
      public static pbr::FileDescriptor Descriptor {
        get { return descriptor; }
      }
      private static pbr::FileDescriptor descriptor;

      static Any() {
        byte[] descriptorData = global::System.Convert.FromBase64String(
            string.Concat(
              "Chlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvEg9nb29nbGUucHJvdG9idWYi", 
              "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQksKE2Nv", 
              "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAGgAQGiAgNHUEKqAh5Hb29n", 
            "bGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
        descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
            new pbr::FileDescriptor[] {
            });
        internal__static_google_protobuf_Any__FieldAccessorTable = 
            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Any), descriptor.MessageTypes[0],
                new string[] { "TypeUrl", "Value", }, new string[] { });
      }
      #endregion

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

    private static readonly string[] _fieldNames = new string[] { "type_url", "value" };
    private static readonly uint[] _fieldTags = new uint[] { 10, 18 };
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Google.Protobuf.WellKnownTypes.Proto.Any.Descriptor.MessageTypes[0]; }
    }

    pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
      get { return global::Google.Protobuf.WellKnownTypes.Proto.Any.internal__static_google_protobuf_Any__FieldAccessorTable; }
    }

    private bool _frozen = false;
    public bool IsFrozen { get { return _frozen; } }

    public Any() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Any(Any other) : this() {
      typeUrl_ = other.typeUrl_;
      value_ = other.value_;
    }

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

    public void Freeze() {
      if (IsFrozen) {
        return;
      }
      _frozen = true;
    }

    public const int TypeUrlFieldNumber = 1;
    private string typeUrl_ = "";
    public string TypeUrl {
      get { return typeUrl_; }
      set {
        pb::Freezable.CheckMutable(this);
        typeUrl_ = value ?? "";
      }
    }

    public const int ValueFieldNumber = 2;
    private pb::ByteString value_ = pb::ByteString.Empty;
    public pb::ByteString Value {
      get { return value_; }
      set {
        pb::Freezable.CheckMutable(this);
        value_ = value ?? pb::ByteString.Empty;
      }
    }

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

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

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

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (TypeUrl.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(TypeUrl);
      }
      if (Value.Length != 0) {
        output.WriteRawTag(18);
        output.WriteBytes(Value);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (TypeUrl.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(TypeUrl);
      }
      if (Value.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value);
      }
      return size;
    }

    public void MergeFrom(Any other) {
      if (other == null) {
        return;
      }
      if (other.TypeUrl.Length != 0) {
        TypeUrl = other.TypeUrl;
      }
      if (other.Value.Length != 0) {
        Value = other.Value;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 10: {
            TypeUrl = input.ReadString();
            break;
          }
          case 18: {
            Value = input.ReadBytes();
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
