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

  /// <summary>Holder for reflection information generated from google/protobuf/type.proto</summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public static partial class TypeReflection {

    #region Descriptor
    /// <summary>File descriptor for google/protobuf/type.proto</summary>
    public static pbr::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbr::FileDescriptor descriptor;

    static TypeReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "Chpnb29nbGUvcHJvdG9idWYvdHlwZS5wcm90bxIPZ29vZ2xlLnByb3RvYnVm",
            "Ghlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvGiRnb29nbGUvcHJvdG9idWYv",
            "c291cmNlX2NvbnRleHQucHJvdG8i1wEKBFR5cGUSDAoEbmFtZRgBIAEoCRIm",
            "CgZmaWVsZHMYAiADKAsyFi5nb29nbGUucHJvdG9idWYuRmllbGQSDgoGb25l",
            "b2ZzGAMgAygJEigKB29wdGlvbnMYBCADKAsyFy5nb29nbGUucHJvdG9idWYu",
            "T3B0aW9uEjYKDnNvdXJjZV9jb250ZXh0GAUgASgLMh4uZ29vZ2xlLnByb3Rv",
            "YnVmLlNvdXJjZUNvbnRleHQSJwoGc3ludGF4GAYgASgOMhcuZ29vZ2xlLnBy",
            "b3RvYnVmLlN5bnRheCK+BQoFRmllbGQSKQoEa2luZBgBIAEoDjIbLmdvb2ds",
            "ZS5wcm90b2J1Zi5GaWVsZC5LaW5kEjcKC2NhcmRpbmFsaXR5GAIgASgOMiIu",
            "Z29vZ2xlLnByb3RvYnVmLkZpZWxkLkNhcmRpbmFsaXR5Eg4KBm51bWJlchgD",
            "IAEoBRIMCgRuYW1lGAQgASgJEhAKCHR5cGVfdXJsGAYgASgJEhMKC29uZW9m",
            "X2luZGV4GAcgASgFEg4KBnBhY2tlZBgIIAEoCBIoCgdvcHRpb25zGAkgAygL",
            "MhcuZ29vZ2xlLnByb3RvYnVmLk9wdGlvbhIRCglqc29uX25hbWUYCiABKAki",
            "yAIKBEtpbmQSEAoMVFlQRV9VTktOT1dOEAASDwoLVFlQRV9ET1VCTEUQARIO",
            "CgpUWVBFX0ZMT0FUEAISDgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0",
            "EAQSDgoKVFlQRV9JTlQzMhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVf",
            "RklYRUQzMhAHEg0KCVRZUEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSDgoK",
            "VFlQRV9HUk9VUBAKEhAKDFRZUEVfTUVTU0FHRRALEg4KClRZUEVfQllURVMQ",
            "DBIPCgtUWVBFX1VJTlQzMhANEg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVfU0ZJ",
            "WEVEMzIQDxIRCg1UWVBFX1NGSVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQERIP",
            "CgtUWVBFX1NJTlQ2NBASInQKC0NhcmRpbmFsaXR5EhcKE0NBUkRJTkFMSVRZ",
            "X1VOS05PV04QABIYChRDQVJESU5BTElUWV9PUFRJT05BTBABEhgKFENBUkRJ",
            "TkFMSVRZX1JFUVVJUkVEEAISGAoUQ0FSRElOQUxJVFlfUkVQRUFURUQQAyLO",
            "AQoERW51bRIMCgRuYW1lGAEgASgJEi0KCWVudW12YWx1ZRgCIAMoCzIaLmdv",
            "b2dsZS5wcm90b2J1Zi5FbnVtVmFsdWUSKAoHb3B0aW9ucxgDIAMoCzIXLmdv",
            "b2dsZS5wcm90b2J1Zi5PcHRpb24SNgoOc291cmNlX2NvbnRleHQYBCABKAsy",
            "Hi5nb29nbGUucHJvdG9idWYuU291cmNlQ29udGV4dBInCgZzeW50YXgYBSAB",
            "KA4yFy5nb29nbGUucHJvdG9idWYuU3ludGF4IlMKCUVudW1WYWx1ZRIMCgRu",
            "YW1lGAEgASgJEg4KBm51bWJlchgCIAEoBRIoCgdvcHRpb25zGAMgAygLMhcu",
            "Z29vZ2xlLnByb3RvYnVmLk9wdGlvbiI7CgZPcHRpb24SDAoEbmFtZRgBIAEo",
            "CRIjCgV2YWx1ZRgCIAEoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnkqLgoGU3lu",
            "dGF4EhEKDVNZTlRBWF9QUk9UTzIQABIRCg1TWU5UQVhfUFJPVE8zEAFCTAoT",
            "Y29tLmdvb2dsZS5wcm90b2J1ZkIJVHlwZVByb3RvUAGgAQGiAgNHUEKqAh5H",
            "b29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
          new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, },
          new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.Syntax), }, new pbr::GeneratedCodeInfo[] {
            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Type), global::Google.Protobuf.WellKnownTypes.Type.Parser, new[]{ "Name", "Fields", "Oneofs", "Options", "SourceContext", "Syntax" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Field), global::Google.Protobuf.WellKnownTypes.Field.Parser, new[]{ "Kind", "Cardinality", "Number", "Name", "TypeUrl", "OneofIndex", "Packed", "Options", "JsonName" }, null, new[]{ typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Kind), typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) }, null),
            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Enum), global::Google.Protobuf.WellKnownTypes.Enum.Parser, new[]{ "Name", "Enumvalue", "Options", "SourceContext", "Syntax" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.EnumValue), global::Google.Protobuf.WellKnownTypes.EnumValue.Parser, new[]{ "Name", "Number", "Options" }, null, null, null),
            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Option), global::Google.Protobuf.WellKnownTypes.Option.Parser, new[]{ "Name", "Value" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Enums
  /// <summary>
  ///  Syntax specifies the syntax in which a service element was defined.
  /// </summary>
  public enum Syntax {
    /// <summary>
    ///  Syntax "proto2"
    /// </summary>
    SYNTAX_PROTO2 = 0,
    /// <summary>
    ///  Syntax "proto3"
    /// </summary>
    SYNTAX_PROTO3 = 1,
  }

  #endregion

  #region Messages
  /// <summary>
  ///  A light-weight descriptor for a proto message type.
  /// </summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class Type : pb::IMessage<Type> {
    private static readonly pb::MessageParser<Type> _parser = new pb::MessageParser<Type>(() => new Type());
    public static pb::MessageParser<Type> Parser { get { return _parser; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[0]; }
    }

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

    public Type() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Type(Type other) : this() {
      name_ = other.name_;
      fields_ = other.fields_.Clone();
      oneofs_ = other.oneofs_.Clone();
      options_ = other.options_.Clone();
      SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
      syntax_ = other.syntax_;
    }

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

    /// <summary>Field number for the "name" field.</summary>
    public const int NameFieldNumber = 1;
    private string name_ = "";
    /// <summary>
    ///  The fully qualified message name.
    /// </summary>
    public string Name {
      get { return name_; }
      set {
        name_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "fields" field.</summary>
    public const int FieldsFieldNumber = 2;
    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Field> _repeated_fields_codec
        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Field.Parser);
    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Field> fields_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Field>();
    /// <summary>
    ///  The list of fields.
    /// </summary>
    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Field> Fields {
      get { return fields_; }
    }

    /// <summary>Field number for the "oneofs" field.</summary>
    public const int OneofsFieldNumber = 3;
    private static readonly pb::FieldCodec<string> _repeated_oneofs_codec
        = pb::FieldCodec.ForString(26);
    private readonly pbc::RepeatedField<string> oneofs_ = new pbc::RepeatedField<string>();
    /// <summary>
    ///  The list of oneof definitions.
    /// </summary>
    public pbc::RepeatedField<string> Oneofs {
      get { return oneofs_; }
    }

    /// <summary>Field number for the "options" field.</summary>
    public const int OptionsFieldNumber = 4;
    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Option> _repeated_options_codec
        = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.WellKnownTypes.Option.Parser);
    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
    /// <summary>
    ///  The proto options.
    /// </summary>
    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
      get { return options_; }
    }

    /// <summary>Field number for the "source_context" field.</summary>
    public const int SourceContextFieldNumber = 5;
    private global::Google.Protobuf.WellKnownTypes.SourceContext sourceContext_;
    /// <summary>
    ///  The source context.
    /// </summary>
    public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContext {
      get { return sourceContext_; }
      set {
        sourceContext_ = value;
      }
    }

    /// <summary>Field number for the "syntax" field.</summary>
    public const int SyntaxFieldNumber = 6;
    private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2;
    /// <summary>
    ///  The source syntax.
    /// </summary>
    public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
      get { return syntax_; }
      set {
        syntax_ = value;
      }
    }

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

    public bool Equals(Type other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Name != other.Name) return false;
      if(!fields_.Equals(other.fields_)) return false;
      if(!oneofs_.Equals(other.oneofs_)) return false;
      if(!options_.Equals(other.options_)) return false;
      if (!object.Equals(SourceContext, other.SourceContext)) return false;
      if (Syntax != other.Syntax) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Name.Length != 0) hash ^= Name.GetHashCode();
      hash ^= fields_.GetHashCode();
      hash ^= oneofs_.GetHashCode();
      hash ^= options_.GetHashCode();
      if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
      if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) hash ^= Syntax.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Name.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Name);
      }
      fields_.WriteTo(output, _repeated_fields_codec);
      oneofs_.WriteTo(output, _repeated_oneofs_codec);
      options_.WriteTo(output, _repeated_options_codec);
      if (sourceContext_ != null) {
        output.WriteRawTag(42);
        output.WriteMessage(SourceContext);
      }
      if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
        output.WriteRawTag(48);
        output.WriteEnum((int) Syntax);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Name.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
      }
      size += fields_.CalculateSize(_repeated_fields_codec);
      size += oneofs_.CalculateSize(_repeated_oneofs_codec);
      size += options_.CalculateSize(_repeated_options_codec);
      if (sourceContext_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext);
      }
      if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
      }
      return size;
    }

    public void MergeFrom(Type other) {
      if (other == null) {
        return;
      }
      if (other.Name.Length != 0) {
        Name = other.Name;
      }
      fields_.Add(other.fields_);
      oneofs_.Add(other.oneofs_);
      options_.Add(other.options_);
      if (other.sourceContext_ != null) {
        if (sourceContext_ == null) {
          sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
        }
        SourceContext.MergeFrom(other.SourceContext);
      }
      if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
        Syntax = other.Syntax;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            Name = input.ReadString();
            break;
          }
          case 18: {
            fields_.AddEntriesFrom(input, _repeated_fields_codec);
            break;
          }
          case 26: {
            oneofs_.AddEntriesFrom(input, _repeated_oneofs_codec);
            break;
          }
          case 34: {
            options_.AddEntriesFrom(input, _repeated_options_codec);
            break;
          }
          case 42: {
            if (sourceContext_ == null) {
              sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
            }
            input.ReadMessage(sourceContext_);
            break;
          }
          case 48: {
            syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  ///  Field represents a single field of a message type.
  /// </summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class Field : pb::IMessage<Field> {
    private static readonly pb::MessageParser<Field> _parser = new pb::MessageParser<Field>(() => new Field());
    public static pb::MessageParser<Field> Parser { get { return _parser; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[1]; }
    }

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

    public Field() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Field(Field other) : this() {
      kind_ = other.kind_;
      cardinality_ = other.cardinality_;
      number_ = other.number_;
      name_ = other.name_;
      typeUrl_ = other.typeUrl_;
      oneofIndex_ = other.oneofIndex_;
      packed_ = other.packed_;
      options_ = other.options_.Clone();
      jsonName_ = other.jsonName_;
    }

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

    /// <summary>Field number for the "kind" field.</summary>
    public const int KindFieldNumber = 1;
    private global::Google.Protobuf.WellKnownTypes.Field.Types.Kind kind_ = global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN;
    /// <summary>
    ///  The field kind.
    /// </summary>
    public global::Google.Protobuf.WellKnownTypes.Field.Types.Kind Kind {
      get { return kind_; }
      set {
        kind_ = value;
      }
    }

    /// <summary>Field number for the "cardinality" field.</summary>
    public const int CardinalityFieldNumber = 2;
    private global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality cardinality_ = global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN;
    /// <summary>
    ///  The field cardinality, i.e. optional/required/repeated.
    /// </summary>
    public global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality Cardinality {
      get { return cardinality_; }
      set {
        cardinality_ = value;
      }
    }

    /// <summary>Field number for the "number" field.</summary>
    public const int NumberFieldNumber = 3;
    private int number_;
    /// <summary>
    ///  The proto field number.
    /// </summary>
    public int Number {
      get { return number_; }
      set {
        number_ = value;
      }
    }

    /// <summary>Field number for the "name" field.</summary>
    public const int NameFieldNumber = 4;
    private string name_ = "";
    /// <summary>
    ///  The field name.
    /// </summary>
    public string Name {
      get { return name_; }
      set {
        name_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "type_url" field.</summary>
    public const int TypeUrlFieldNumber = 6;
    private string typeUrl_ = "";
    /// <summary>
    ///  The type URL (without the scheme) when the type is MESSAGE or ENUM,
    ///  such as `type.googleapis.com/google.protobuf.Empty`.
    /// </summary>
    public string TypeUrl {
      get { return typeUrl_; }
      set {
        typeUrl_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "oneof_index" field.</summary>
    public const int OneofIndexFieldNumber = 7;
    private int oneofIndex_;
    /// <summary>
    ///  Index in Type.oneofs. Starts at 1. Zero means no oneof mapping.
    /// </summary>
    public int OneofIndex {
      get { return oneofIndex_; }
      set {
        oneofIndex_ = value;
      }
    }

    /// <summary>Field number for the "packed" field.</summary>
    public const int PackedFieldNumber = 8;
    private bool packed_;
    /// <summary>
    ///  Whether to use alternative packed wire representation.
    /// </summary>
    public bool Packed {
      get { return packed_; }
      set {
        packed_ = value;
      }
    }

    /// <summary>Field number for the "options" field.</summary>
    public const int OptionsFieldNumber = 9;
    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Option> _repeated_options_codec
        = pb::FieldCodec.ForMessage(74, global::Google.Protobuf.WellKnownTypes.Option.Parser);
    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
    /// <summary>
    ///  The proto options.
    /// </summary>
    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
      get { return options_; }
    }

    /// <summary>Field number for the "json_name" field.</summary>
    public const int JsonNameFieldNumber = 10;
    private string jsonName_ = "";
    /// <summary>
    ///  The JSON name for this field.
    /// </summary>
    public string JsonName {
      get { return jsonName_; }
      set {
        jsonName_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

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

    public bool Equals(Field other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Kind != other.Kind) return false;
      if (Cardinality != other.Cardinality) return false;
      if (Number != other.Number) return false;
      if (Name != other.Name) return false;
      if (TypeUrl != other.TypeUrl) return false;
      if (OneofIndex != other.OneofIndex) return false;
      if (Packed != other.Packed) return false;
      if(!options_.Equals(other.options_)) return false;
      if (JsonName != other.JsonName) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN) hash ^= Kind.GetHashCode();
      if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN) hash ^= Cardinality.GetHashCode();
      if (Number != 0) hash ^= Number.GetHashCode();
      if (Name.Length != 0) hash ^= Name.GetHashCode();
      if (TypeUrl.Length != 0) hash ^= TypeUrl.GetHashCode();
      if (OneofIndex != 0) hash ^= OneofIndex.GetHashCode();
      if (Packed != false) hash ^= Packed.GetHashCode();
      hash ^= options_.GetHashCode();
      if (JsonName.Length != 0) hash ^= JsonName.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN) {
        output.WriteRawTag(8);
        output.WriteEnum((int) Kind);
      }
      if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN) {
        output.WriteRawTag(16);
        output.WriteEnum((int) Cardinality);
      }
      if (Number != 0) {
        output.WriteRawTag(24);
        output.WriteInt32(Number);
      }
      if (Name.Length != 0) {
        output.WriteRawTag(34);
        output.WriteString(Name);
      }
      if (TypeUrl.Length != 0) {
        output.WriteRawTag(50);
        output.WriteString(TypeUrl);
      }
      if (OneofIndex != 0) {
        output.WriteRawTag(56);
        output.WriteInt32(OneofIndex);
      }
      if (Packed != false) {
        output.WriteRawTag(64);
        output.WriteBool(Packed);
      }
      options_.WriteTo(output, _repeated_options_codec);
      if (JsonName.Length != 0) {
        output.WriteRawTag(82);
        output.WriteString(JsonName);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Kind);
      }
      if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Cardinality);
      }
      if (Number != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
      }
      if (Name.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
      }
      if (TypeUrl.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(TypeUrl);
      }
      if (OneofIndex != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OneofIndex);
      }
      if (Packed != false) {
        size += 1 + 1;
      }
      size += options_.CalculateSize(_repeated_options_codec);
      if (JsonName.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonName);
      }
      return size;
    }

    public void MergeFrom(Field other) {
      if (other == null) {
        return;
      }
      if (other.Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN) {
        Kind = other.Kind;
      }
      if (other.Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN) {
        Cardinality = other.Cardinality;
      }
      if (other.Number != 0) {
        Number = other.Number;
      }
      if (other.Name.Length != 0) {
        Name = other.Name;
      }
      if (other.TypeUrl.Length != 0) {
        TypeUrl = other.TypeUrl;
      }
      if (other.OneofIndex != 0) {
        OneofIndex = other.OneofIndex;
      }
      if (other.Packed != false) {
        Packed = other.Packed;
      }
      options_.Add(other.options_);
      if (other.JsonName.Length != 0) {
        JsonName = other.JsonName;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            kind_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
            break;
          }
          case 16: {
            cardinality_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) input.ReadEnum();
            break;
          }
          case 24: {
            Number = input.ReadInt32();
            break;
          }
          case 34: {
            Name = input.ReadString();
            break;
          }
          case 50: {
            TypeUrl = input.ReadString();
            break;
          }
          case 56: {
            OneofIndex = input.ReadInt32();
            break;
          }
          case 64: {
            Packed = input.ReadBool();
            break;
          }
          case 74: {
            options_.AddEntriesFrom(input, _repeated_options_codec);
            break;
          }
          case 82: {
            JsonName = input.ReadString();
            break;
          }
        }
      }
    }

    #region Nested types
    /// <summary>Container for nested types declared in the Field message type.</summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      /// <summary>
      ///  Kind represents a basic field type.
      /// </summary>
      public enum Kind {
        /// <summary>
        ///  Field type unknown.
        /// </summary>
        TYPE_UNKNOWN = 0,
        /// <summary>
        ///  Field type double.
        /// </summary>
        TYPE_DOUBLE = 1,
        /// <summary>
        ///  Field type float.
        /// </summary>
        TYPE_FLOAT = 2,
        /// <summary>
        ///  Field type int64.
        /// </summary>
        TYPE_INT64 = 3,
        /// <summary>
        ///  Field type uint64.
        /// </summary>
        TYPE_UINT64 = 4,
        /// <summary>
        ///  Field type int32.
        /// </summary>
        TYPE_INT32 = 5,
        /// <summary>
        ///  Field type fixed64.
        /// </summary>
        TYPE_FIXED64 = 6,
        /// <summary>
        ///  Field type fixed32.
        /// </summary>
        TYPE_FIXED32 = 7,
        /// <summary>
        ///  Field type bool.
        /// </summary>
        TYPE_BOOL = 8,
        /// <summary>
        ///  Field type string.
        /// </summary>
        TYPE_STRING = 9,
        /// <summary>
        ///  Field type group (deprecated proto2 type)
        /// </summary>
        TYPE_GROUP = 10,
        /// <summary>
        ///  Field type message.
        /// </summary>
        TYPE_MESSAGE = 11,
        /// <summary>
        ///  Field type bytes.
        /// </summary>
        TYPE_BYTES = 12,
        /// <summary>
        ///  Field type uint32.
        /// </summary>
        TYPE_UINT32 = 13,
        /// <summary>
        ///  Field type enum.
        /// </summary>
        TYPE_ENUM = 14,
        /// <summary>
        ///  Field type sfixed32.
        /// </summary>
        TYPE_SFIXED32 = 15,
        /// <summary>
        ///  Field type sfixed64.
        /// </summary>
        TYPE_SFIXED64 = 16,
        /// <summary>
        ///  Field type sint32.
        /// </summary>
        TYPE_SINT32 = 17,
        /// <summary>
        ///  Field type sint64.
        /// </summary>
        TYPE_SINT64 = 18,
      }

      /// <summary>
      ///  Cardinality represents whether a field is optional, required, or
      ///  repeated.
      /// </summary>
      public enum Cardinality {
        /// <summary>
        ///  The field cardinality is unknown. Typically an error condition.
        /// </summary>
        CARDINALITY_UNKNOWN = 0,
        /// <summary>
        ///  For optional fields.
        /// </summary>
        CARDINALITY_OPTIONAL = 1,
        /// <summary>
        ///  For required fields. Not used for proto3.
        /// </summary>
        CARDINALITY_REQUIRED = 2,
        /// <summary>
        ///  For repeated fields.
        /// </summary>
        CARDINALITY_REPEATED = 3,
      }

    }
    #endregion

  }

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

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[2]; }
    }

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

    public Enum() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Enum(Enum other) : this() {
      name_ = other.name_;
      enumvalue_ = other.enumvalue_.Clone();
      options_ = other.options_.Clone();
      SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
      syntax_ = other.syntax_;
    }

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

    /// <summary>Field number for the "name" field.</summary>
    public const int NameFieldNumber = 1;
    private string name_ = "";
    /// <summary>
    ///  Enum type name.
    /// </summary>
    public string Name {
      get { return name_; }
      set {
        name_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "enumvalue" field.</summary>
    public const int EnumvalueFieldNumber = 2;
    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.EnumValue> _repeated_enumvalue_codec
        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.EnumValue.Parser);
    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.EnumValue> enumvalue_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.EnumValue>();
    /// <summary>
    ///  Enum value definitions.
    /// </summary>
    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.EnumValue> Enumvalue {
      get { return enumvalue_; }
    }

    /// <summary>Field number for the "options" field.</summary>
    public const int OptionsFieldNumber = 3;
    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Option> _repeated_options_codec
        = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Option.Parser);
    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
    /// <summary>
    ///  Proto options for the enum type.
    /// </summary>
    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
      get { return options_; }
    }

    /// <summary>Field number for the "source_context" field.</summary>
    public const int SourceContextFieldNumber = 4;
    private global::Google.Protobuf.WellKnownTypes.SourceContext sourceContext_;
    /// <summary>
    ///  The source context.
    /// </summary>
    public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContext {
      get { return sourceContext_; }
      set {
        sourceContext_ = value;
      }
    }

    /// <summary>Field number for the "syntax" field.</summary>
    public const int SyntaxFieldNumber = 5;
    private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2;
    /// <summary>
    ///  The source syntax.
    /// </summary>
    public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
      get { return syntax_; }
      set {
        syntax_ = value;
      }
    }

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

    public bool Equals(Enum other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Name != other.Name) return false;
      if(!enumvalue_.Equals(other.enumvalue_)) return false;
      if(!options_.Equals(other.options_)) return false;
      if (!object.Equals(SourceContext, other.SourceContext)) return false;
      if (Syntax != other.Syntax) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Name.Length != 0) hash ^= Name.GetHashCode();
      hash ^= enumvalue_.GetHashCode();
      hash ^= options_.GetHashCode();
      if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
      if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) hash ^= Syntax.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Name.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Name);
      }
      enumvalue_.WriteTo(output, _repeated_enumvalue_codec);
      options_.WriteTo(output, _repeated_options_codec);
      if (sourceContext_ != null) {
        output.WriteRawTag(34);
        output.WriteMessage(SourceContext);
      }
      if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
        output.WriteRawTag(40);
        output.WriteEnum((int) Syntax);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Name.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
      }
      size += enumvalue_.CalculateSize(_repeated_enumvalue_codec);
      size += options_.CalculateSize(_repeated_options_codec);
      if (sourceContext_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext);
      }
      if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
      }
      return size;
    }

    public void MergeFrom(Enum other) {
      if (other == null) {
        return;
      }
      if (other.Name.Length != 0) {
        Name = other.Name;
      }
      enumvalue_.Add(other.enumvalue_);
      options_.Add(other.options_);
      if (other.sourceContext_ != null) {
        if (sourceContext_ == null) {
          sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
        }
        SourceContext.MergeFrom(other.SourceContext);
      }
      if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
        Syntax = other.Syntax;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            Name = input.ReadString();
            break;
          }
          case 18: {
            enumvalue_.AddEntriesFrom(input, _repeated_enumvalue_codec);
            break;
          }
          case 26: {
            options_.AddEntriesFrom(input, _repeated_options_codec);
            break;
          }
          case 34: {
            if (sourceContext_ == null) {
              sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
            }
            input.ReadMessage(sourceContext_);
            break;
          }
          case 40: {
            syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
            break;
          }
        }
      }
    }

  }

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

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[3]; }
    }

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

    public EnumValue() {
      OnConstruction();
    }

    partial void OnConstruction();

    public EnumValue(EnumValue other) : this() {
      name_ = other.name_;
      number_ = other.number_;
      options_ = other.options_.Clone();
    }

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

    /// <summary>Field number for the "name" field.</summary>
    public const int NameFieldNumber = 1;
    private string name_ = "";
    /// <summary>
    ///  Enum value name.
    /// </summary>
    public string Name {
      get { return name_; }
      set {
        name_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "number" field.</summary>
    public const int NumberFieldNumber = 2;
    private int number_;
    /// <summary>
    ///  Enum value number.
    /// </summary>
    public int Number {
      get { return number_; }
      set {
        number_ = value;
      }
    }

    /// <summary>Field number for the "options" field.</summary>
    public const int OptionsFieldNumber = 3;
    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Option> _repeated_options_codec
        = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Option.Parser);
    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
    /// <summary>
    ///  Proto options for the enum value.
    /// </summary>
    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
      get { return options_; }
    }

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

    public bool Equals(EnumValue other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Name != other.Name) return false;
      if (Number != other.Number) return false;
      if(!options_.Equals(other.options_)) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Name.Length != 0) hash ^= Name.GetHashCode();
      if (Number != 0) hash ^= Number.GetHashCode();
      hash ^= options_.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Name.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Name);
      }
      if (Number != 0) {
        output.WriteRawTag(16);
        output.WriteInt32(Number);
      }
      options_.WriteTo(output, _repeated_options_codec);
    }

    public int CalculateSize() {
      int size = 0;
      if (Name.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
      }
      if (Number != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
      }
      size += options_.CalculateSize(_repeated_options_codec);
      return size;
    }

    public void MergeFrom(EnumValue other) {
      if (other == null) {
        return;
      }
      if (other.Name.Length != 0) {
        Name = other.Name;
      }
      if (other.Number != 0) {
        Number = other.Number;
      }
      options_.Add(other.options_);
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            Name = input.ReadString();
            break;
          }
          case 16: {
            Number = input.ReadInt32();
            break;
          }
          case 26: {
            options_.AddEntriesFrom(input, _repeated_options_codec);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  ///  Proto option attached to messages/fields/enums etc.
  /// </summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class Option : pb::IMessage<Option> {
    private static readonly pb::MessageParser<Option> _parser = new pb::MessageParser<Option>(() => new Option());
    public static pb::MessageParser<Option> Parser { get { return _parser; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[4]; }
    }

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

    public Option() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Option(Option other) : this() {
      name_ = other.name_;
      Value = other.value_ != null ? other.Value.Clone() : null;
    }

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

    /// <summary>Field number for the "name" field.</summary>
    public const int NameFieldNumber = 1;
    private string name_ = "";
    /// <summary>
    ///  Proto option name.
    /// </summary>
    public string Name {
      get { return name_; }
      set {
        name_ = pb::Preconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "value" field.</summary>
    public const int ValueFieldNumber = 2;
    private global::Google.Protobuf.WellKnownTypes.Any value_;
    /// <summary>
    ///  Proto option value.
    /// </summary>
    public global::Google.Protobuf.WellKnownTypes.Any Value {
      get { return value_; }
      set {
        value_ = value;
      }
    }

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

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

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

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (Name.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Name);
      }
      if (value_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(Value);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Name.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
      }
      if (value_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value);
      }
      return size;
    }

    public void MergeFrom(Option other) {
      if (other == null) {
        return;
      }
      if (other.Name.Length != 0) {
        Name = other.Name;
      }
      if (other.value_ != null) {
        if (value_ == null) {
          value_ = new global::Google.Protobuf.WellKnownTypes.Any();
        }
        Value.MergeFrom(other.Value);
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            Name = input.ReadString();
            break;
          }
          case 18: {
            if (value_ == null) {
              value_ = new global::Google.Protobuf.WellKnownTypes.Any();
            }
            input.ReadMessage(value_);
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
