// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: google/protobuf/struct.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/struct.proto</summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public static partial class StructReflection {

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

    static StructReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "Chxnb29nbGUvcHJvdG9idWYvc3RydWN0LnByb3RvEg9nb29nbGUucHJvdG9i",
            "dWYihAEKBlN0cnVjdBIzCgZmaWVsZHMYASADKAsyIy5nb29nbGUucHJvdG9i",
            "dWYuU3RydWN0LkZpZWxkc0VudHJ5GkUKC0ZpZWxkc0VudHJ5EgsKA2tleRgB",
            "IAEoCRIlCgV2YWx1ZRgCIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZToC",
            "OAEi6gEKBVZhbHVlEjAKCm51bGxfdmFsdWUYASABKA4yGi5nb29nbGUucHJv",
            "dG9idWYuTnVsbFZhbHVlSAASFgoMbnVtYmVyX3ZhbHVlGAIgASgBSAASFgoM",
            "c3RyaW5nX3ZhbHVlGAMgASgJSAASFAoKYm9vbF92YWx1ZRgEIAEoCEgAEi8K",
            "DHN0cnVjdF92YWx1ZRgFIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RI",
            "ABIwCgpsaXN0X3ZhbHVlGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLkxpc3RW",
            "YWx1ZUgAQgYKBGtpbmQiMwoJTGlzdFZhbHVlEiYKBnZhbHVlcxgBIAMoCzIW",
            "Lmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSobCglOdWxsVmFsdWUSDgoKTlVMTF9W",
            "QUxVRRAAQk4KE2NvbS5nb29nbGUucHJvdG9idWZCC1N0cnVjdFByb3RvUAGg",
            "AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnBy",
            "b3RvMw=="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { },
          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.NullValue), }, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Struct), global::Google.Protobuf.WellKnownTypes.Struct.Parser, new[]{ "Fields" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, }),
            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Value), global::Google.Protobuf.WellKnownTypes.Value.Parser, new[]{ "NullValue", "NumberValue", "StringValue", "BoolValue", "StructValue", "ListValue" }, new[]{ "Kind" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.ListValue), global::Google.Protobuf.WellKnownTypes.ListValue.Parser, new[]{ "Values" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Enums
  /// <summary>
  ///  `NullValue` is a singleton enumeration to represent the null value for the
  ///  `Value` type union.
  ///
  ///   The JSON representation for `NullValue` is JSON `null`.
  /// </summary>
  public enum NullValue {
    /// <summary>
    ///  Null value.
    /// </summary>
    NULL_VALUE = 0,
  }

  #endregion

  #region Messages
  /// <summary>
  ///  `Struct` represents a structured data value, consisting of fields
  ///  which map to dynamically typed values. In some languages, `Struct`
  ///  might be supported by a native representation. For example, in
  ///  scripting languages like JS a struct is represented as an
  ///  object. The details of that representation are described together
  ///  with the proto support for the language.
  ///
  ///  The JSON representation for `Struct` is JSON object.
  /// </summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class Struct : pb::IMessage<Struct> {
    private static readonly pb::MessageParser<Struct> _parser = new pb::MessageParser<Struct>(() => new Struct());
    public static pb::MessageParser<Struct> Parser { get { return _parser; } }

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

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

    public Struct() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Struct(Struct other) : this() {
      fields_ = other.fields_.Clone();
    }

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

    /// <summary>Field number for the "fields" field.</summary>
    public const int FieldsFieldNumber = 1;
    private static readonly pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value>.Codec _map_fields_codec
        = new pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Value.Parser), 10);
    private readonly pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value> fields_ = new pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value>();
    /// <summary>
    ///  Map of dynamically typed values.
    /// </summary>
    public pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value> Fields {
      get { return fields_; }
    }

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

    public bool Equals(Struct other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!Fields.Equals(other.Fields)) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      hash ^= Fields.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      fields_.WriteTo(output, _map_fields_codec);
    }

    public int CalculateSize() {
      int size = 0;
      size += fields_.CalculateSize(_map_fields_codec);
      return size;
    }

    public void MergeFrom(Struct other) {
      if (other == null) {
        return;
      }
      fields_.Add(other.fields_);
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            fields_.AddEntriesFrom(input, _map_fields_codec);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  ///  `Value` represents a dynamically typed value which can be either
  ///  null, a number, a string, a boolean, a recursive struct value, or a
  ///  list of values. A producer of value is expected to set one of that
  ///  variants, absence of any variant indicates an error.
  ///
  ///  The JSON representation for `Value` is JSON value.
  /// </summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class Value : pb::IMessage<Value> {
    private static readonly pb::MessageParser<Value> _parser = new pb::MessageParser<Value>(() => new Value());
    public static pb::MessageParser<Value> Parser { get { return _parser; } }

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

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

    public Value() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Value(Value other) : this() {
      switch (other.KindCase) {
        case KindOneofCase.NullValue:
          NullValue = other.NullValue;
          break;
        case KindOneofCase.NumberValue:
          NumberValue = other.NumberValue;
          break;
        case KindOneofCase.StringValue:
          StringValue = other.StringValue;
          break;
        case KindOneofCase.BoolValue:
          BoolValue = other.BoolValue;
          break;
        case KindOneofCase.StructValue:
          StructValue = other.StructValue.Clone();
          break;
        case KindOneofCase.ListValue:
          ListValue = other.ListValue.Clone();
          break;
      }

    }

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

    /// <summary>Field number for the "null_value" field.</summary>
    public const int NullValueFieldNumber = 1;
    /// <summary>
    ///  Represents a null value.
    /// </summary>
    public global::Google.Protobuf.WellKnownTypes.NullValue NullValue {
      get { return kindCase_ == KindOneofCase.NullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) kind_ : global::Google.Protobuf.WellKnownTypes.NullValue.NULL_VALUE; }
      set {
        kind_ = value;
        kindCase_ = KindOneofCase.NullValue;
      }
    }

    /// <summary>Field number for the "number_value" field.</summary>
    public const int NumberValueFieldNumber = 2;
    /// <summary>
    ///  Represents a double value.
    /// </summary>
    public double NumberValue {
      get { return kindCase_ == KindOneofCase.NumberValue ? (double) kind_ : 0D; }
      set {
        kind_ = value;
        kindCase_ = KindOneofCase.NumberValue;
      }
    }

    /// <summary>Field number for the "string_value" field.</summary>
    public const int StringValueFieldNumber = 3;
    /// <summary>
    ///  Represents a string value.
    /// </summary>
    public string StringValue {
      get { return kindCase_ == KindOneofCase.StringValue ? (string) kind_ : ""; }
      set {
        kind_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        kindCase_ = KindOneofCase.StringValue;
      }
    }

    /// <summary>Field number for the "bool_value" field.</summary>
    public const int BoolValueFieldNumber = 4;
    /// <summary>
    ///  Represents a boolean value.
    /// </summary>
    public bool BoolValue {
      get { return kindCase_ == KindOneofCase.BoolValue ? (bool) kind_ : false; }
      set {
        kind_ = value;
        kindCase_ = KindOneofCase.BoolValue;
      }
    }

    /// <summary>Field number for the "struct_value" field.</summary>
    public const int StructValueFieldNumber = 5;
    /// <summary>
    ///  Represents a structured value.
    /// </summary>
    public global::Google.Protobuf.WellKnownTypes.Struct StructValue {
      get { return kindCase_ == KindOneofCase.StructValue ? (global::Google.Protobuf.WellKnownTypes.Struct) kind_ : null; }
      set {
        kind_ = value;
        kindCase_ = value == null ? KindOneofCase.None : KindOneofCase.StructValue;
      }
    }

    /// <summary>Field number for the "list_value" field.</summary>
    public const int ListValueFieldNumber = 6;
    /// <summary>
    ///  Represents a repeated `Value`.
    /// </summary>
    public global::Google.Protobuf.WellKnownTypes.ListValue ListValue {
      get { return kindCase_ == KindOneofCase.ListValue ? (global::Google.Protobuf.WellKnownTypes.ListValue) kind_ : null; }
      set {
        kind_ = value;
        kindCase_ = value == null ? KindOneofCase.None : KindOneofCase.ListValue;
      }
    }

    private object kind_;
    /// <summary>Enum of possible cases for the "kind" oneof.</summary>
    public enum KindOneofCase {
      None = 0,
      NullValue = 1,
      NumberValue = 2,
      StringValue = 3,
      BoolValue = 4,
      StructValue = 5,
      ListValue = 6,
    }
    private KindOneofCase kindCase_ = KindOneofCase.None;
    public KindOneofCase KindCase {
      get { return kindCase_; }
    }

    public void ClearKind() {
      kindCase_ = KindOneofCase.None;
      kind_ = null;
    }

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

    public bool Equals(Value other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (NullValue != other.NullValue) return false;
      if (NumberValue != other.NumberValue) return false;
      if (StringValue != other.StringValue) return false;
      if (BoolValue != other.BoolValue) return false;
      if (!object.Equals(StructValue, other.StructValue)) return false;
      if (!object.Equals(ListValue, other.ListValue)) return false;
      if (KindCase != other.KindCase) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (kindCase_ == KindOneofCase.NullValue) hash ^= NullValue.GetHashCode();
      if (kindCase_ == KindOneofCase.NumberValue) hash ^= NumberValue.GetHashCode();
      if (kindCase_ == KindOneofCase.StringValue) hash ^= StringValue.GetHashCode();
      if (kindCase_ == KindOneofCase.BoolValue) hash ^= BoolValue.GetHashCode();
      if (kindCase_ == KindOneofCase.StructValue) hash ^= StructValue.GetHashCode();
      if (kindCase_ == KindOneofCase.ListValue) hash ^= ListValue.GetHashCode();
      hash ^= (int) kindCase_;
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      if (kindCase_ == KindOneofCase.NullValue) {
        output.WriteRawTag(8);
        output.WriteEnum((int) NullValue);
      }
      if (kindCase_ == KindOneofCase.NumberValue) {
        output.WriteRawTag(17);
        output.WriteDouble(NumberValue);
      }
      if (kindCase_ == KindOneofCase.StringValue) {
        output.WriteRawTag(26);
        output.WriteString(StringValue);
      }
      if (kindCase_ == KindOneofCase.BoolValue) {
        output.WriteRawTag(32);
        output.WriteBool(BoolValue);
      }
      if (kindCase_ == KindOneofCase.StructValue) {
        output.WriteRawTag(42);
        output.WriteMessage(StructValue);
      }
      if (kindCase_ == KindOneofCase.ListValue) {
        output.WriteRawTag(50);
        output.WriteMessage(ListValue);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (kindCase_ == KindOneofCase.NullValue) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) NullValue);
      }
      if (kindCase_ == KindOneofCase.NumberValue) {
        size += 1 + 8;
      }
      if (kindCase_ == KindOneofCase.StringValue) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue);
      }
      if (kindCase_ == KindOneofCase.BoolValue) {
        size += 1 + 1;
      }
      if (kindCase_ == KindOneofCase.StructValue) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(StructValue);
      }
      if (kindCase_ == KindOneofCase.ListValue) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ListValue);
      }
      return size;
    }

    public void MergeFrom(Value other) {
      if (other == null) {
        return;
      }
      switch (other.KindCase) {
        case KindOneofCase.NullValue:
          NullValue = other.NullValue;
          break;
        case KindOneofCase.NumberValue:
          NumberValue = other.NumberValue;
          break;
        case KindOneofCase.StringValue:
          StringValue = other.StringValue;
          break;
        case KindOneofCase.BoolValue:
          BoolValue = other.BoolValue;
          break;
        case KindOneofCase.StructValue:
          StructValue = other.StructValue;
          break;
        case KindOneofCase.ListValue:
          ListValue = other.ListValue;
          break;
      }

    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            kind_ = input.ReadEnum();
            kindCase_ = KindOneofCase.NullValue;
            break;
          }
          case 17: {
            NumberValue = input.ReadDouble();
            break;
          }
          case 26: {
            StringValue = input.ReadString();
            break;
          }
          case 32: {
            BoolValue = input.ReadBool();
            break;
          }
          case 42: {
            global::Google.Protobuf.WellKnownTypes.Struct subBuilder = new global::Google.Protobuf.WellKnownTypes.Struct();
            if (kindCase_ == KindOneofCase.StructValue) {
              subBuilder.MergeFrom(StructValue);
            }
            input.ReadMessage(subBuilder);
            StructValue = subBuilder;
            break;
          }
          case 50: {
            global::Google.Protobuf.WellKnownTypes.ListValue subBuilder = new global::Google.Protobuf.WellKnownTypes.ListValue();
            if (kindCase_ == KindOneofCase.ListValue) {
              subBuilder.MergeFrom(ListValue);
            }
            input.ReadMessage(subBuilder);
            ListValue = subBuilder;
            break;
          }
        }
      }
    }

  }

  /// <summary>
  ///  `ListValue` is a wrapper around a repeated field of values.
  ///
  ///  The JSON representation for `ListValue` is JSON array.
  /// </summary>
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class ListValue : pb::IMessage<ListValue> {
    private static readonly pb::MessageParser<ListValue> _parser = new pb::MessageParser<ListValue>(() => new ListValue());
    public static pb::MessageParser<ListValue> Parser { get { return _parser; } }

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

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

    public ListValue() {
      OnConstruction();
    }

    partial void OnConstruction();

    public ListValue(ListValue other) : this() {
      values_ = other.values_.Clone();
    }

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

    /// <summary>Field number for the "values" field.</summary>
    public const int ValuesFieldNumber = 1;
    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Value> _repeated_values_codec
        = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.WellKnownTypes.Value.Parser);
    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> values_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value>();
    /// <summary>
    ///  Repeated field of dynamically typed values.
    /// </summary>
    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> Values {
      get { return values_; }
    }

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

    public bool Equals(ListValue other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if(!values_.Equals(other.values_)) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      hash ^= values_.GetHashCode();
      return hash;
    }

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

    public void WriteTo(pb::CodedOutputStream output) {
      values_.WriteTo(output, _repeated_values_codec);
    }

    public int CalculateSize() {
      int size = 0;
      size += values_.CalculateSize(_repeated_values_codec);
      return size;
    }

    public void MergeFrom(ListValue other) {
      if (other == null) {
        return;
      }
      values_.Add(other.values_);
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            values_.AddEntriesFrom(input, _repeated_values_codec);
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
