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

#pragma once

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

namespace test {
namespace handlesintypes {

//
// Domain objects declarations
//

enum class obj_type : uint32_t {

  NONE = 0u,

  VMO = 3u,
};

inline zx_status_t Clone(::test::handlesintypes::obj_type value,
                         ::test::handlesintypes::obj_type* result) {
  *result = value;
  return ZX_OK;
}

class UnionWithHandle;

class TableWithHandle;

class HandlesInTypes;

#ifdef __Fuchsia__

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

  UnionWithHandle();
  ~UnionWithHandle();

  UnionWithHandle(UnionWithHandle&&);
  UnionWithHandle& operator=(UnionWithHandle&&);

  static UnionWithHandle WithH(::zx::vmo&&);

  enum __attribute__((enum_extensibility(closed))) Tag : fidl_xunion_tag_t {
    kUnknown = 0,

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

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

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

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

  bool is_h() const { return tag_ == ::test::handlesintypes::UnionWithHandle::Tag::kH; }

  ::zx::vmo& h() {
    EnsureStorageInitialized(::test::handlesintypes::UnionWithHandle::Tag::kH);
    return h_;
  }

  const ::zx::vmo& h() const {
    ZX_ASSERT(is_h());
    return h_;
  }
  UnionWithHandle& set_h(::zx::vmo value);
  UnionWithHandle& SetUnknownData(fidl_xunion_tag_t ordinal, std::vector<uint8_t> bytes, std::vector<zx::handle> handles);

  ::test::handlesintypes::UnionWithHandle::Tag Which() const {
    switch (tag_) {
      case ::test::handlesintypes::UnionWithHandle::Tag::Invalid:
      case ::test::handlesintypes::UnionWithHandle::Tag::kH:
        return ::test::handlesintypes::UnionWithHandle::Tag(tag_);
      default:
        return ::test::handlesintypes::UnionWithHandle::Tag::kUnknown;
    }
  }

  // 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_;
  }
  const std::vector<uint8_t>* UnknownBytes() const {
    if (Which() != ::test::handlesintypes::UnionWithHandle::Tag::kUnknown) {
      return nullptr;
    }
    return &unknown_data_.bytes;
  }
  const std::vector<zx::handle>* UnknownHandles() const {
    if (Which() != ::test::handlesintypes::UnionWithHandle::Tag::kUnknown) {
      return nullptr;
    }
    return &unknown_data_.handles;
  }

  friend ::fidl::Equality<::test::handlesintypes::UnionWithHandle>;

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

  ::fidl_xunion_tag_t tag_ = static_cast<fidl_xunion_tag_t>(::test::handlesintypes::UnionWithHandle::Tag::Invalid);
  union {
    ::zx::vmo h_;
    ::fidl::UnknownData unknown_data_;
  };
};

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

using UnionWithHandlePtr = ::std::unique_ptr<UnionWithHandle>;
#endif  // __Fuchsia__

#ifdef __Fuchsia__

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

  const ::zx::vmo& h() const {
    ZX_ASSERT(field_presence_.IsSet<0>());
    return h_value_.value;
  }
  bool has_h() const {
    return field_presence_.IsSet<0>();
  }

  ::zx::vmo* mutable_h() {
    if (!field_presence_.IsSet<0>()) {
      field_presence_.Set<0>();
      Construct(&h_value_.value);
    }
    return &h_value_.value;
  }
  TableWithHandle& set_h(::zx::vmo _value) {
    if (!field_presence_.IsSet<0>()) {
      field_presence_.Set<0>();
      Construct(&h_value_.value, std::move(_value));
    } else {
      h_value_.value = std::move(_value);
    }
    return *this;
  }
  void clear_h() {
    if (!field_presence_.IsSet<0>()) {
      return;
    }
    field_presence_.Clear<0>();
    Destruct(&h_value_.value);
  }

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

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

  void Encode(::fidl::Encoder* _encoder, size_t _offset,
              cpp17::optional<::fidl::HandleInformation> maybe_handle_info = cpp17::nullopt);
  static void Decode(::fidl::Decoder* _decoder, TableWithHandle* _value, size_t _offset);
  zx_status_t Clone(TableWithHandle* _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_h {
    ValueUnion_h() {}
    ~ValueUnion_h() {}

    ::zx::vmo value;
  };
  ValueUnion_h h_value_;
};

using TableWithHandlePtr = ::std::unique_ptr<TableWithHandle>;
#endif  // __Fuchsia__

#ifdef __Fuchsia__

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

  ::zx::vmo normal_handle{};

  ::std::vector<::zx::vmo> handle_in_vec{};

  ::std::array<::zx::vmo, 5> handle_in_array{};

  ::std::vector<::std::array<::zx::vmo, 5>> handle_in_mixed_vec_array{};

  ::test::handlesintypes::TableWithHandle table_with_handle{};

  ::test::handlesintypes::UnionWithHandle union_with_handle{};

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

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

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

using HandlesInTypesPtr = ::std::unique_ptr<HandlesInTypes>;
#endif  // __Fuchsia__

}  // namespace handlesintypes
}  // namespace test
namespace fidl {
template <>
struct CodingTraits<::test::handlesintypes::obj_type> {
  static constexpr size_t inline_size_v2 = sizeof(::test::handlesintypes::obj_type);
  static void Encode(Encoder* encoder, ::test::handlesintypes::obj_type* value, size_t offset,
                     cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
    ZX_DEBUG_ASSERT(!maybe_handle_info);
    uint32_t underlying = static_cast<uint32_t>(*value);
    ::fidl::Encode(encoder, &underlying, offset);
  }
  static void Decode(Decoder* decoder, ::test::handlesintypes::obj_type* value, size_t offset) {
    uint32_t underlying = {};
    ::fidl::Decode(decoder, &underlying, offset);
    *value = static_cast<::test::handlesintypes::obj_type>(underlying);
  }
};

inline zx_status_t Clone(::test::handlesintypes::obj_type value,
                         ::test::handlesintypes::obj_type* result) {
  return ::test::handlesintypes::Clone(value, result);
}
template <>
struct Equality<::test::handlesintypes::obj_type> {
  bool operator()(const ::test::handlesintypes::obj_type& _lhs, const ::test::handlesintypes::obj_type& _rhs) const {
    return _lhs == _rhs;
  }
};

#ifdef __Fuchsia__

template <>
struct IsFidlXUnion<::test::handlesintypes::UnionWithHandle> : public std::true_type {};

template <>
struct CodingTraits<::test::handlesintypes::UnionWithHandle>
    : public EncodableCodingTraits<::test::handlesintypes::UnionWithHandle, 16> {};

template <>
struct CodingTraits<std::unique_ptr<::test::handlesintypes::UnionWithHandle>> {
  static constexpr size_t inline_size_v2 = 16;

  static void Encode(Encoder* encoder, std::unique_ptr<::test::handlesintypes::UnionWithHandle>* 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::handlesintypes::UnionWithHandle>* value, size_t offset) {
    fidl_xunion_t* encoded = _decoder->GetPtr<fidl_xunion_t>(offset);
    if (encoded->tag == 0) {
      value->reset(nullptr);
      return;
    }

    value->reset(new ::test::handlesintypes::UnionWithHandle);

    ::test::handlesintypes::UnionWithHandle::Decode(_decoder, value->get(), offset);
  }
};

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

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

    switch (_lhs.Ordinal()) {
      case static_cast<fidl_xunion_tag_t>(::test::handlesintypes::UnionWithHandle::Tag::Invalid):
        return true;
      case ::test::handlesintypes::UnionWithHandle::Tag::kH:
        return ::fidl::Equals(_lhs.h_, _rhs.h_);
      default:
        return ::fidl::Equals(_lhs.unknown_data_, _rhs.unknown_data_);
    }
  }
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
struct CodingTraits<::test::handlesintypes::TableWithHandle>
    : public EncodableCodingTraits<::test::handlesintypes::TableWithHandle, 16> {};

inline zx_status_t Clone(const ::test::handlesintypes::TableWithHandle& _value,
                         ::test::handlesintypes::TableWithHandle* result) {
  return _value.Clone(result);
}
template <>
struct Equality<::test::handlesintypes::TableWithHandle> {
  bool operator()(const ::test::handlesintypes::TableWithHandle& _lhs, const ::test::handlesintypes::TableWithHandle& _rhs) const {
    if (_lhs.has_h()) {
      if (!_rhs.has_h()) {
        return false;
      }
      if (!::fidl::Equals(_lhs.h(), _rhs.h())) {
        return false;
      }
    } else if (_rhs.has_h()) {
      return false;
    }
    return true;
  }
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
struct CodingTraits<::test::handlesintypes::HandlesInTypes>
    : public EncodableCodingTraits<::test::handlesintypes::HandlesInTypes, 96> {};

template <>
struct HasPadding<::test::handlesintypes::HandlesInTypes> : public std::true_type {};

template <>
struct IsMemcpyCompatible<::test::handlesintypes::HandlesInTypes> : public internal::BoolConstant<
                                                                        !HasPadding<::test::handlesintypes::HandlesInTypes>::value && IsMemcpyCompatible<::zx::vmo>::value && IsMemcpyCompatible<::std::vector<::zx::vmo>>::value && IsMemcpyCompatible<::std::array<::zx::vmo, 5>>::value && IsMemcpyCompatible<::std::vector<::std::array<::zx::vmo, 5>>>::value && IsMemcpyCompatible<::test::handlesintypes::TableWithHandle>::value && IsMemcpyCompatible<::test::handlesintypes::UnionWithHandle>::value> {};

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

template <>
struct Equality<::test::handlesintypes::HandlesInTypes> {
  bool operator()(const ::test::handlesintypes::HandlesInTypes& _lhs, const ::test::handlesintypes::HandlesInTypes& _rhs) const {
    if (!::fidl::Equals(_lhs.normal_handle, _rhs.normal_handle)) {
      return false;
    }
    if (!::fidl::Equals(_lhs.handle_in_vec, _rhs.handle_in_vec)) {
      return false;
    }
    if (!::fidl::Equals(_lhs.handle_in_array, _rhs.handle_in_array)) {
      return false;
    }
    if (!::fidl::Equals(_lhs.handle_in_mixed_vec_array, _rhs.handle_in_mixed_vec_array)) {
      return false;
    }
    if (!::fidl::Equals(_lhs.table_with_handle, _rhs.table_with_handle)) {
      return false;
    }
    if (!::fidl::Equals(_lhs.union_with_handle, _rhs.union_with_handle)) {
      return false;
    }
    return true;
  }
};
#endif  // __Fuchsia__

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