// 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_vectors {
namespace wire {
struct ExampleUseOfVectors;

extern "C" const fidl_type_t fidl_test_vectors_ExampleUseOfVectorsTable;

struct ExampleUseOfVectors {
  static constexpr const fidl_type_t* Type =
      &fidl_test_vectors_ExampleUseOfVectorsTable;
  static constexpr uint32_t MaxNumHandles = 0;
  static constexpr uint32_t PrimarySize = 32;
  [[maybe_unused]] static constexpr uint32_t MaxOutOfLine = 4294967295;
  static constexpr bool HasPointer = true;

  ::fidl::VectorView<uint8_t> vector_of_uint8 = {};

  ::fidl::VectorView<::fidl::VectorView<bool>> vector_of_vector_of_bool = {};

  class UnownedEncodedMessage final {
   public:
    UnownedEncodedMessage(uint8_t* backing_buffer, uint32_t backing_buffer_size,
                          ExampleUseOfVectors* value)
        : message_(::fidl::OutgoingMessage::ConstructorArgs{
              .iovecs = iovecs_,
              .iovec_capacity = ::fidl::internal::IovecBufferSize,
              .backing_buffer = backing_buffer,
              .backing_buffer_capacity = backing_buffer_size,
          }) {
      if (backing_buffer_size < sizeof(ExampleUseOfVectors)) {
        ::fidl::internal::OutgoingMessageResultSetter::SetResult(
            message_, ZX_ERR_BUFFER_TOO_SMALL, nullptr);
        return;
      }
      message_.Encode<ExampleUseOfVectors>(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::internal::IovecBuffer iovecs_;
    ::fidl::OutgoingMessage message_;
  };

  class OwnedEncodedMessage final {
   public:
    explicit OwnedEncodedMessage(ExampleUseOfVectors* value)
        : message_(backing_buffer_.data(), backing_buffer_.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::BoxedMessageBuffer<ZX_CHANNEL_MAX_MSG_BYTES>
        backing_buffer_;
    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 ExampleUseOfVectors>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<struct ExampleUseOfVectors>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;

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

}  // namespace wire
}  // namespace fidl_test_vectors
namespace fidl {

template <>
struct IsFidlType<::fidl_test_vectors::wire::ExampleUseOfVectors>
    : public std::true_type {};
template <>
struct IsStruct<::fidl_test_vectors::wire::ExampleUseOfVectors>
    : public std::true_type {};
static_assert(
    std::is_standard_layout_v<::fidl_test_vectors::wire::ExampleUseOfVectors>);
static_assert(offsetof(::fidl_test_vectors::wire::ExampleUseOfVectors,
                       vector_of_uint8) == 0);
static_assert(offsetof(::fidl_test_vectors::wire::ExampleUseOfVectors,
                       vector_of_vector_of_bool) == 16);
static_assert(sizeof(::fidl_test_vectors::wire::ExampleUseOfVectors) ==
              ::fidl_test_vectors::wire::ExampleUseOfVectors::PrimarySize);

}  // namespace fidl
