// 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/coding.h>
#include <lib/fidl/llcpp/envelope.h>
#include <lib/fidl/llcpp/errors.h>
#include <lib/fidl/llcpp/message.h>
#include <lib/fidl/llcpp/message_storage.h>
#include <lib/fidl/llcpp/object_view.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/fidl/llcpp/traits.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/fit/function.h>
#include <lib/stdcompat/optional.h>

#include <algorithm>
#include <cstddef>
#include <variant>
#ifdef __Fuchsia__
#include <lib/fidl/llcpp/client.h>
#include <lib/fidl/llcpp/client_end.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/result.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl/llcpp/server_end.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/llcpp/wire_messaging.h>
#include <lib/fidl/txn_header.h>

#endif  // __Fuchsia__
#include <zircon/fidl.h>

namespace fidl_test_table {
namespace wire {
class SimpleTable;

class ReverseOrdinalTable;

class OlderSimpleTable;

class NewerSimpleTable;

class EmptyTable;

extern "C" const fidl_type_t fidl_test_table_SimpleTableTable;

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

  class Frame;

  const int64_t& x() const {
    ZX_ASSERT(has_x());
    return *frame_ptr_->x_.data;
  }
  int64_t& x() {
    ZX_ASSERT(has_x());
    return *frame_ptr_->x_.data;
  }
  bool has_x() const {
    return max_ordinal_ >= 1 && frame_ptr_->x_.data != nullptr;
  }
  SimpleTable& set_x(::fidl::ObjectView<int64_t> elem) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data = elem;
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(1));
    return *this;
  }
  SimpleTable& set_x(std::nullptr_t) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data = nullptr;
    return *this;
  }
  template <typename... Args>
  SimpleTable& set_x(::fidl::AnyAllocator& allocator, Args&&... args) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data =
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...);
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(1));
    return *this;
  }

  const int64_t& y() const {
    ZX_ASSERT(has_y());
    return *frame_ptr_->y_.data;
  }
  int64_t& y() {
    ZX_ASSERT(has_y());
    return *frame_ptr_->y_.data;
  }
  bool has_y() const {
    return max_ordinal_ >= 5 && frame_ptr_->y_.data != nullptr;
  }
  SimpleTable& set_y(::fidl::ObjectView<int64_t> elem) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->y_.data = elem;
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(5));
    return *this;
  }
  SimpleTable& set_y(std::nullptr_t) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->y_.data = nullptr;
    return *this;
  }
  template <typename... Args>
  SimpleTable& set_y(::fidl::AnyAllocator& allocator, Args&&... args) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->y_.data =
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...);
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(5));
    return *this;
  }

  SimpleTable() = default;
  explicit SimpleTable(::fidl::AnyAllocator& allocator)
      : frame_ptr_(::fidl::ObjectView<Frame>(allocator)) {}
  // This constructor allows a user controlled allocation (not using a
  // FidlAllocator). It should only be used when performance is key. As soon as
  // the frame is given to the table, it must not be used directly or for
  // another table.
  explicit SimpleTable(::fidl::ObjectView<Frame>&& frame)
      : frame_ptr_(std::move(frame)) {}
  ~SimpleTable() = default;
  SimpleTable(const SimpleTable& other) noexcept = default;
  SimpleTable& operator=(const SimpleTable& other) noexcept = default;
  SimpleTable(SimpleTable&& other) noexcept = default;
  SimpleTable& operator=(SimpleTable&& other) noexcept = default;

  static constexpr const fidl_type_t* Type = &fidl_test_table_SimpleTableTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 16;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 96;
  static constexpr bool HasPointer = true;

  void Allocate(::fidl::AnyAllocator& allocator) {
    max_ordinal_ = 0;
    frame_ptr_ = ::fidl::ObjectView<Frame>(allocator);
  }
  void Init(::fidl::ObjectView<Frame>&& frame_ptr) {
    max_ordinal_ = 0;
    frame_ptr_ = std::move(frame_ptr);
  }

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          SimpleTable* value)
        : message_(bytes, byte_size, sizeof(SimpleTable), nullptr, 0, 0) {
      message_.Encode<SimpleTable>(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  // __Fuchsia__
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

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

   private:
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(SimpleTable* value)
        : message_(bytes_.data(), bytes_.size(), 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  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

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

   private:
    ::fidl::internal::InlineMessageBuffer<112> 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<SimpleTable>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<SimpleTable>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

    SimpleTable* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<SimpleTable*>(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(); }
  };

  // Frames are managed automatically by the FidlAllocator class.
  // The only direct usage is when performance is key and a frame needs to be
  // allocated outside a FidlAllocator. Once created, a frame can only be used
  // for one single table.
  class Frame final {
   public:
    Frame() = default;
    // In its intended usage, Frame will be referenced by an ObjectView. If the
    // ObjectView 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<int64_t> x_;
    ::fidl::Envelope<void> reserved_1_;
    ::fidl::Envelope<void> reserved_2_;
    ::fidl::Envelope<void> reserved_3_;
    ::fidl::Envelope<int64_t> y_;

    friend class SimpleTable;
  };

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

extern "C" const fidl_type_t fidl_test_table_ReverseOrdinalTableTable;

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

  class Frame;

  const int64_t& z() const {
    ZX_ASSERT(has_z());
    return *frame_ptr_->z_.data;
  }
  int64_t& z() {
    ZX_ASSERT(has_z());
    return *frame_ptr_->z_.data;
  }
  bool has_z() const {
    return max_ordinal_ >= 1 && frame_ptr_->z_.data != nullptr;
  }
  ReverseOrdinalTable& set_z(::fidl::ObjectView<int64_t> elem) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->z_.data = elem;
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(1));
    return *this;
  }
  ReverseOrdinalTable& set_z(std::nullptr_t) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->z_.data = nullptr;
    return *this;
  }
  template <typename... Args>
  ReverseOrdinalTable& set_z(::fidl::AnyAllocator& allocator, Args&&... args) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->z_.data =
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...);
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(1));
    return *this;
  }

  const int64_t& y() const {
    ZX_ASSERT(has_y());
    return *frame_ptr_->y_.data;
  }
  int64_t& y() {
    ZX_ASSERT(has_y());
    return *frame_ptr_->y_.data;
  }
  bool has_y() const {
    return max_ordinal_ >= 2 && frame_ptr_->y_.data != nullptr;
  }
  ReverseOrdinalTable& set_y(::fidl::ObjectView<int64_t> elem) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->y_.data = elem;
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(2));
    return *this;
  }
  ReverseOrdinalTable& set_y(std::nullptr_t) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->y_.data = nullptr;
    return *this;
  }
  template <typename... Args>
  ReverseOrdinalTable& set_y(::fidl::AnyAllocator& allocator, Args&&... args) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->y_.data =
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...);
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(2));
    return *this;
  }

  const int64_t& x() const {
    ZX_ASSERT(has_x());
    return *frame_ptr_->x_.data;
  }
  int64_t& x() {
    ZX_ASSERT(has_x());
    return *frame_ptr_->x_.data;
  }
  bool has_x() const {
    return max_ordinal_ >= 3 && frame_ptr_->x_.data != nullptr;
  }
  ReverseOrdinalTable& set_x(::fidl::ObjectView<int64_t> elem) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data = elem;
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(3));
    return *this;
  }
  ReverseOrdinalTable& set_x(std::nullptr_t) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data = nullptr;
    return *this;
  }
  template <typename... Args>
  ReverseOrdinalTable& set_x(::fidl::AnyAllocator& allocator, Args&&... args) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data =
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...);
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(3));
    return *this;
  }

  ReverseOrdinalTable() = default;
  explicit ReverseOrdinalTable(::fidl::AnyAllocator& allocator)
      : frame_ptr_(::fidl::ObjectView<Frame>(allocator)) {}
  // This constructor allows a user controlled allocation (not using a
  // FidlAllocator). It should only be used when performance is key. As soon as
  // the frame is given to the table, it must not be used directly or for
  // another table.
  explicit ReverseOrdinalTable(::fidl::ObjectView<Frame>&& frame)
      : frame_ptr_(std::move(frame)) {}
  ~ReverseOrdinalTable() = default;
  ReverseOrdinalTable(const ReverseOrdinalTable& other) noexcept = default;
  ReverseOrdinalTable& operator=(const ReverseOrdinalTable& other) noexcept =
      default;
  ReverseOrdinalTable(ReverseOrdinalTable&& other) noexcept = default;
  ReverseOrdinalTable& operator=(ReverseOrdinalTable&& other) noexcept =
      default;

  static constexpr const fidl_type_t* Type =
      &fidl_test_table_ReverseOrdinalTableTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 16;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 72;
  static constexpr bool HasPointer = true;

  void Allocate(::fidl::AnyAllocator& allocator) {
    max_ordinal_ = 0;
    frame_ptr_ = ::fidl::ObjectView<Frame>(allocator);
  }
  void Init(::fidl::ObjectView<Frame>&& frame_ptr) {
    max_ordinal_ = 0;
    frame_ptr_ = std::move(frame_ptr);
  }

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          ReverseOrdinalTable* value)
        : message_(bytes, byte_size, sizeof(ReverseOrdinalTable), nullptr, 0,
                   0) {
      message_.Encode<ReverseOrdinalTable>(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  // __Fuchsia__
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

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

   private:
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(ReverseOrdinalTable* value)
        : message_(bytes_.data(), bytes_.size(), 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  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

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

   private:
    ::fidl::internal::InlineMessageBuffer<88> 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<ReverseOrdinalTable>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<ReverseOrdinalTable>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

    ReverseOrdinalTable* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<ReverseOrdinalTable*>(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(); }
  };

  // Frames are managed automatically by the FidlAllocator class.
  // The only direct usage is when performance is key and a frame needs to be
  // allocated outside a FidlAllocator. Once created, a frame can only be used
  // for one single table.
  class Frame final {
   public:
    Frame() = default;
    // In its intended usage, Frame will be referenced by an ObjectView. If the
    // ObjectView 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<int64_t> z_;
    ::fidl::Envelope<int64_t> y_;
    ::fidl::Envelope<int64_t> x_;

    friend class ReverseOrdinalTable;
  };

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

extern "C" const fidl_type_t fidl_test_table_OlderSimpleTableTable;

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

  class Frame;

  const int64_t& x() const {
    ZX_ASSERT(has_x());
    return *frame_ptr_->x_.data;
  }
  int64_t& x() {
    ZX_ASSERT(has_x());
    return *frame_ptr_->x_.data;
  }
  bool has_x() const {
    return max_ordinal_ >= 1 && frame_ptr_->x_.data != nullptr;
  }
  OlderSimpleTable& set_x(::fidl::ObjectView<int64_t> elem) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data = elem;
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(1));
    return *this;
  }
  OlderSimpleTable& set_x(std::nullptr_t) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data = nullptr;
    return *this;
  }
  template <typename... Args>
  OlderSimpleTable& set_x(::fidl::AnyAllocator& allocator, Args&&... args) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data =
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...);
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(1));
    return *this;
  }

  OlderSimpleTable() = default;
  explicit OlderSimpleTable(::fidl::AnyAllocator& allocator)
      : frame_ptr_(::fidl::ObjectView<Frame>(allocator)) {}
  // This constructor allows a user controlled allocation (not using a
  // FidlAllocator). It should only be used when performance is key. As soon as
  // the frame is given to the table, it must not be used directly or for
  // another table.
  explicit OlderSimpleTable(::fidl::ObjectView<Frame>&& frame)
      : frame_ptr_(std::move(frame)) {}
  ~OlderSimpleTable() = default;
  OlderSimpleTable(const OlderSimpleTable& other) noexcept = default;
  OlderSimpleTable& operator=(const OlderSimpleTable& other) noexcept = default;
  OlderSimpleTable(OlderSimpleTable&& other) noexcept = default;
  OlderSimpleTable& operator=(OlderSimpleTable&& other) noexcept = default;

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

  void Allocate(::fidl::AnyAllocator& allocator) {
    max_ordinal_ = 0;
    frame_ptr_ = ::fidl::ObjectView<Frame>(allocator);
  }
  void Init(::fidl::ObjectView<Frame>&& frame_ptr) {
    max_ordinal_ = 0;
    frame_ptr_ = std::move(frame_ptr);
  }

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          OlderSimpleTable* value)
        : message_(bytes, byte_size, sizeof(OlderSimpleTable), nullptr, 0, 0) {
      message_.Encode<OlderSimpleTable>(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  // __Fuchsia__
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

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

   private:
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(OlderSimpleTable* value)
        : message_(bytes_.data(), bytes_.size(), 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  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

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

   private:
    ::fidl::internal::InlineMessageBuffer<40> 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<OlderSimpleTable>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<OlderSimpleTable>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

    OlderSimpleTable* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<OlderSimpleTable*>(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(); }
  };

  // Frames are managed automatically by the FidlAllocator class.
  // The only direct usage is when performance is key and a frame needs to be
  // allocated outside a FidlAllocator. Once created, a frame can only be used
  // for one single table.
  class Frame final {
   public:
    Frame() = default;
    // In its intended usage, Frame will be referenced by an ObjectView. If the
    // ObjectView 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<int64_t> x_;

    friend class OlderSimpleTable;
  };

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

extern "C" const fidl_type_t fidl_test_table_NewerSimpleTableTable;

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

  class Frame;

  const int64_t& x() const {
    ZX_ASSERT(has_x());
    return *frame_ptr_->x_.data;
  }
  int64_t& x() {
    ZX_ASSERT(has_x());
    return *frame_ptr_->x_.data;
  }
  bool has_x() const {
    return max_ordinal_ >= 1 && frame_ptr_->x_.data != nullptr;
  }
  NewerSimpleTable& set_x(::fidl::ObjectView<int64_t> elem) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data = elem;
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(1));
    return *this;
  }
  NewerSimpleTable& set_x(std::nullptr_t) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data = nullptr;
    return *this;
  }
  template <typename... Args>
  NewerSimpleTable& set_x(::fidl::AnyAllocator& allocator, Args&&... args) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->x_.data =
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...);
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(1));
    return *this;
  }

  const int64_t& y() const {
    ZX_ASSERT(has_y());
    return *frame_ptr_->y_.data;
  }
  int64_t& y() {
    ZX_ASSERT(has_y());
    return *frame_ptr_->y_.data;
  }
  bool has_y() const {
    return max_ordinal_ >= 5 && frame_ptr_->y_.data != nullptr;
  }
  NewerSimpleTable& set_y(::fidl::ObjectView<int64_t> elem) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->y_.data = elem;
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(5));
    return *this;
  }
  NewerSimpleTable& set_y(std::nullptr_t) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->y_.data = nullptr;
    return *this;
  }
  template <typename... Args>
  NewerSimpleTable& set_y(::fidl::AnyAllocator& allocator, Args&&... args) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->y_.data =
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...);
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(5));
    return *this;
  }

  const int64_t& z() const {
    ZX_ASSERT(has_z());
    return *frame_ptr_->z_.data;
  }
  int64_t& z() {
    ZX_ASSERT(has_z());
    return *frame_ptr_->z_.data;
  }
  bool has_z() const {
    return max_ordinal_ >= 6 && frame_ptr_->z_.data != nullptr;
  }
  NewerSimpleTable& set_z(::fidl::ObjectView<int64_t> elem) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->z_.data = elem;
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(6));
    return *this;
  }
  NewerSimpleTable& set_z(std::nullptr_t) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->z_.data = nullptr;
    return *this;
  }
  template <typename... Args>
  NewerSimpleTable& set_z(::fidl::AnyAllocator& allocator, Args&&... args) {
    ZX_DEBUG_ASSERT(frame_ptr_ != nullptr);
    frame_ptr_->z_.data =
        ::fidl::ObjectView<int64_t>(allocator, std::forward<Args>(args)...);
    max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>(6));
    return *this;
  }

  NewerSimpleTable() = default;
  explicit NewerSimpleTable(::fidl::AnyAllocator& allocator)
      : frame_ptr_(::fidl::ObjectView<Frame>(allocator)) {}
  // This constructor allows a user controlled allocation (not using a
  // FidlAllocator). It should only be used when performance is key. As soon as
  // the frame is given to the table, it must not be used directly or for
  // another table.
  explicit NewerSimpleTable(::fidl::ObjectView<Frame>&& frame)
      : frame_ptr_(std::move(frame)) {}
  ~NewerSimpleTable() = default;
  NewerSimpleTable(const NewerSimpleTable& other) noexcept = default;
  NewerSimpleTable& operator=(const NewerSimpleTable& other) noexcept = default;
  NewerSimpleTable(NewerSimpleTable&& other) noexcept = default;
  NewerSimpleTable& operator=(NewerSimpleTable&& other) noexcept = default;

  static constexpr const fidl_type_t* Type =
      &fidl_test_table_NewerSimpleTableTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 16;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 120;
  static constexpr bool HasPointer = true;

  void Allocate(::fidl::AnyAllocator& allocator) {
    max_ordinal_ = 0;
    frame_ptr_ = ::fidl::ObjectView<Frame>(allocator);
  }
  void Init(::fidl::ObjectView<Frame>&& frame_ptr) {
    max_ordinal_ = 0;
    frame_ptr_ = std::move(frame_ptr);
  }

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          NewerSimpleTable* value)
        : message_(bytes, byte_size, sizeof(NewerSimpleTable), nullptr, 0, 0) {
      message_.Encode<NewerSimpleTable>(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  // __Fuchsia__
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

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

   private:
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(NewerSimpleTable* value)
        : message_(bytes_.data(), bytes_.size(), 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  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

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

   private:
    ::fidl::internal::InlineMessageBuffer<136> 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<NewerSimpleTable>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<NewerSimpleTable>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

    NewerSimpleTable* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<NewerSimpleTable*>(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(); }
  };

  // Frames are managed automatically by the FidlAllocator class.
  // The only direct usage is when performance is key and a frame needs to be
  // allocated outside a FidlAllocator. Once created, a frame can only be used
  // for one single table.
  class Frame final {
   public:
    Frame() = default;
    // In its intended usage, Frame will be referenced by an ObjectView. If the
    // ObjectView 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<int64_t> x_;
    ::fidl::Envelope<void> reserved_1_;
    ::fidl::Envelope<void> reserved_2_;
    ::fidl::Envelope<void> reserved_3_;
    ::fidl::Envelope<int64_t> y_;
    ::fidl::Envelope<int64_t> z_;

    friend class NewerSimpleTable;
  };

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

extern "C" const fidl_type_t fidl_test_table_EmptyTableTable;

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

  class Frame;

  EmptyTable() = default;
  explicit EmptyTable(::fidl::AnyAllocator& allocator)
      : frame_ptr_(::fidl::ObjectView<Frame>(allocator)) {}
  // This constructor allows a user controlled allocation (not using a
  // FidlAllocator). It should only be used when performance is key. As soon as
  // the frame is given to the table, it must not be used directly or for
  // another table.
  explicit EmptyTable(::fidl::ObjectView<Frame>&& frame)
      : frame_ptr_(std::move(frame)) {}
  ~EmptyTable() = default;
  EmptyTable(const EmptyTable& other) noexcept = default;
  EmptyTable& operator=(const EmptyTable& other) noexcept = default;
  EmptyTable(EmptyTable&& other) noexcept = default;
  EmptyTable& operator=(EmptyTable&& other) noexcept = default;

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

  void Allocate(::fidl::AnyAllocator& allocator) {
    max_ordinal_ = 0;
    frame_ptr_ = ::fidl::ObjectView<Frame>(allocator);
  }
  void Init(::fidl::ObjectView<Frame>&& frame_ptr) {
    max_ordinal_ = 0;
    frame_ptr_ = std::move(frame_ptr);
  }

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size, EmptyTable* value)
        : message_(bytes, byte_size, sizeof(EmptyTable), nullptr, 0, 0) {
      message_.Encode<EmptyTable>(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  // __Fuchsia__
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

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

   private:
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(EmptyTable* value)
        : message_(bytes_.data(), bytes_.size(), 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  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

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

   private:
    ::fidl::internal::InlineMessageBuffer<16> 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<EmptyTable>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<EmptyTable>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

    EmptyTable* PrimaryObject() {
      ZX_DEBUG_ASSERT(ok());
      return reinterpret_cast<EmptyTable*>(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(); }
  };

  // Frames are managed automatically by the FidlAllocator class.
  // The only direct usage is when performance is key and a frame needs to be
  // allocated outside a FidlAllocator. Once created, a frame can only be used
  // for one single table.
  class Frame final {
   public:
    Frame() = default;
    // In its intended usage, Frame will be referenced by an ObjectView. If the
    // ObjectView 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;

    friend class EmptyTable;
  };

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

}  // namespace wire
}  // namespace fidl_test_table
namespace fidl {

template <>
struct IsFidlType<::fidl_test_table::wire::SimpleTable>
    : public std::true_type {};
template <>
struct IsTable<::fidl_test_table::wire::SimpleTable> : public std::true_type {};
static_assert(std::is_standard_layout_v<::fidl_test_table::wire::SimpleTable>);

template <>
struct IsFidlType<::fidl_test_table::wire::ReverseOrdinalTable>
    : public std::true_type {};
template <>
struct IsTable<::fidl_test_table::wire::ReverseOrdinalTable>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::fidl_test_table::wire::ReverseOrdinalTable>);

template <>
struct IsFidlType<::fidl_test_table::wire::OlderSimpleTable>
    : public std::true_type {};
template <>
struct IsTable<::fidl_test_table::wire::OlderSimpleTable>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::fidl_test_table::wire::OlderSimpleTable>);

template <>
struct IsFidlType<::fidl_test_table::wire::NewerSimpleTable>
    : public std::true_type {};
template <>
struct IsTable<::fidl_test_table::wire::NewerSimpleTable>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::fidl_test_table::wire::NewerSimpleTable>);

template <>
struct IsFidlType<::fidl_test_table::wire::EmptyTable> : public std::true_type {
};
template <>
struct IsTable<::fidl_test_table::wire::EmptyTable> : public std::true_type {};
static_assert(std::is_standard_layout_v<::fidl_test_table::wire::EmptyTable>);

}  // namespace fidl
