// WARNING: This file is machine generated by fidlgen.

// fidl_experiment = output_index_json

#pragma once

#include "lib/fidl/cpp/internal/header.h"

namespace test {
namespace arrays {

//
// Domain objects declarations
//

class StructSmallArray;

class StructLargeArray;

class TableSmallArray;

class TableLargeArray;

class UnionSmallArray;

class UnionLargeArray;

class StructSmallArray final {
 public:
  static const fidl_type_t* FidlType;

  ::std::array<uint32_t, 2> a{};

  static inline ::std::unique_ptr<StructSmallArray> New() { return ::std::make_unique<StructSmallArray>(); }

  void Encode(::fidl::Encoder* _encoder, size_t _offset,
              cpp17::optional<::fidl::HandleInformation> maybe_handle_info = cpp17::nullopt);
  static void Decode(::fidl::Decoder* _decoder, StructSmallArray* value, size_t _offset);
  zx_status_t Clone(StructSmallArray* result) const;
};

inline zx_status_t Clone(const ::test::arrays::StructSmallArray& _value,
                         ::test::arrays::StructSmallArray* _result) {
  return _value.Clone(_result);
}

using StructSmallArrayPtr = ::std::unique_ptr<StructSmallArray>;

class StructLargeArray final {
 public:
  static const fidl_type_t* FidlType;

  ::std::array<uint32_t, 100> a{};

  static inline ::std::unique_ptr<StructLargeArray> New() { return ::std::make_unique<StructLargeArray>(); }

  void Encode(::fidl::Encoder* _encoder, size_t _offset,
              cpp17::optional<::fidl::HandleInformation> maybe_handle_info = cpp17::nullopt);
  static void Decode(::fidl::Decoder* _decoder, StructLargeArray* value, size_t _offset);
  zx_status_t Clone(StructLargeArray* result) const;
};

inline zx_status_t Clone(const ::test::arrays::StructLargeArray& _value,
                         ::test::arrays::StructLargeArray* _result) {
  return _value.Clone(_result);
}

using StructLargeArrayPtr = ::std::unique_ptr<StructLargeArray>;

class TableSmallArray final {
 public:
  static const fidl_type_t* FidlType;
  /// Returns whether no field is set.
  bool IsEmpty() const;

  const ::std::array<uint32_t, 2>& a() const {
    ZX_ASSERT(field_presence_.IsSet<0>());
    return a_value_.value;
  }
  bool has_a() const {
    return field_presence_.IsSet<0>();
  }

  ::std::array<uint32_t, 2>* mutable_a() {
    if (!field_presence_.IsSet<0>()) {
      field_presence_.Set<0>();
      Construct(&a_value_.value);
    }
    return &a_value_.value;
  }
  TableSmallArray& set_a(::std::array<uint32_t, 2> _value);
  void clear_a() {
    if (!field_presence_.IsSet<0>()) {
      return;
    }
    field_presence_.Clear<0>();
    Destruct(&a_value_.value);
  }

  TableSmallArray();
  TableSmallArray(TableSmallArray&& other);
  ~TableSmallArray();
  TableSmallArray& operator=(TableSmallArray&& other);

  static inline ::std::unique_ptr<TableSmallArray> New() { return ::std::make_unique<TableSmallArray>(); }

  void Encode(::fidl::Encoder* _encoder, size_t _offset,
              cpp17::optional<::fidl::HandleInformation> maybe_handle_info = cpp17::nullopt);
  static void Decode(::fidl::Decoder* _decoder, TableSmallArray* _value, size_t _offset);
  zx_status_t Clone(TableSmallArray* _result) const;

 private:
  template <class T, class... Args>
  void Construct(T* p, Args&&... args) {
    new (p) T(std::forward<Args>(args)...);
  }

  template <class T>
  void Destruct(T* p) {
    p->~T();
  }

  size_t MaxOrdinal() const {
    return static_cast<size_t>(field_presence_.MaxSetIndex()) + std::size_t{1};
  }

  static bool IsOrdinalKnown(uint64_t ordinal) {
    switch (ordinal) {
      case 1:
        return true;
      default:
        return false;
    }
  }

  ::fidl::internal::BitSet<1> field_presence_;
  union ValueUnion_a {
    ValueUnion_a() {}
    ~ValueUnion_a() {}

    ::std::array<uint32_t, 2> value;
  };
  ValueUnion_a a_value_;
};

using TableSmallArrayPtr = ::std::unique_ptr<TableSmallArray>;

class TableLargeArray final {
 public:
  static const fidl_type_t* FidlType;
  /// Returns whether no field is set.
  bool IsEmpty() const;

  const ::std::array<uint32_t, 100>& a() const {
    ZX_ASSERT(field_presence_.IsSet<0>());
    return a_value_.value;
  }
  bool has_a() const {
    return field_presence_.IsSet<0>();
  }

  ::std::array<uint32_t, 100>* mutable_a() {
    if (!field_presence_.IsSet<0>()) {
      field_presence_.Set<0>();
      Construct(&a_value_.value);
    }
    return &a_value_.value;
  }
  TableLargeArray& set_a(::std::array<uint32_t, 100> _value);
  void clear_a() {
    if (!field_presence_.IsSet<0>()) {
      return;
    }
    field_presence_.Clear<0>();
    Destruct(&a_value_.value);
  }

  TableLargeArray();
  TableLargeArray(TableLargeArray&& other);
  ~TableLargeArray();
  TableLargeArray& operator=(TableLargeArray&& other);

  static inline ::std::unique_ptr<TableLargeArray> New() { return ::std::make_unique<TableLargeArray>(); }

  void Encode(::fidl::Encoder* _encoder, size_t _offset,
              cpp17::optional<::fidl::HandleInformation> maybe_handle_info = cpp17::nullopt);
  static void Decode(::fidl::Decoder* _decoder, TableLargeArray* _value, size_t _offset);
  zx_status_t Clone(TableLargeArray* _result) const;

 private:
  template <class T, class... Args>
  void Construct(T* p, Args&&... args) {
    new (p) T(std::forward<Args>(args)...);
  }

  template <class T>
  void Destruct(T* p) {
    p->~T();
  }

  size_t MaxOrdinal() const {
    return static_cast<size_t>(field_presence_.MaxSetIndex()) + std::size_t{1};
  }

  static bool IsOrdinalKnown(uint64_t ordinal) {
    switch (ordinal) {
      case 1:
        return true;
      default:
        return false;
    }
  }

  ::fidl::internal::BitSet<1> field_presence_;
  union ValueUnion_a {
    ValueUnion_a() {}
    ~ValueUnion_a() {}

    ::std::array<uint32_t, 100> value;
  };
  ValueUnion_a a_value_;
};

using TableLargeArrayPtr = ::std::unique_ptr<TableLargeArray>;

class UnionSmallArray final {
 public:
  static const fidl_type_t* FidlType;

  UnionSmallArray();
  ~UnionSmallArray();

  UnionSmallArray(UnionSmallArray&&);
  UnionSmallArray& operator=(UnionSmallArray&&);

  static UnionSmallArray WithA(::std::array<uint32_t, 2>&&);

  enum __attribute__((enum_extensibility(closed))) Tag : fidl_xunion_tag_t {

    kA = 1,  // 0x1
    Invalid = ::std::numeric_limits<::fidl_union_tag_t>::max(),
  };

  static inline ::std::unique_ptr<UnionSmallArray> New() { return ::std::make_unique<UnionSmallArray>(); }

  void Encode(::fidl::Encoder* encoder, size_t offset,
              cpp17::optional<::fidl::HandleInformation> maybe_handle_info = cpp17::nullopt);
  static void Decode(::fidl::Decoder* _decoder, UnionSmallArray* value, size_t offset);
  zx_status_t Clone(UnionSmallArray* result) const;

  bool has_invalid_tag() const {
    return tag_ == Invalid;
  }

  bool is_a() const { return tag_ == ::test::arrays::UnionSmallArray::Tag::kA; }

  ::std::array<uint32_t, 2>& a() {
    EnsureStorageInitialized(::test::arrays::UnionSmallArray::Tag::kA);
    return a_;
  }

  const ::std::array<uint32_t, 2>& a() const {
    ZX_ASSERT(is_a());
    return a_;
  }
  UnionSmallArray& set_a(::std::array<uint32_t, 2> value);

  ::test::arrays::UnionSmallArray::Tag Which() const {
    return ::test::arrays::UnionSmallArray::Tag(tag_);
  }

  // You probably want to use Which() method instead of Ordinal(). Use Ordinal() only when you need
  // access to the raw integral ordinal value.
  fidl_xunion_tag_t Ordinal() const {
    return tag_;
  }

  friend ::fidl::Equality<::test::arrays::UnionSmallArray>;

 private:
  void Destroy();
  void EnsureStorageInitialized(::fidl_xunion_tag_t tag);

  ::fidl_xunion_tag_t tag_ = static_cast<fidl_xunion_tag_t>(::test::arrays::UnionSmallArray::Tag::Invalid);
  union {
    ::std::array<uint32_t, 2> a_;
  };
};

inline zx_status_t Clone(const ::test::arrays::UnionSmallArray& value,
                         ::test::arrays::UnionSmallArray* result) {
  return value.Clone(result);
}

using UnionSmallArrayPtr = ::std::unique_ptr<UnionSmallArray>;

class UnionLargeArray final {
 public:
  static const fidl_type_t* FidlType;

  UnionLargeArray();
  ~UnionLargeArray();

  UnionLargeArray(UnionLargeArray&&);
  UnionLargeArray& operator=(UnionLargeArray&&);

  static UnionLargeArray WithA(::std::array<uint32_t, 100>&&);

  enum __attribute__((enum_extensibility(closed))) Tag : fidl_xunion_tag_t {

    kA = 1,  // 0x1
    Invalid = ::std::numeric_limits<::fidl_union_tag_t>::max(),
  };

  static inline ::std::unique_ptr<UnionLargeArray> New() { return ::std::make_unique<UnionLargeArray>(); }

  void Encode(::fidl::Encoder* encoder, size_t offset,
              cpp17::optional<::fidl::HandleInformation> maybe_handle_info = cpp17::nullopt);
  static void Decode(::fidl::Decoder* _decoder, UnionLargeArray* value, size_t offset);
  zx_status_t Clone(UnionLargeArray* result) const;

  bool has_invalid_tag() const {
    return tag_ == Invalid;
  }

  bool is_a() const { return tag_ == ::test::arrays::UnionLargeArray::Tag::kA; }

  ::std::array<uint32_t, 100>& a() {
    EnsureStorageInitialized(::test::arrays::UnionLargeArray::Tag::kA);
    return a_;
  }

  const ::std::array<uint32_t, 100>& a() const {
    ZX_ASSERT(is_a());
    return a_;
  }
  UnionLargeArray& set_a(::std::array<uint32_t, 100> value);

  ::test::arrays::UnionLargeArray::Tag Which() const {
    return ::test::arrays::UnionLargeArray::Tag(tag_);
  }

  // You probably want to use Which() method instead of Ordinal(). Use Ordinal() only when you need
  // access to the raw integral ordinal value.
  fidl_xunion_tag_t Ordinal() const {
    return tag_;
  }

  friend ::fidl::Equality<::test::arrays::UnionLargeArray>;

 private:
  void Destroy();
  void EnsureStorageInitialized(::fidl_xunion_tag_t tag);

  ::fidl_xunion_tag_t tag_ = static_cast<fidl_xunion_tag_t>(::test::arrays::UnionLargeArray::Tag::Invalid);
  union {
    ::std::array<uint32_t, 100> a_;
  };
};

inline zx_status_t Clone(const ::test::arrays::UnionLargeArray& value,
                         ::test::arrays::UnionLargeArray* result) {
  return value.Clone(result);
}

using UnionLargeArrayPtr = ::std::unique_ptr<UnionLargeArray>;

}  // namespace arrays
}  // namespace test
namespace fidl {

template <>
struct CodingTraits<::test::arrays::StructSmallArray>
    : public EncodableCodingTraits<::test::arrays::StructSmallArray, 8> {};

template <>
struct IsMemcpyCompatible<::test::arrays::StructSmallArray> : public internal::BoolConstant<
                                                                  !HasPadding<::test::arrays::StructSmallArray>::value && IsMemcpyCompatible<::std::array<uint32_t, 2>>::value> {};

inline zx_status_t Clone(const ::test::arrays::StructSmallArray& value,
                         ::test::arrays::StructSmallArray* result) {
  return ::test::arrays::Clone(value, result);
}

template <>
struct Equality<::test::arrays::StructSmallArray> {
  bool operator()(const ::test::arrays::StructSmallArray& _lhs, const ::test::arrays::StructSmallArray& _rhs) const {
    if (!::fidl::Equals(_lhs.a, _rhs.a)) {
      return false;
    }
    return true;
  }
};
template <>
struct CodingTraits<::test::arrays::StructLargeArray>
    : public EncodableCodingTraits<::test::arrays::StructLargeArray, 400> {};

template <>
struct IsMemcpyCompatible<::test::arrays::StructLargeArray> : public internal::BoolConstant<
                                                                  !HasPadding<::test::arrays::StructLargeArray>::value && IsMemcpyCompatible<::std::array<uint32_t, 100>>::value> {};

inline zx_status_t Clone(const ::test::arrays::StructLargeArray& value,
                         ::test::arrays::StructLargeArray* result) {
  return ::test::arrays::Clone(value, result);
}

template <>
struct Equality<::test::arrays::StructLargeArray> {
  bool operator()(const ::test::arrays::StructLargeArray& _lhs, const ::test::arrays::StructLargeArray& _rhs) const {
    if (!::fidl::Equals(_lhs.a, _rhs.a)) {
      return false;
    }
    return true;
  }
};
template <>
struct CodingTraits<::test::arrays::TableSmallArray>
    : public EncodableCodingTraits<::test::arrays::TableSmallArray, 16> {};

inline zx_status_t Clone(const ::test::arrays::TableSmallArray& _value,
                         ::test::arrays::TableSmallArray* result) {
  return _value.Clone(result);
}
template <>
struct Equality<::test::arrays::TableSmallArray> {
  bool operator()(const ::test::arrays::TableSmallArray& _lhs, const ::test::arrays::TableSmallArray& _rhs) const {
    if (_lhs.has_a()) {
      if (!_rhs.has_a()) {
        return false;
      }
      if (!::fidl::Equals(_lhs.a(), _rhs.a())) {
        return false;
      }
    } else if (_rhs.has_a()) {
      return false;
    }
    return true;
  }
};
template <>
struct CodingTraits<::test::arrays::TableLargeArray>
    : public EncodableCodingTraits<::test::arrays::TableLargeArray, 16> {};

inline zx_status_t Clone(const ::test::arrays::TableLargeArray& _value,
                         ::test::arrays::TableLargeArray* result) {
  return _value.Clone(result);
}
template <>
struct Equality<::test::arrays::TableLargeArray> {
  bool operator()(const ::test::arrays::TableLargeArray& _lhs, const ::test::arrays::TableLargeArray& _rhs) const {
    if (_lhs.has_a()) {
      if (!_rhs.has_a()) {
        return false;
      }
      if (!::fidl::Equals(_lhs.a(), _rhs.a())) {
        return false;
      }
    } else if (_rhs.has_a()) {
      return false;
    }
    return true;
  }
};
template <>
struct IsFidlXUnion<::test::arrays::UnionSmallArray> : public std::true_type{};

template <>
struct CodingTraits<::test::arrays::UnionSmallArray>
    : public EncodableCodingTraits<::test::arrays::UnionSmallArray, 16> {};

template <>
struct CodingTraits<std::unique_ptr<::test::arrays::UnionSmallArray>> {
  static constexpr size_t kInlineSize = 16;

  static void Encode(Encoder* encoder, std::unique_ptr<::test::arrays::UnionSmallArray>* value, size_t offset,
                     cpp17::optional<::fidl::HandleInformation> maybe_handle_info = cpp17::nullopt) {
    auto&& p_xunion = *value;
    if (p_xunion) {
      p_xunion->Encode(encoder, offset);
    }
  }

  static void Decode(Decoder* _decoder, std::unique_ptr<::test::arrays::UnionSmallArray>* value, size_t offset) {
    fidl_union_t* encoded = _decoder->GetPtr<fidl_union_t>(offset);
    if (encoded->tag == 0) {
      value->reset(nullptr);
      return;
    }

    value->reset(new ::test::arrays::UnionSmallArray);

    ::test::arrays::UnionSmallArray::Decode(_decoder, value->get(), offset);
  }
};

inline zx_status_t Clone(const ::test::arrays::UnionSmallArray& value,
                         ::test::arrays::UnionSmallArray* result) {
  return ::test::arrays::Clone(value, result);
}

template <>
struct Equality<::test::arrays::UnionSmallArray> {
  bool operator()(const ::test::arrays::UnionSmallArray& _lhs, const ::test::arrays::UnionSmallArray& _rhs) const {
    if (_lhs.Ordinal() != _rhs.Ordinal()) {
      return false;
    }

    switch (_lhs.Ordinal()) {
      case static_cast<fidl_xunion_tag_t>(::test::arrays::UnionSmallArray::Tag::Invalid):
        return true;
      case ::test::arrays::UnionSmallArray::Tag::kA:
        return ::fidl::Equals(_lhs.a_, _rhs.a_);

      default:
        return false;
    }
  }
};
template <>
struct IsFidlXUnion<::test::arrays::UnionLargeArray> : public std::true_type{};

template <>
struct CodingTraits<::test::arrays::UnionLargeArray>
    : public EncodableCodingTraits<::test::arrays::UnionLargeArray, 16> {};

template <>
struct CodingTraits<std::unique_ptr<::test::arrays::UnionLargeArray>> {
  static constexpr size_t kInlineSize = 16;

  static void Encode(Encoder* encoder, std::unique_ptr<::test::arrays::UnionLargeArray>* value, size_t offset,
                     cpp17::optional<::fidl::HandleInformation> maybe_handle_info = cpp17::nullopt) {
    auto&& p_xunion = *value;
    if (p_xunion) {
      p_xunion->Encode(encoder, offset);
    }
  }

  static void Decode(Decoder* _decoder, std::unique_ptr<::test::arrays::UnionLargeArray>* value, size_t offset) {
    fidl_union_t* encoded = _decoder->GetPtr<fidl_union_t>(offset);
    if (encoded->tag == 0) {
      value->reset(nullptr);
      return;
    }

    value->reset(new ::test::arrays::UnionLargeArray);

    ::test::arrays::UnionLargeArray::Decode(_decoder, value->get(), offset);
  }
};

inline zx_status_t Clone(const ::test::arrays::UnionLargeArray& value,
                         ::test::arrays::UnionLargeArray* result) {
  return ::test::arrays::Clone(value, result);
}

template <>
struct Equality<::test::arrays::UnionLargeArray> {
  bool operator()(const ::test::arrays::UnionLargeArray& _lhs, const ::test::arrays::UnionLargeArray& _rhs) const {
    if (_lhs.Ordinal() != _rhs.Ordinal()) {
      return false;
    }

    switch (_lhs.Ordinal()) {
      case static_cast<fidl_xunion_tag_t>(::test::arrays::UnionLargeArray::Tag::Invalid):
        return true;
      case ::test::arrays::UnionLargeArray::Tag::kA:
        return ::fidl::Equals(_lhs.a_, _rhs.a_);

      default:
        return false;
    }
  }
};

//
// Proxies and stubs declarations
//
}  // namespace fidl
