// services/network/public/mojom/cors_origin_pattern.mojom.h is auto generated by mojom_bindings_generator.py, do not edit

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SERVICES_NETWORK_PUBLIC_MOJOM_CORS_ORIGIN_PATTERN_MOJOM_H_
#define SERVICES_NETWORK_PUBLIC_MOJOM_CORS_ORIGIN_PATTERN_MOJOM_H_

#include <stdint.h>

#include <limits>
#include <type_traits>
#include <utility>

#include "third_party/abseil-cpp/absl/types/optional.h"
#include "mojo/public/cpp/bindings/clone_traits.h"
#include "mojo/public/cpp/bindings/equals_traits.h"
#include "mojo/public/cpp/bindings/lib/serialization.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "mojo/public/cpp/bindings/union_traits.h"

#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"

#include "services/network/public/mojom/cors_origin_pattern.mojom-shared.h"
#include "services/network/public/mojom/cors_origin_pattern.mojom-forward.h"
#include "url/mojom/origin.mojom.h"
#include <string>
#include <vector>





#ifdef KYTHE_IS_RUNNING
#pragma kythe_inline_metadata "Metadata comment"
#endif


namespace network {
namespace mojom {









// @generated_from: network.mojom.CorsOriginPattern
class  CorsOriginPattern {
 public:
  template <typename T>
  using EnableIfSame = std::enable_if_t<std::is_same<CorsOriginPattern, T>::value>;
  using DataView = CorsOriginPatternDataView;
  using Data_ = internal::CorsOriginPattern_Data;

  template <typename... Args>
  static CorsOriginPatternPtr New(Args&&... args) {
    return CorsOriginPatternPtr(
        absl::in_place, std::forward<Args>(args)...);
  }

  template <typename U>
  static CorsOriginPatternPtr From(const U& u) {
    return mojo::TypeConverter<CorsOriginPatternPtr, U>::Convert(u);
  }

  template <typename U>
  U To() const {
    return mojo::TypeConverter<U, CorsOriginPattern>::Convert(*this);
  }


  CorsOriginPattern();

  CorsOriginPattern(
      const std::string& protocol,
      const std::string& domain,
      uint16_t port,
      CorsDomainMatchMode domain_match_mode,
      CorsPortMatchMode port_match_mode,
      CorsOriginAccessMatchPriority priority);


  ~CorsOriginPattern();

  // Clone() is a template so it is only instantiated if it is used. Thus, the
  // bindings generator does not need to know whether Clone() or copy
  // constructor/assignment are available for members.
  template <typename StructPtrType = CorsOriginPatternPtr>
  CorsOriginPatternPtr Clone() const;

  // Equals() is a template so it is only instantiated if it is used. Thus, the
  // bindings generator does not need to know whether Equals() or == operator
  // are available for members.
  template <typename T, CorsOriginPattern::EnableIfSame<T>* = nullptr>
  bool Equals(const T& other) const;

  template <typename T, CorsOriginPattern::EnableIfSame<T>* = nullptr>
  bool operator==(const T& rhs) const { return Equals(rhs); }
  size_t Hash(size_t seed) const;
  template <typename UserType>
  static std::vector<uint8_t> Serialize(UserType* input) {
    return mojo::internal::SerializeImpl<
        CorsOriginPattern::DataView, std::vector<uint8_t>>(input);
  }

  template <typename UserType>
  static mojo::Message SerializeAsMessage(UserType* input) {
    return mojo::internal::SerializeAsMessageImpl<
        CorsOriginPattern::DataView>(input);
  }

  // The returned Message is serialized only if the message is moved
  // cross-process or cross-language. Otherwise if the message is Deserialized
  // as the same UserType |input| will just be moved to |output| in
  // DeserializeFromMessage.
  template <typename UserType>
  static mojo::Message WrapAsMessage(UserType input) {
    return mojo::Message(std::make_unique<
        internal::CorsOriginPattern_UnserializedMessageContext<
            UserType, CorsOriginPattern::DataView>>(0, 0, std::move(input)),
        MOJO_CREATE_MESSAGE_FLAG_NONE);
  }

  template <typename UserType>
  static bool Deserialize(const void* data,
                          size_t data_num_bytes,
                          UserType* output) {
    mojo::Message message;
    return mojo::internal::DeserializeImpl<CorsOriginPattern::DataView>(
        message, data, data_num_bytes, output, Validate);
  }

  template <typename UserType>
  static bool Deserialize(const std::vector<uint8_t>& input,
                          UserType* output) {
    return CorsOriginPattern::Deserialize(
        input.size() == 0 ? nullptr : &input.front(), input.size(), output);
  }

  template <typename UserType>
  static bool DeserializeFromMessage(mojo::Message input,
                                     UserType* output) {
    auto context = input.TakeUnserializedContext<
        internal::CorsOriginPattern_UnserializedMessageContext<
            UserType, CorsOriginPattern::DataView>>();
    if (context) {
      *output = std::move(context->TakeData());
      return true;
    }
    input.SerializeIfNecessary();
    return mojo::internal::DeserializeImpl<CorsOriginPattern::DataView>(
        input, input.payload(), input.payload_num_bytes(), output, Validate);
  }

  
// @generated_from: network.mojom.CorsOriginPattern.protocol
  std::string protocol;
  
// @generated_from: network.mojom.CorsOriginPattern.domain
  std::string domain;
  
// @generated_from: network.mojom.CorsOriginPattern.port
  uint16_t port;
  
// @generated_from: network.mojom.CorsOriginPattern.domain_match_mode
  CorsDomainMatchMode domain_match_mode;
  
// @generated_from: network.mojom.CorsOriginPattern.port_match_mode
  CorsPortMatchMode port_match_mode;
  
// @generated_from: network.mojom.CorsOriginPattern.priority
  CorsOriginAccessMatchPriority priority;

  // Serialise this struct into a trace.
  void WriteIntoTrace(perfetto::TracedValue traced_context) const;

 private:
  static bool Validate(const void* data,
                       mojo::internal::ValidationContext* validation_context);
};

// The comparison operators are templates, so they are only instantiated if they
// are used. Thus, the bindings generator does not need to know whether
// comparison operators are available for members.
template <typename T, CorsOriginPattern::EnableIfSame<T>* = nullptr>
bool operator<(const T& lhs, const T& rhs);

template <typename T, CorsOriginPattern::EnableIfSame<T>* = nullptr>
bool operator<=(const T& lhs, const T& rhs) {
  return !(rhs < lhs);
}

template <typename T, CorsOriginPattern::EnableIfSame<T>* = nullptr>
bool operator>(const T& lhs, const T& rhs) {
  return rhs < lhs;
}

template <typename T, CorsOriginPattern::EnableIfSame<T>* = nullptr>
bool operator>=(const T& lhs, const T& rhs) {
  return !(lhs < rhs);
}





// @generated_from: network.mojom.CorsOriginAccessPatterns
class  CorsOriginAccessPatterns {
 public:
  template <typename T>
  using EnableIfSame = std::enable_if_t<std::is_same<CorsOriginAccessPatterns, T>::value>;
  using DataView = CorsOriginAccessPatternsDataView;
  using Data_ = internal::CorsOriginAccessPatterns_Data;

  template <typename... Args>
  static CorsOriginAccessPatternsPtr New(Args&&... args) {
    return CorsOriginAccessPatternsPtr(
        absl::in_place, std::forward<Args>(args)...);
  }

  template <typename U>
  static CorsOriginAccessPatternsPtr From(const U& u) {
    return mojo::TypeConverter<CorsOriginAccessPatternsPtr, U>::Convert(u);
  }

  template <typename U>
  U To() const {
    return mojo::TypeConverter<U, CorsOriginAccessPatterns>::Convert(*this);
  }


  CorsOriginAccessPatterns();

  CorsOriginAccessPatterns(
      const ::url::Origin& source_origin,
      std::vector<CorsOriginPatternPtr> allow_patterns,
      std::vector<CorsOriginPatternPtr> block_patterns);

CorsOriginAccessPatterns(const CorsOriginAccessPatterns&) = delete;
CorsOriginAccessPatterns& operator=(const CorsOriginAccessPatterns&) = delete;

  ~CorsOriginAccessPatterns();

  // Clone() is a template so it is only instantiated if it is used. Thus, the
  // bindings generator does not need to know whether Clone() or copy
  // constructor/assignment are available for members.
  template <typename StructPtrType = CorsOriginAccessPatternsPtr>
  CorsOriginAccessPatternsPtr Clone() const;

  // Equals() is a template so it is only instantiated if it is used. Thus, the
  // bindings generator does not need to know whether Equals() or == operator
  // are available for members.
  template <typename T, CorsOriginAccessPatterns::EnableIfSame<T>* = nullptr>
  bool Equals(const T& other) const;

  template <typename T, CorsOriginAccessPatterns::EnableIfSame<T>* = nullptr>
  bool operator==(const T& rhs) const { return Equals(rhs); }
  template <typename UserType>
  static std::vector<uint8_t> Serialize(UserType* input) {
    return mojo::internal::SerializeImpl<
        CorsOriginAccessPatterns::DataView, std::vector<uint8_t>>(input);
  }

  template <typename UserType>
  static mojo::Message SerializeAsMessage(UserType* input) {
    return mojo::internal::SerializeAsMessageImpl<
        CorsOriginAccessPatterns::DataView>(input);
  }

  // The returned Message is serialized only if the message is moved
  // cross-process or cross-language. Otherwise if the message is Deserialized
  // as the same UserType |input| will just be moved to |output| in
  // DeserializeFromMessage.
  template <typename UserType>
  static mojo::Message WrapAsMessage(UserType input) {
    return mojo::Message(std::make_unique<
        internal::CorsOriginAccessPatterns_UnserializedMessageContext<
            UserType, CorsOriginAccessPatterns::DataView>>(0, 0, std::move(input)),
        MOJO_CREATE_MESSAGE_FLAG_NONE);
  }

  template <typename UserType>
  static bool Deserialize(const void* data,
                          size_t data_num_bytes,
                          UserType* output) {
    mojo::Message message;
    return mojo::internal::DeserializeImpl<CorsOriginAccessPatterns::DataView>(
        message, data, data_num_bytes, output, Validate);
  }

  template <typename UserType>
  static bool Deserialize(const std::vector<uint8_t>& input,
                          UserType* output) {
    return CorsOriginAccessPatterns::Deserialize(
        input.size() == 0 ? nullptr : &input.front(), input.size(), output);
  }

  template <typename UserType>
  static bool DeserializeFromMessage(mojo::Message input,
                                     UserType* output) {
    auto context = input.TakeUnserializedContext<
        internal::CorsOriginAccessPatterns_UnserializedMessageContext<
            UserType, CorsOriginAccessPatterns::DataView>>();
    if (context) {
      *output = std::move(context->TakeData());
      return true;
    }
    input.SerializeIfNecessary();
    return mojo::internal::DeserializeImpl<CorsOriginAccessPatterns::DataView>(
        input, input.payload(), input.payload_num_bytes(), output, Validate);
  }

  
// @generated_from: network.mojom.CorsOriginAccessPatterns.source_origin
  ::url::Origin source_origin;
  
// @generated_from: network.mojom.CorsOriginAccessPatterns.allow_patterns
  std::vector<CorsOriginPatternPtr> allow_patterns;
  
// @generated_from: network.mojom.CorsOriginAccessPatterns.block_patterns
  std::vector<CorsOriginPatternPtr> block_patterns;

  // Serialise this struct into a trace.
  void WriteIntoTrace(perfetto::TracedValue traced_context) const;

 private:
  static bool Validate(const void* data,
                       mojo::internal::ValidationContext* validation_context);
};

// The comparison operators are templates, so they are only instantiated if they
// are used. Thus, the bindings generator does not need to know whether
// comparison operators are available for members.
template <typename T, CorsOriginAccessPatterns::EnableIfSame<T>* = nullptr>
bool operator<(const T& lhs, const T& rhs);

template <typename T, CorsOriginAccessPatterns::EnableIfSame<T>* = nullptr>
bool operator<=(const T& lhs, const T& rhs) {
  return !(rhs < lhs);
}

template <typename T, CorsOriginAccessPatterns::EnableIfSame<T>* = nullptr>
bool operator>(const T& lhs, const T& rhs) {
  return rhs < lhs;
}

template <typename T, CorsOriginAccessPatterns::EnableIfSame<T>* = nullptr>
bool operator>=(const T& lhs, const T& rhs) {
  return !(lhs < rhs);
}

template <typename StructPtrType>
CorsOriginPatternPtr CorsOriginPattern::Clone() const {
  return New(
      mojo::Clone(protocol),
      mojo::Clone(domain),
      mojo::Clone(port),
      mojo::Clone(domain_match_mode),
      mojo::Clone(port_match_mode),
      mojo::Clone(priority)
  );
}

template <typename T, CorsOriginPattern::EnableIfSame<T>*>
bool CorsOriginPattern::Equals(const T& other_struct) const {
  if (!mojo::Equals(this->protocol, other_struct.protocol))
    return false;
  if (!mojo::Equals(this->domain, other_struct.domain))
    return false;
  if (!mojo::Equals(this->port, other_struct.port))
    return false;
  if (!mojo::Equals(this->domain_match_mode, other_struct.domain_match_mode))
    return false;
  if (!mojo::Equals(this->port_match_mode, other_struct.port_match_mode))
    return false;
  if (!mojo::Equals(this->priority, other_struct.priority))
    return false;
  return true;
}

template <typename T, CorsOriginPattern::EnableIfSame<T>*>
bool operator<(const T& lhs, const T& rhs) {
  if (lhs.protocol < rhs.protocol)
    return true;
  if (rhs.protocol < lhs.protocol)
    return false;
  if (lhs.domain < rhs.domain)
    return true;
  if (rhs.domain < lhs.domain)
    return false;
  if (lhs.port < rhs.port)
    return true;
  if (rhs.port < lhs.port)
    return false;
  if (lhs.domain_match_mode < rhs.domain_match_mode)
    return true;
  if (rhs.domain_match_mode < lhs.domain_match_mode)
    return false;
  if (lhs.port_match_mode < rhs.port_match_mode)
    return true;
  if (rhs.port_match_mode < lhs.port_match_mode)
    return false;
  if (lhs.priority < rhs.priority)
    return true;
  if (rhs.priority < lhs.priority)
    return false;
  return false;
}
template <typename StructPtrType>
CorsOriginAccessPatternsPtr CorsOriginAccessPatterns::Clone() const {
  return New(
      mojo::Clone(source_origin),
      mojo::Clone(allow_patterns),
      mojo::Clone(block_patterns)
  );
}

template <typename T, CorsOriginAccessPatterns::EnableIfSame<T>*>
bool CorsOriginAccessPatterns::Equals(const T& other_struct) const {
  if (!mojo::Equals(this->source_origin, other_struct.source_origin))
    return false;
  if (!mojo::Equals(this->allow_patterns, other_struct.allow_patterns))
    return false;
  if (!mojo::Equals(this->block_patterns, other_struct.block_patterns))
    return false;
  return true;
}

template <typename T, CorsOriginAccessPatterns::EnableIfSame<T>*>
bool operator<(const T& lhs, const T& rhs) {
  if (lhs.source_origin < rhs.source_origin)
    return true;
  if (rhs.source_origin < lhs.source_origin)
    return false;
  if (lhs.allow_patterns < rhs.allow_patterns)
    return true;
  if (rhs.allow_patterns < lhs.allow_patterns)
    return false;
  if (lhs.block_patterns < rhs.block_patterns)
    return true;
  if (rhs.block_patterns < lhs.block_patterns)
    return false;
  return false;
}


}  // namespace mojom
}  // namespace network

namespace mojo {


template <>
struct  StructTraits<::network::mojom::CorsOriginPattern::DataView,
                                         ::network::mojom::CorsOriginPatternPtr> {
  static bool IsNull(const ::network::mojom::CorsOriginPatternPtr& input) { return !input; }
  static void SetToNull(::network::mojom::CorsOriginPatternPtr* output) { output->reset(); }

  static const decltype(::network::mojom::CorsOriginPattern::protocol)& protocol(
      const ::network::mojom::CorsOriginPatternPtr& input) {
    return input->protocol;
  }

  static const decltype(::network::mojom::CorsOriginPattern::domain)& domain(
      const ::network::mojom::CorsOriginPatternPtr& input) {
    return input->domain;
  }

  static decltype(::network::mojom::CorsOriginPattern::port) port(
      const ::network::mojom::CorsOriginPatternPtr& input) {
    return input->port;
  }

  static decltype(::network::mojom::CorsOriginPattern::domain_match_mode) domain_match_mode(
      const ::network::mojom::CorsOriginPatternPtr& input) {
    return input->domain_match_mode;
  }

  static decltype(::network::mojom::CorsOriginPattern::port_match_mode) port_match_mode(
      const ::network::mojom::CorsOriginPatternPtr& input) {
    return input->port_match_mode;
  }

  static decltype(::network::mojom::CorsOriginPattern::priority) priority(
      const ::network::mojom::CorsOriginPatternPtr& input) {
    return input->priority;
  }

  static bool Read(::network::mojom::CorsOriginPattern::DataView input, ::network::mojom::CorsOriginPatternPtr* output);
};


template <>
struct  StructTraits<::network::mojom::CorsOriginAccessPatterns::DataView,
                                         ::network::mojom::CorsOriginAccessPatternsPtr> {
  static bool IsNull(const ::network::mojom::CorsOriginAccessPatternsPtr& input) { return !input; }
  static void SetToNull(::network::mojom::CorsOriginAccessPatternsPtr* output) { output->reset(); }

  static const decltype(::network::mojom::CorsOriginAccessPatterns::source_origin)& source_origin(
      const ::network::mojom::CorsOriginAccessPatternsPtr& input) {
    return input->source_origin;
  }

  static const decltype(::network::mojom::CorsOriginAccessPatterns::allow_patterns)& allow_patterns(
      const ::network::mojom::CorsOriginAccessPatternsPtr& input) {
    return input->allow_patterns;
  }

  static const decltype(::network::mojom::CorsOriginAccessPatterns::block_patterns)& block_patterns(
      const ::network::mojom::CorsOriginAccessPatternsPtr& input) {
    return input->block_patterns;
  }

  static bool Read(::network::mojom::CorsOriginAccessPatterns::DataView input, ::network::mojom::CorsOriginAccessPatternsPtr* output);
};

}  // namespace mojo

#endif  // SERVICES_NETWORK_PUBLIC_MOJOM_CORS_ORIGIN_PATTERN_MOJOM_H_

/* Metadata comment
eyJtZXRhIjogW3siZW5kIjogMTM5MSwgImJlZ2luIjogMTM3NCwgImVkZ2UiOiAiJS9reXRoZS9l
ZGdlL2dlbmVyYXRlcyIsICJ0eXBlIjogImFuY2hvcl9kZWZpbmVzIiwgInZuYW1lIjogeyJjb3Jw
dXMiOiAiY2hyb21pdW0uZ29vZ2xlc291cmNlLmNvbS9jaHJvbWl1bS9zcmMiLCAibGFuZ3VhZ2Ui
OiAibW9qb20iLCAic2lnbmF0dXJlIjogIm5ldHdvcmsubW9qb20uQ29yc09yaWdpblBhdHRlcm4i
fX0sIHsiZW5kIjogNTM0NCwgImJlZ2luIjogNTMzNiwgImVkZ2UiOiAiJS9reXRoZS9lZGdlL2dl
bmVyYXRlcyIsICJ0eXBlIjogImFuY2hvcl9kZWZpbmVzIiwgInZuYW1lIjogeyJjb3JwdXMiOiAi
Y2hyb21pdW0uZ29vZ2xlc291cmNlLmNvbS9jaHJvbWl1bS9zcmMiLCAibGFuZ3VhZ2UiOiAibW9q
b20iLCAic2lnbmF0dXJlIjogIm5ldHdvcmsubW9qb20uQ29yc09yaWdpblBhdHRlcm4ucHJvdG9j
b2wifX0sIHsiZW5kIjogNTQyOCwgImJlZ2luIjogNTQyMiwgImVkZ2UiOiAiJS9reXRoZS9lZGdl
L2dlbmVyYXRlcyIsICJ0eXBlIjogImFuY2hvcl9kZWZpbmVzIiwgInZuYW1lIjogeyJjb3JwdXMi
OiAiY2hyb21pdW0uZ29vZ2xlc291cmNlLmNvbS9jaHJvbWl1bS9zcmMiLCAibGFuZ3VhZ2UiOiAi
bW9qb20iLCAic2lnbmF0dXJlIjogIm5ldHdvcmsubW9qb20uQ29yc09yaWdpblBhdHRlcm4uZG9t
YWluIn19LCB7ImVuZCI6IDU1MDUsICJiZWdpbiI6IDU1MDEsICJlZGdlIjogIiUva3l0aGUvZWRn
ZS9nZW5lcmF0ZXMiLCAidHlwZSI6ICJhbmNob3JfZGVmaW5lcyIsICJ2bmFtZSI6IHsiY29ycHVz
IjogImNocm9taXVtLmdvb2dsZXNvdXJjZS5jb20vY2hyb21pdW0vc3JjIiwgImxhbmd1YWdlIjog
Im1vam9tIiwgInNpZ25hdHVyZSI6ICJuZXR3b3JrLm1vam9tLkNvcnNPcmlnaW5QYXR0ZXJuLnBv
cnQifX0sIHsiZW5kIjogNTYxOSwgImJlZ2luIjogNTYwMiwgImVkZ2UiOiAiJS9reXRoZS9lZGdl
L2dlbmVyYXRlcyIsICJ0eXBlIjogImFuY2hvcl9kZWZpbmVzIiwgInZuYW1lIjogeyJjb3JwdXMi
OiAiY2hyb21pdW0uZ29vZ2xlc291cmNlLmNvbS9jaHJvbWl1bS9zcmMiLCAibGFuZ3VhZ2UiOiAi
bW9qb20iLCAic2lnbmF0dXJlIjogIm5ldHdvcmsubW9qb20uQ29yc09yaWdpblBhdHRlcm4uZG9t
YWluX21hdGNoX21vZGUifX0sIHsiZW5kIjogNTcyNywgImJlZ2luIjogNTcxMiwgImVkZ2UiOiAi
JS9reXRoZS9lZGdlL2dlbmVyYXRlcyIsICJ0eXBlIjogImFuY2hvcl9kZWZpbmVzIiwgInZuYW1l
IjogeyJjb3JwdXMiOiAiY2hyb21pdW0uZ29vZ2xlc291cmNlLmNvbS9jaHJvbWl1bS9zcmMiLCAi
bGFuZ3VhZ2UiOiAibW9qb20iLCAic2lnbmF0dXJlIjogIm5ldHdvcmsubW9qb20uQ29yc09yaWdp
blBhdHRlcm4ucG9ydF9tYXRjaF9tb2RlIn19LCB7ImVuZCI6IDU4MzMsICJiZWdpbiI6IDU4MjUs
ICJlZGdlIjogIiUva3l0aGUvZWRnZS9nZW5lcmF0ZXMiLCAidHlwZSI6ICJhbmNob3JfZGVmaW5l
cyIsICJ2bmFtZSI6IHsiY29ycHVzIjogImNocm9taXVtLmdvb2dsZXNvdXJjZS5jb20vY2hyb21p
dW0vc3JjIiwgImxhbmd1YWdlIjogIm1vam9tIiwgInNpZ25hdHVyZSI6ICJuZXR3b3JrLm1vam9t
LkNvcnNPcmlnaW5QYXR0ZXJuLnByaW9yaXR5In19LCB7ImVuZCI6IDY5MTAsICJiZWdpbiI6IDY4
ODYsICJlZGdlIjogIiUva3l0aGUvZWRnZS9nZW5lcmF0ZXMiLCAidHlwZSI6ICJhbmNob3JfZGVm
aW5lcyIsICJ2bmFtZSI6IHsiY29ycHVzIjogImNocm9taXVtLmdvb2dsZXNvdXJjZS5jb20vY2hy
b21pdW0vc3JjIiwgImxhbmd1YWdlIjogIm1vam9tIiwgInNpZ25hdHVyZSI6ICJuZXR3b3JrLm1v
am9tLkNvcnNPcmlnaW5BY2Nlc3NQYXR0ZXJucyJ9fSwgeyJlbmQiOiAxMTA5NiwgImJlZ2luIjog
MTEwODMsICJlZGdlIjogIiUva3l0aGUvZWRnZS9nZW5lcmF0ZXMiLCAidHlwZSI6ICJhbmNob3Jf
ZGVmaW5lcyIsICJ2bmFtZSI6IHsiY29ycHVzIjogImNocm9taXVtLmdvb2dsZXNvdXJjZS5jb20v
Y2hyb21pdW0vc3JjIiwgImxhbmd1YWdlIjogIm1vam9tIiwgInNpZ25hdHVyZSI6ICJuZXR3b3Jr
Lm1vam9tLkNvcnNPcmlnaW5BY2Nlc3NQYXR0ZXJucy5zb3VyY2Vfb3JpZ2luIn19LCB7ImVuZCI6
IDExMjI1LCAiYmVnaW4iOiAxMTIxMSwgImVkZ2UiOiAiJS9reXRoZS9lZGdlL2dlbmVyYXRlcyIs
ICJ0eXBlIjogImFuY2hvcl9kZWZpbmVzIiwgInZuYW1lIjogeyJjb3JwdXMiOiAiY2hyb21pdW0u
Z29vZ2xlc291cmNlLmNvbS9jaHJvbWl1bS9zcmMiLCAibGFuZ3VhZ2UiOiAibW9qb20iLCAic2ln
bmF0dXJlIjogIm5ldHdvcmsubW9qb20uQ29yc09yaWdpbkFjY2Vzc1BhdHRlcm5zLmFsbG93X3Bh
dHRlcm5zIn19LCB7ImVuZCI6IDExMzU0LCAiYmVnaW4iOiAxMTM0MCwgImVkZ2UiOiAiJS9reXRo
ZS9lZGdlL2dlbmVyYXRlcyIsICJ0eXBlIjogImFuY2hvcl9kZWZpbmVzIiwgInZuYW1lIjogeyJj
b3JwdXMiOiAiY2hyb21pdW0uZ29vZ2xlc291cmNlLmNvbS9jaHJvbWl1bS9zcmMiLCAibGFuZ3Vh
Z2UiOiAibW9qb20iLCAic2lnbmF0dXJlIjogIm5ldHdvcmsubW9qb20uQ29yc09yaWdpbkFjY2Vz
c1BhdHRlcm5zLmJsb2NrX3BhdHRlcm5zIn19XSwgInR5cGUiOiAia3l0aGUwIn0=
*/