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

#pragma once

#include <lib/fidl/internal.h>
#include <lib/fidl/llcpp/array.h>
#include <lib/fidl/llcpp/buffer_allocator.h>
#include <lib/fidl/llcpp/buffer_then_heap_allocator.h>
#include <lib/fidl/llcpp/coding.h>
#include <lib/fidl/llcpp/envelope.h>
#include <lib/fidl/llcpp/errors.h>
#include <lib/fidl/llcpp/memory.h>
#include <lib/fidl/llcpp/message.h>
#include <lib/fidl/llcpp/message_storage.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/fidl/llcpp/tracking_ptr.h>
#include <lib/fidl/llcpp/traits.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/fit/function.h>
#include <lib/fit/optional.h>

#include <variant>
#ifdef __Fuchsia__
#include <lib/fidl/llcpp/client.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/result.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl/llcpp/service_handler_interface.h>
#include <lib/fidl/llcpp/sync_call.h>
#include <lib/fidl/llcpp/transaction.h>
#include <lib/fidl/txn_header.h>
#include <lib/zx/vmo.h>
#endif  // __Fuchsia__
#include <zircon/fidl.h>

namespace llcpp {

namespace fidl {
namespace test {
namespace handlesintypes {

enum class obj_type : uint32_t {

  NONE = 0u,

  VMO = 3u,
};

class UnionWithHandle;
class TableWithHandle;
struct HandlesInTypes;

#ifdef __Fuchsia__
extern "C" const fidl_type_t fidl_test_handlesintypes_UnionWithHandleTable;

class UnionWithHandle {
 public:
  UnionWithHandle() : ordinal_(Ordinal::Invalid), envelope_{} {}

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

  ~UnionWithHandle() { reset_ptr(nullptr); }

  enum class Tag : fidl_xunion_tag_t {
    kH = 1,  // 0x1
    kUnknown = ::std::numeric_limits<::fidl_union_tag_t>::max(),
  };

  bool has_invalid_tag() const { return ordinal_ == Ordinal::Invalid; }

  bool is_h() const { return ordinal_ == Ordinal::kH; }

  static UnionWithHandle WithH(::fidl::tracking_ptr<::zx::vmo>&& val) {
    UnionWithHandle result;
    result.set_h(std::move(val));
    return result;
  }

  void set_h(::fidl::tracking_ptr<::zx::vmo>&& elem) {
    ordinal_ = Ordinal::kH;
    reset_ptr(static_cast<::fidl::tracking_ptr<void>>(std::move(elem)));
  }

  ::zx::vmo& mutable_h() {
    ZX_ASSERT(ordinal_ == Ordinal::kH);
    return *static_cast<::zx::vmo*>(envelope_.data.get());
  }
  const ::zx::vmo& h() const {
    ZX_ASSERT(ordinal_ == Ordinal::kH);
    return *static_cast<::zx::vmo*>(envelope_.data.get());
  }
  Tag which() const;

  static constexpr const fidl_type_t* Type =
      &fidl_test_handlesintypes_UnionWithHandleTable;
  static constexpr uint32_t MaxNumHandles = 1;
  static constexpr uint32_t PrimarySize = 24;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 8;
  static constexpr bool HasPointer = true;

  void _CloseHandles();

 private:
  enum class Ordinal : fidl_xunion_tag_t {
    Invalid = 0,
    kH = 1,  // 0x1
  };

  void reset_ptr(::fidl::tracking_ptr<void>&& new_ptr) {
    // To clear the existing value, std::move it and let it go out of scope.
    switch (static_cast<fidl_xunion_tag_t>(ordinal_)) {
      case 1: {
        ::fidl::tracking_ptr<::zx::vmo> to_destroy =
            static_cast<::fidl::tracking_ptr<::zx::vmo>>(
                std::move(envelope_.data));
        break;
      }
    }

    envelope_.data = std::move(new_ptr);
  }

  static void SizeAndOffsetAssertionHelper();
  Ordinal ordinal_;
  FIDL_ALIGNDECL
  ::fidl::Envelope<void> envelope_;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__
extern "C" const fidl_type_t fidl_test_handlesintypes_TableWithHandleTable;

class TableWithHandle final {
 public:
  // Returns whether no field is set.
  bool IsEmpty() const { return max_ordinal_ == 0; }

  const ::zx::vmo& h() const {
    ZX_ASSERT(has_h());
    return *frame_ptr_->h_.data;
  }
  ::zx::vmo& h() {
    ZX_ASSERT(has_h());
    return *frame_ptr_->h_.data;
  }
  bool has_h() const {
    return max_ordinal_ >= 1 && frame_ptr_->h_.data != nullptr;
  }

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

  static constexpr const fidl_type_t* Type =
      &fidl_test_handlesintypes_TableWithHandleTable;
  static constexpr uint32_t MaxNumHandles = 1;
  static constexpr uint32_t PrimarySize = 16;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 24;
  static constexpr bool HasPointer = true;

  void _CloseHandles();

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          TableWithHandle* value)
        : message_(bytes, byte_size, sizeof(TableWithHandle), handles_,
                   std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
      message_.LinearizeAndEncode<TableWithHandle>(value);
    }
    UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
    UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

    zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
    const char* status_string() const { return message_.status_string(); }
#endif
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

   private:
    zx_handle_disposition_t
        handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(TableWithHandle* value)
        : message_(bytes_, sizeof(bytes_), value) {}
    OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
    OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

    zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
    const char* status_string() const { return message_.status_string(); }
#endif
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() {
      return message_.GetOutgoingMessage();
    }

   private:
    FIDL_ALIGNDECL
    uint8_t bytes_[FIDL_ALIGN(PrimarySize + MaxOutOfLine)];
    UnownedEncodedMessage message_;
  };

  class DecodedMessage final : public ::fidl::internal::IncomingMessage {
   public:
    DecodedMessage(uint8_t* bytes, uint32_t byte_actual,
                   zx_handle_info_t* handles = nullptr,
                   uint32_t handle_actual = 0)
        : ::fidl::internal::IncomingMessage(bytes, byte_actual, handles,
                                            handle_actual) {
      Decode<TableWithHandle>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<TableWithHandle>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;
    ~DecodedMessage() {
      if (ok() && (PrimaryObject() != nullptr)) {
        PrimaryObject()->_CloseHandles();
      }
    }

    TableWithHandle* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<TableWithHandle*>(bytes());
    }

    // Release the ownership of the decoded message. That means that the handles
    // won't be closed When the object is destroyed. After calling this method,
    // the DecodedMessage object should not be used anymore.
    void ReleasePrimaryObject() { ResetBytes(); }

    // These methods should only be used for testing purpose.
    // They create an DecodedMessage using the bytes of an outgoing message and
    // copying the handles.
    static DecodedMessage FromOutgoingWithRawHandleCopy(
        UnownedEncodedMessage* encoded_message) {
      return DecodedMessage(encoded_message->GetOutgoingMessage());
    }
    static DecodedMessage FromOutgoingWithRawHandleCopy(
        OwnedEncodedMessage* encoded_message) {
      return DecodedMessage(encoded_message->GetOutgoingMessage());
    }

   private:
    DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
      zx_handle_info_t
          handles[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
      Init(outgoing_message, handles,
           std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles));
      if (ok()) {
        Decode<TableWithHandle>();
      }
    }
  };

  class Builder;
  class UnownedBuilder;

  class Frame final {
   public:
    Frame() = default;
    // In its intended usage, Frame will be referenced by a tracking_ptr. If the
    // tracking_ptr is assigned before a move or copy, then it will reference
    // the old invalid object. Because this is unsafe, copies are disallowed and
    // moves are only allowed by friend classes that operate safely.
    Frame(const Frame&) = delete;
    Frame& operator=(const Frame&) = delete;

   private:
    Frame(Frame&&) noexcept = default;
    Frame& operator=(Frame&&) noexcept = default;
    ::fidl::Envelope<::zx::vmo> h_;

    friend class TableWithHandle;
    friend class TableWithHandle::Builder;
    friend class TableWithHandle::UnownedBuilder;
  };

 private:
  TableWithHandle(uint64_t max_ordinal, ::fidl::tracking_ptr<Frame>&& frame_ptr)
      : max_ordinal_(max_ordinal), frame_ptr_(std::move(frame_ptr)) {}
  uint64_t max_ordinal_ = 0;
  ::fidl::tracking_ptr<Frame> frame_ptr_;
};

// TableWithHandle::Builder builds TableWithHandle.
// Usage:
// TableWithHandle val =
// TableWithHandle::Builder(std::make_unique<TableWithHandle::Frame>())
// .set_h(ptr)
// .build();
class TableWithHandle::Builder final {
 public:
  ~Builder() = default;
  Builder() = delete;
  Builder(::fidl::tracking_ptr<TableWithHandle::Frame>&& frame_ptr)
      : max_ordinal_(0), frame_ptr_(std::move(frame_ptr)) {}

  Builder(Builder&& other) noexcept = default;
  Builder& operator=(Builder&& other) noexcept = default;

  Builder(const Builder& other) = delete;
  Builder& operator=(const Builder& other) = delete;

  // Returns whether no field is set.
  bool IsEmpty() const { return max_ordinal_ == 0; }

  Builder&& set_h(::fidl::tracking_ptr<::zx::vmo> elem) {
    frame_ptr_->h_.data = std::move(elem);
    if (max_ordinal_ < 1) {
      // Note: the table size is not currently reduced if nullptr is set.
      // This is possible to reconsider in the future.
      max_ordinal_ = 1;
    }
    return std::move(*this);
  }
  const ::zx::vmo& h() const {
    ZX_ASSERT(has_h());
    return *frame_ptr_->h_.data;
  }
  ::zx::vmo& h() {
    ZX_ASSERT(has_h());
    return *frame_ptr_->h_.data;
  }
  bool has_h() const {
    return max_ordinal_ >= 1 && frame_ptr_->h_.data != nullptr;
  }

  TableWithHandle build() {
    return TableWithHandle(max_ordinal_, std::move(frame_ptr_));
  }

 private:
  uint64_t max_ordinal_ = 0;
  ::fidl::tracking_ptr<TableWithHandle::Frame> frame_ptr_;
};

// UnownedBuilder acts like Builder but directly owns its Frame, simplifying
// working with unowned data.
class TableWithHandle::UnownedBuilder final {
 public:
  ~UnownedBuilder() = default;
  UnownedBuilder() noexcept = default;
  UnownedBuilder(UnownedBuilder&& other) noexcept = default;
  UnownedBuilder& operator=(UnownedBuilder&& other) noexcept = default;

  // Returns whether no field is set.
  bool IsEmpty() const { return max_ordinal_ == 0; }

  UnownedBuilder&& set_h(::fidl::tracking_ptr<::zx::vmo> elem) {
    ZX_ASSERT(elem);
    frame_.h_.data = std::move(elem);
    if (max_ordinal_ < 1) {
      max_ordinal_ = 1;
    }
    return std::move(*this);
  }
  const ::zx::vmo& h() const {
    ZX_ASSERT(has_h());
    return *frame_.h_.data;
  }
  ::zx::vmo& h() {
    ZX_ASSERT(has_h());
    return *frame_.h_.data;
  }
  bool has_h() const { return max_ordinal_ >= 1 && frame_.h_.data != nullptr; }

  TableWithHandle build() {
    return TableWithHandle(max_ordinal_, ::fidl::unowned_ptr(&frame_));
  }

 private:
  uint64_t max_ordinal_ = 0;
  TableWithHandle::Frame frame_;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__
extern "C" const fidl_type_t fidl_test_handlesintypes_HandlesInTypesTable;

struct HandlesInTypes {
  static constexpr const fidl_type_t* Type =
      &fidl_test_handlesintypes_HandlesInTypesTable;
  static constexpr uint32_t MaxNumHandles = 4294967295;
  static constexpr uint32_t PrimarySize = 104;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

  ::zx::vmo normal_handle = {};

  ::fidl::VectorView<::zx::vmo> handle_in_vec = {};

  ::fidl::Array<::zx::vmo, 5> handle_in_array = {};

  ::fidl::VectorView<::fidl::Array<::zx::vmo, 5>> handle_in_mixed_vec_array =
      {};

  ::llcpp::fidl::test::handlesintypes::TableWithHandle table_with_handle = {};

  ::llcpp::fidl::test::handlesintypes::UnionWithHandle union_with_handle = {};

  void _CloseHandles();

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          HandlesInTypes* value)
        : message_(bytes, byte_size, sizeof(HandlesInTypes), handles_,
                   std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
      message_.LinearizeAndEncode<HandlesInTypes>(value);
    }
    UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
    UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
    UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

    zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
    const char* status_string() const { return message_.status_string(); }
#endif
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

   private:
    zx_handle_disposition_t
        handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(HandlesInTypes* value)
        : bytes_(std::make_unique<
                 ::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>()),
          message_(bytes_->data(), ZX_CHANNEL_MAX_MSG_BYTES, value) {}
    OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
    OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
    OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

    zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
    const char* status_string() const { return message_.status_string(); }
#endif
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() {
      return message_.GetOutgoingMessage();
    }

   private:
    std::unique_ptr<::fidl::internal::AlignedBuffer<ZX_CHANNEL_MAX_MSG_BYTES>>
        bytes_;
    UnownedEncodedMessage message_;
  };

  class DecodedMessage final : public ::fidl::internal::IncomingMessage {
   public:
    DecodedMessage(uint8_t* bytes, uint32_t byte_actual,
                   zx_handle_info_t* handles = nullptr,
                   uint32_t handle_actual = 0)
        : ::fidl::internal::IncomingMessage(bytes, byte_actual, handles,
                                            handle_actual) {
      Decode<struct HandlesInTypes>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<struct HandlesInTypes>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;
    ~DecodedMessage() {
      if (ok() && (PrimaryObject() != nullptr)) {
        PrimaryObject()->_CloseHandles();
      }
    }

    struct HandlesInTypes* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<struct HandlesInTypes*>(bytes());
    }

    // Release the ownership of the decoded message. That means that the handles
    // won't be closed When the object is destroyed. After calling this method,
    // the DecodedMessage object should not be used anymore.
    void ReleasePrimaryObject() { ResetBytes(); }

    // These methods should only be used for testing purpose.
    // They create an DecodedMessage using the bytes of an outgoing message and
    // copying the handles.
    static DecodedMessage FromOutgoingWithRawHandleCopy(
        UnownedEncodedMessage* encoded_message) {
      return DecodedMessage(encoded_message->GetOutgoingMessage());
    }
    static DecodedMessage FromOutgoingWithRawHandleCopy(
        OwnedEncodedMessage* encoded_message) {
      return DecodedMessage(encoded_message->GetOutgoingMessage());
    }

   private:
    DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
      zx_handle_info_t
          handles[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
      Init(outgoing_message, handles,
           std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles));
      if (ok()) {
        Decode<struct HandlesInTypes>();
      }
    }
  };
};
#endif  // __Fuchsia__

}  // namespace handlesintypes
}  // namespace test
}  // namespace fidl
}  // namespace llcpp

namespace fidl {

template <>
struct IsFidlType<::llcpp::fidl::test::handlesintypes::obj_type>
    : public std::true_type {};

#ifdef __Fuchsia__
template <>
struct IsFidlType<::llcpp::fidl::test::handlesintypes::UnionWithHandle>
    : public std::true_type {};
template <>
struct IsUnion<::llcpp::fidl::test::handlesintypes::UnionWithHandle>
    : public std::true_type {};
static_assert(std::is_standard_layout_v<
              ::llcpp::fidl::test::handlesintypes::UnionWithHandle>);
#endif  // __Fuchsia__

#ifdef __Fuchsia__
template <>
struct IsFidlType<::llcpp::fidl::test::handlesintypes::TableWithHandle>
    : public std::true_type {};
template <>
struct IsTable<::llcpp::fidl::test::handlesintypes::TableWithHandle>
    : public std::true_type {};
template <>
struct IsTableBuilder<
    ::llcpp::fidl::test::handlesintypes::TableWithHandle::Builder>
    : public std::true_type {};
static_assert(std::is_standard_layout_v<
              ::llcpp::fidl::test::handlesintypes::TableWithHandle>);
#endif  // __Fuchsia__

#ifdef __Fuchsia__
template <>
struct IsFidlType<::llcpp::fidl::test::handlesintypes::HandlesInTypes>
    : public std::true_type {};
template <>
struct IsStruct<::llcpp::fidl::test::handlesintypes::HandlesInTypes>
    : public std::true_type {};
static_assert(std::is_standard_layout_v<
              ::llcpp::fidl::test::handlesintypes::HandlesInTypes>);
static_assert(offsetof(::llcpp::fidl::test::handlesintypes::HandlesInTypes,
                       normal_handle) == 0);
static_assert(offsetof(::llcpp::fidl::test::handlesintypes::HandlesInTypes,
                       handle_in_vec) == 8);
static_assert(offsetof(::llcpp::fidl::test::handlesintypes::HandlesInTypes,
                       handle_in_array) == 24);
static_assert(offsetof(::llcpp::fidl::test::handlesintypes::HandlesInTypes,
                       handle_in_mixed_vec_array) == 48);
static_assert(offsetof(::llcpp::fidl::test::handlesintypes::HandlesInTypes,
                       table_with_handle) == 64);
static_assert(offsetof(::llcpp::fidl::test::handlesintypes::HandlesInTypes,
                       union_with_handle) == 80);
static_assert(sizeof(::llcpp::fidl::test::handlesintypes::HandlesInTypes) ==
              ::llcpp::fidl::test::handlesintypes::HandlesInTypes::PrimarySize);
#endif  // __Fuchsia__

}  // namespace fidl

namespace llcpp {

namespace fidl {
namespace test {
namespace handlesintypes {}  // namespace handlesintypes
}  // namespace test
}  // namespace fidl
}  // namespace llcpp
