// 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 {

  namespace Proto {

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

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

      static Struct() {
        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.InternalBuildGeneratedFileFrom(descriptorData,
            new pbr::FileDescriptor[] {
            });
        internal__static_google_protobuf_Struct__FieldAccessorTable = 
            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Struct), descriptor.MessageTypes[0],
                new string[] { "Fields", }, new string[] { });
        internal__static_google_protobuf_Value__FieldAccessorTable = 
            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Value), descriptor.MessageTypes[1],
                new string[] { "NullValue", "NumberValue", "StringValue", "BoolValue", "StructValue", "ListValue", }, new string[] { "Kind", });
        internal__static_google_protobuf_ListValue__FieldAccessorTable = 
            new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.ListValue), descriptor.MessageTypes[2],
                new string[] { "Values", }, new string[] { });
      }
      #endregion

    }
  }
  #region Enums
  public enum NullValue {
    NULL_VALUE = 0,
  }

  #endregion

  #region Messages
  [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; } }

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

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

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

    public Struct() {
      OnConstruction();
    }

    partial void OnConstruction();

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

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

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

    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>();
    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.Default.Format(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 (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 10: {
            fields_.AddEntriesFrom(input, _map_fields_codec);
            break;
          }
        }
      }
    }

  }

  [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; } }

    private static readonly string[] _fieldNames = new string[] { "bool_value", "list_value", "null_value", "number_value", "string_value", "struct_value" };
    private static readonly uint[] _fieldTags = new uint[] { 32, 50, 8, 17, 26, 42 };
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Google.Protobuf.WellKnownTypes.Proto.Struct.Descriptor.MessageTypes[1]; }
    }

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

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

    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);
    }

    public void Freeze() {
      if (IsFrozen) {
        return;
      }
      _frozen = true;
      if (kind_ is IFreezable) ((IFreezable) kind_).Freeze();
    }

    public const int NullValueFieldNumber = 1;
    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 {
        pb::Freezable.CheckMutable(this);
        kind_ = value;
        kindCase_ = KindOneofCase.NullValue;
      }
    }

    public const int NumberValueFieldNumber = 2;
    public double NumberValue {
      get { return kindCase_ == KindOneofCase.NumberValue ? (double) kind_ : 0D; }
      set {
        pb::Freezable.CheckMutable(this);
        kind_ = value;
        kindCase_ = KindOneofCase.NumberValue;
      }
    }

    public const int StringValueFieldNumber = 3;
    public string StringValue {
      get { return kindCase_ == KindOneofCase.StringValue ? (string) kind_ : ""; }
      set {
        pb::Freezable.CheckMutable(this);
        kind_ = value ?? "";
        kindCase_ = KindOneofCase.StringValue;
      }
    }

    public const int BoolValueFieldNumber = 4;
    public bool BoolValue {
      get { return kindCase_ == KindOneofCase.BoolValue ? (bool) kind_ : false; }
      set {
        pb::Freezable.CheckMutable(this);
        kind_ = value;
        kindCase_ = KindOneofCase.BoolValue;
      }
    }

    public const int StructValueFieldNumber = 5;
    public global::Google.Protobuf.WellKnownTypes.Struct StructValue {
      get { return kindCase_ == KindOneofCase.StructValue ? (global::Google.Protobuf.WellKnownTypes.Struct) kind_ : null; }
      set {
        pb::Freezable.CheckMutable(this);
        kind_ = value;
        kindCase_ = value == null ? KindOneofCase.None : KindOneofCase.StructValue;
      }
    }

    public const int ListValueFieldNumber = 6;
    public global::Google.Protobuf.WellKnownTypes.ListValue ListValue {
      get { return kindCase_ == KindOneofCase.ListValue ? (global::Google.Protobuf.WellKnownTypes.ListValue) kind_ : null; }
      set {
        pb::Freezable.CheckMutable(this);
        kind_ = value;
        kindCase_ = value == null ? KindOneofCase.None : KindOneofCase.ListValue;
      }
    }

    private object kind_;
    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() {
      pb::Freezable.CheckMutable(this);
      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;
      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();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(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 (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            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;
          }
        }
      }
    }

  }

  [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; } }

    private static readonly string[] _fieldNames = new string[] { "values" };
    private static readonly uint[] _fieldTags = new uint[] { 10 };
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Google.Protobuf.WellKnownTypes.Proto.Struct.Descriptor.MessageTypes[2]; }
    }

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

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

    public ListValue() {
      OnConstruction();
    }

    partial void OnConstruction();

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

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

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

    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>();
    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.Default.Format(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 (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 10: {
            values_.AddEntriesFrom(input, _repeated_values_codec);
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
