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

#pragma once

#include <lib/fidl/internal.h>
#include <lib/fidl/txn_header.h>
#include <lib/fidl/llcpp/array.h>
#include <lib/fidl/llcpp/coding.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/service_handler_interface.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/fidl/llcpp/sync_call.h>
#include <lib/fidl/llcpp/traits.h>
#include <lib/fidl/llcpp/transaction.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/fit/function.h>
#include <lib/zx/channel.h>
#include <lib/zx/debuglog.h>
#include <lib/zx/job.h>
#include <lib/zx/resource.h>
#include <lib/zx/vmo.h>
#include <zircon/fidl.h>

namespace llcpp {

namespace fuchsia {
namespace boot {

class WriteOnlyLog;
class ReadOnlyLog;
class Items;
class FactoryItems;
class RootResource;
class RootJob;
class RootJobForInspect;
class Arguments;

extern "C" const fidl_type_t v1_fuchsia_boot_WriteOnlyLogGetRequestTable;
extern "C" const fidl_type_t v1_fuchsia_boot_WriteOnlyLogGetResponseTable;

// Protocol for providing the kernel log, writable.
class WriteOnlyLog final {
  WriteOnlyLog() = delete;
 public:
  static constexpr char Name[] = "fuchsia.boot.WriteOnlyLog";

  struct GetResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::debuglog log;

    static constexpr const fidl_type_t* Type = &v1_fuchsia_boot_WriteOnlyLogGetResponseTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
  };
  using GetRequest = ::fidl::AnyZeroArgMessage;


  // Collection of return types of FIDL calls in this interface.
  class ResultOf final {
    ResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  // Collection of return types of FIDL calls in this interface,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  class SyncClient final {
   public:
    explicit SyncClient(::zx::channel channel) : channel_(std::move(channel)) {}
    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::zx::channel& channel() const { return channel_; }

    ::zx::channel* mutable_channel() { return &channel_; }

    // Get write-only handle to the kernel `log`.
    // Allocates 40 bytes of message buffer on the stack. No heap allocation necessary.
    ResultOf::Get Get();

    // Get write-only handle to the kernel `log`.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    UnownedResultOf::Get Get(::fidl::BytePart _response_buffer);

   private:
    ::zx::channel channel_;
  };

  // Methods to make a sync FIDL call directly on an unowned channel, avoiding setting up a client.
  class Call final {
    Call() = delete;
   public:

    // Get write-only handle to the kernel `log`.
    // Allocates 40 bytes of message buffer on the stack. No heap allocation necessary.
    static ResultOf::Get Get(::zx::unowned_channel _client_end);

    // Get write-only handle to the kernel `log`.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    static UnownedResultOf::Get Get(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);

  };

  // Messages are encoded and decoded in-place when these methods are used.
  // Additionally, requests must be already laid-out according to the FIDL wire-format.
  class InPlace final {
    InPlace() = delete;
   public:

    // Get write-only handle to the kernel `log`.
    static ::fidl::DecodeResult<GetResponse> Get(::zx::unowned_channel _client_end, ::fidl::BytePart response_buffer);

  };

  // Pure-virtual interface to be implemented by a server.
  class Interface {
   public:
    Interface() = default;
    virtual ~Interface() = default;
    using _Outer = WriteOnlyLog;
    using _Base = ::fidl::CompleterBase;

    class GetCompleterBase : public _Base {
     public:
      void Reply(::zx::debuglog log);
      void Reply(::fidl::BytePart _buffer, ::zx::debuglog log);
      void Reply(::fidl::DecodedMessage<GetResponse> params);

     protected:
      using ::fidl::CompleterBase::CompleterBase;
    };

    using GetCompleter = ::fidl::Completer<GetCompleterBase>;

    virtual void Get(GetCompleter::Sync _completer) = 0;

  };

  // Attempts to dispatch the incoming message to a handler function in the server implementation.
  // If there is no matching handler, it returns false, leaving the message and transaction intact.
  // In all other cases, it consumes the message and returns true.
  // It is possible to chain multiple TryDispatch functions in this manner.
  static bool TryDispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the interface.
  // If there is no matching handler, it closes all the handles in |msg| and closes the channel with
  // a |ZX_ERR_NOT_SUPPORTED| epitaph, before returning false. The message should then be discarded.
  static bool Dispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of |Interface*|. Only used with |fidl::Bind|
  // to reduce template expansion.
  // Do not call this method manually. Use |Dispatch| instead.
  static bool TypeErasedDispatch(void* impl, fidl_msg_t* msg, ::fidl::Transaction* txn) {
    return Dispatch(static_cast<Interface*>(impl), msg, txn);
  }


  // Helper functions to fill in the transaction header in a |DecodedMessage<TransactionalMessage>|.
  class SetTransactionHeaderFor final {
    SetTransactionHeaderFor() = delete;
   public:
    static void GetRequest(const ::fidl::DecodedMessage<WriteOnlyLog::GetRequest>& _msg);
    static void GetResponse(const ::fidl::DecodedMessage<WriteOnlyLog::GetResponse>& _msg);
  };
};

extern "C" const fidl_type_t v1_fuchsia_boot_ReadOnlyLogGetRequestTable;
extern "C" const fidl_type_t v1_fuchsia_boot_ReadOnlyLogGetResponseTable;

// Protocol for providing the kernel log, readable.
class ReadOnlyLog final {
  ReadOnlyLog() = delete;
 public:
  static constexpr char Name[] = "fuchsia.boot.ReadOnlyLog";

  struct GetResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::debuglog log;

    static constexpr const fidl_type_t* Type = &v1_fuchsia_boot_ReadOnlyLogGetResponseTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
  };
  using GetRequest = ::fidl::AnyZeroArgMessage;


  // Collection of return types of FIDL calls in this interface.
  class ResultOf final {
    ResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  // Collection of return types of FIDL calls in this interface,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  class SyncClient final {
   public:
    explicit SyncClient(::zx::channel channel) : channel_(std::move(channel)) {}
    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::zx::channel& channel() const { return channel_; }

    ::zx::channel* mutable_channel() { return &channel_; }

    // Get read-only handle to the kernel `log`.
    // Allocates 40 bytes of message buffer on the stack. No heap allocation necessary.
    ResultOf::Get Get();

    // Get read-only handle to the kernel `log`.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    UnownedResultOf::Get Get(::fidl::BytePart _response_buffer);

   private:
    ::zx::channel channel_;
  };

  // Methods to make a sync FIDL call directly on an unowned channel, avoiding setting up a client.
  class Call final {
    Call() = delete;
   public:

    // Get read-only handle to the kernel `log`.
    // Allocates 40 bytes of message buffer on the stack. No heap allocation necessary.
    static ResultOf::Get Get(::zx::unowned_channel _client_end);

    // Get read-only handle to the kernel `log`.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    static UnownedResultOf::Get Get(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);

  };

  // Messages are encoded and decoded in-place when these methods are used.
  // Additionally, requests must be already laid-out according to the FIDL wire-format.
  class InPlace final {
    InPlace() = delete;
   public:

    // Get read-only handle to the kernel `log`.
    static ::fidl::DecodeResult<GetResponse> Get(::zx::unowned_channel _client_end, ::fidl::BytePart response_buffer);

  };

  // Pure-virtual interface to be implemented by a server.
  class Interface {
   public:
    Interface() = default;
    virtual ~Interface() = default;
    using _Outer = ReadOnlyLog;
    using _Base = ::fidl::CompleterBase;

    class GetCompleterBase : public _Base {
     public:
      void Reply(::zx::debuglog log);
      void Reply(::fidl::BytePart _buffer, ::zx::debuglog log);
      void Reply(::fidl::DecodedMessage<GetResponse> params);

     protected:
      using ::fidl::CompleterBase::CompleterBase;
    };

    using GetCompleter = ::fidl::Completer<GetCompleterBase>;

    virtual void Get(GetCompleter::Sync _completer) = 0;

  };

  // Attempts to dispatch the incoming message to a handler function in the server implementation.
  // If there is no matching handler, it returns false, leaving the message and transaction intact.
  // In all other cases, it consumes the message and returns true.
  // It is possible to chain multiple TryDispatch functions in this manner.
  static bool TryDispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the interface.
  // If there is no matching handler, it closes all the handles in |msg| and closes the channel with
  // a |ZX_ERR_NOT_SUPPORTED| epitaph, before returning false. The message should then be discarded.
  static bool Dispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of |Interface*|. Only used with |fidl::Bind|
  // to reduce template expansion.
  // Do not call this method manually. Use |Dispatch| instead.
  static bool TypeErasedDispatch(void* impl, fidl_msg_t* msg, ::fidl::Transaction* txn) {
    return Dispatch(static_cast<Interface*>(impl), msg, txn);
  }


  // Helper functions to fill in the transaction header in a |DecodedMessage<TransactionalMessage>|.
  class SetTransactionHeaderFor final {
    SetTransactionHeaderFor() = delete;
   public:
    static void GetRequest(const ::fidl::DecodedMessage<ReadOnlyLog::GetRequest>& _msg);
    static void GetResponse(const ::fidl::DecodedMessage<ReadOnlyLog::GetResponse>& _msg);
  };
};

extern "C" const fidl_type_t v1_fuchsia_boot_ItemsGetRequestTable;
extern "C" const fidl_type_t v1_fuchsia_boot_ItemsGetResponseTable;

// Protocol for retrieving boot item payloads.
class Items final {
  Items() = delete;
 public:
  static constexpr char Name[] = "fuchsia.boot.Items";

  struct GetResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::vmo payload;
    uint32_t length;

    static constexpr const fidl_type_t* Type = &v1_fuchsia_boot_ItemsGetResponseTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
  };
  struct GetRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    uint32_t type;
    uint32_t extra;

    static constexpr const fidl_type_t* Type = &v1_fuchsia_boot_ItemsGetRequestTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr uint32_t AltPrimarySize = 24;
    static constexpr uint32_t AltMaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kRequest;
    using ResponseType = GetResponse;
  };


  // Collection of return types of FIDL calls in this interface.
  class ResultOf final {
    ResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end, uint32_t type, uint32_t extra);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  // Collection of return types of FIDL calls in this interface,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end, ::fidl::BytePart _request_buffer, uint32_t type, uint32_t extra, ::fidl::BytePart _response_buffer);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  class SyncClient final {
   public:
    explicit SyncClient(::zx::channel channel) : channel_(std::move(channel)) {}
    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::zx::channel& channel() const { return channel_; }

    ::zx::channel* mutable_channel() { return &channel_; }

    // Get a `payload` for a boot item of `type` and `extra`.
    // NOTE: We return the `length` of the item, as VMOs must be page-aligned.
    //
    // For a list of `type`s, refer to <zircon/boot/image.h>.
    // For a list of `extra`s, refer to <zircon/boot/driver-config.h>.
    // Allocates 48 bytes of message buffer on the stack. No heap allocation necessary.
    ResultOf::Get Get(uint32_t type, uint32_t extra);

    // Get a `payload` for a boot item of `type` and `extra`.
    // NOTE: We return the `length` of the item, as VMOs must be page-aligned.
    //
    // For a list of `type`s, refer to <zircon/boot/image.h>.
    // For a list of `extra`s, refer to <zircon/boot/driver-config.h>.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    UnownedResultOf::Get Get(::fidl::BytePart _request_buffer, uint32_t type, uint32_t extra, ::fidl::BytePart _response_buffer);

   private:
    ::zx::channel channel_;
  };

  // Methods to make a sync FIDL call directly on an unowned channel, avoiding setting up a client.
  class Call final {
    Call() = delete;
   public:

    // Get a `payload` for a boot item of `type` and `extra`.
    // NOTE: We return the `length` of the item, as VMOs must be page-aligned.
    //
    // For a list of `type`s, refer to <zircon/boot/image.h>.
    // For a list of `extra`s, refer to <zircon/boot/driver-config.h>.
    // Allocates 48 bytes of message buffer on the stack. No heap allocation necessary.
    static ResultOf::Get Get(::zx::unowned_channel _client_end, uint32_t type, uint32_t extra);

    // Get a `payload` for a boot item of `type` and `extra`.
    // NOTE: We return the `length` of the item, as VMOs must be page-aligned.
    //
    // For a list of `type`s, refer to <zircon/boot/image.h>.
    // For a list of `extra`s, refer to <zircon/boot/driver-config.h>.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    static UnownedResultOf::Get Get(::zx::unowned_channel _client_end, ::fidl::BytePart _request_buffer, uint32_t type, uint32_t extra, ::fidl::BytePart _response_buffer);

  };

  // Messages are encoded and decoded in-place when these methods are used.
  // Additionally, requests must be already laid-out according to the FIDL wire-format.
  class InPlace final {
    InPlace() = delete;
   public:

    // Get a `payload` for a boot item of `type` and `extra`.
    // NOTE: We return the `length` of the item, as VMOs must be page-aligned.
    //
    // For a list of `type`s, refer to <zircon/boot/image.h>.
    // For a list of `extra`s, refer to <zircon/boot/driver-config.h>.
    static ::fidl::DecodeResult<GetResponse> Get(::zx::unowned_channel _client_end, ::fidl::DecodedMessage<GetRequest> params, ::fidl::BytePart response_buffer);

  };

  // Pure-virtual interface to be implemented by a server.
  class Interface {
   public:
    Interface() = default;
    virtual ~Interface() = default;
    using _Outer = Items;
    using _Base = ::fidl::CompleterBase;

    class GetCompleterBase : public _Base {
     public:
      void Reply(::zx::vmo payload, uint32_t length);
      void Reply(::fidl::BytePart _buffer, ::zx::vmo payload, uint32_t length);
      void Reply(::fidl::DecodedMessage<GetResponse> params);

     protected:
      using ::fidl::CompleterBase::CompleterBase;
    };

    using GetCompleter = ::fidl::Completer<GetCompleterBase>;

    virtual void Get(uint32_t type, uint32_t extra, GetCompleter::Sync _completer) = 0;

  };

  // Attempts to dispatch the incoming message to a handler function in the server implementation.
  // If there is no matching handler, it returns false, leaving the message and transaction intact.
  // In all other cases, it consumes the message and returns true.
  // It is possible to chain multiple TryDispatch functions in this manner.
  static bool TryDispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the interface.
  // If there is no matching handler, it closes all the handles in |msg| and closes the channel with
  // a |ZX_ERR_NOT_SUPPORTED| epitaph, before returning false. The message should then be discarded.
  static bool Dispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of |Interface*|. Only used with |fidl::Bind|
  // to reduce template expansion.
  // Do not call this method manually. Use |Dispatch| instead.
  static bool TypeErasedDispatch(void* impl, fidl_msg_t* msg, ::fidl::Transaction* txn) {
    return Dispatch(static_cast<Interface*>(impl), msg, txn);
  }


  // Helper functions to fill in the transaction header in a |DecodedMessage<TransactionalMessage>|.
  class SetTransactionHeaderFor final {
    SetTransactionHeaderFor() = delete;
   public:
    static void GetRequest(const ::fidl::DecodedMessage<Items::GetRequest>& _msg);
    static void GetResponse(const ::fidl::DecodedMessage<Items::GetResponse>& _msg);
  };
};

extern "C" const fidl_type_t v1_fuchsia_boot_FactoryItemsGetRequestTable;
extern "C" const fidl_type_t v1_fuchsia_boot_FactoryItemsGetResponseTable;

// Protocol for retrieving factory boot item payloads.
class FactoryItems final {
  FactoryItems() = delete;
 public:
  static constexpr char Name[] = "fuchsia.boot.FactoryItems";

  struct GetResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::vmo payload;
    uint32_t length;

    static constexpr const fidl_type_t* Type = &v1_fuchsia_boot_FactoryItemsGetResponseTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
  };
  struct GetRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    uint32_t extra;

    static constexpr const fidl_type_t* Type = &v1_fuchsia_boot_FactoryItemsGetRequestTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr uint32_t AltPrimarySize = 24;
    static constexpr uint32_t AltMaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kRequest;
    using ResponseType = GetResponse;
  };


  // Collection of return types of FIDL calls in this interface.
  class ResultOf final {
    ResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end, uint32_t extra);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  // Collection of return types of FIDL calls in this interface,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end, ::fidl::BytePart _request_buffer, uint32_t extra, ::fidl::BytePart _response_buffer);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  class SyncClient final {
   public:
    explicit SyncClient(::zx::channel channel) : channel_(std::move(channel)) {}
    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::zx::channel& channel() const { return channel_; }

    ::zx::channel* mutable_channel() { return &channel_; }

    // Gets a `payload` for a `ZBI_TYPE_STORAGE_BOOTFS_FACTORY` boot item with
    // extra field set to `extra`.
    //
    // NOTE: We return the `length` of the item, as VMOs must be page-aligned.
    // Allocates 48 bytes of message buffer on the stack. No heap allocation necessary.
    ResultOf::Get Get(uint32_t extra);

    // Gets a `payload` for a `ZBI_TYPE_STORAGE_BOOTFS_FACTORY` boot item with
    // extra field set to `extra`.
    //
    // NOTE: We return the `length` of the item, as VMOs must be page-aligned.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    UnownedResultOf::Get Get(::fidl::BytePart _request_buffer, uint32_t extra, ::fidl::BytePart _response_buffer);

   private:
    ::zx::channel channel_;
  };

  // Methods to make a sync FIDL call directly on an unowned channel, avoiding setting up a client.
  class Call final {
    Call() = delete;
   public:

    // Gets a `payload` for a `ZBI_TYPE_STORAGE_BOOTFS_FACTORY` boot item with
    // extra field set to `extra`.
    //
    // NOTE: We return the `length` of the item, as VMOs must be page-aligned.
    // Allocates 48 bytes of message buffer on the stack. No heap allocation necessary.
    static ResultOf::Get Get(::zx::unowned_channel _client_end, uint32_t extra);

    // Gets a `payload` for a `ZBI_TYPE_STORAGE_BOOTFS_FACTORY` boot item with
    // extra field set to `extra`.
    //
    // NOTE: We return the `length` of the item, as VMOs must be page-aligned.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    static UnownedResultOf::Get Get(::zx::unowned_channel _client_end, ::fidl::BytePart _request_buffer, uint32_t extra, ::fidl::BytePart _response_buffer);

  };

  // Messages are encoded and decoded in-place when these methods are used.
  // Additionally, requests must be already laid-out according to the FIDL wire-format.
  class InPlace final {
    InPlace() = delete;
   public:

    // Gets a `payload` for a `ZBI_TYPE_STORAGE_BOOTFS_FACTORY` boot item with
    // extra field set to `extra`.
    //
    // NOTE: We return the `length` of the item, as VMOs must be page-aligned.
    static ::fidl::DecodeResult<GetResponse> Get(::zx::unowned_channel _client_end, ::fidl::DecodedMessage<GetRequest> params, ::fidl::BytePart response_buffer);

  };

  // Pure-virtual interface to be implemented by a server.
  class Interface {
   public:
    Interface() = default;
    virtual ~Interface() = default;
    using _Outer = FactoryItems;
    using _Base = ::fidl::CompleterBase;

    class GetCompleterBase : public _Base {
     public:
      void Reply(::zx::vmo payload, uint32_t length);
      void Reply(::fidl::BytePart _buffer, ::zx::vmo payload, uint32_t length);
      void Reply(::fidl::DecodedMessage<GetResponse> params);

     protected:
      using ::fidl::CompleterBase::CompleterBase;
    };

    using GetCompleter = ::fidl::Completer<GetCompleterBase>;

    virtual void Get(uint32_t extra, GetCompleter::Sync _completer) = 0;

  };

  // Attempts to dispatch the incoming message to a handler function in the server implementation.
  // If there is no matching handler, it returns false, leaving the message and transaction intact.
  // In all other cases, it consumes the message and returns true.
  // It is possible to chain multiple TryDispatch functions in this manner.
  static bool TryDispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the interface.
  // If there is no matching handler, it closes all the handles in |msg| and closes the channel with
  // a |ZX_ERR_NOT_SUPPORTED| epitaph, before returning false. The message should then be discarded.
  static bool Dispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of |Interface*|. Only used with |fidl::Bind|
  // to reduce template expansion.
  // Do not call this method manually. Use |Dispatch| instead.
  static bool TypeErasedDispatch(void* impl, fidl_msg_t* msg, ::fidl::Transaction* txn) {
    return Dispatch(static_cast<Interface*>(impl), msg, txn);
  }


  // Helper functions to fill in the transaction header in a |DecodedMessage<TransactionalMessage>|.
  class SetTransactionHeaderFor final {
    SetTransactionHeaderFor() = delete;
   public:
    static void GetRequest(const ::fidl::DecodedMessage<FactoryItems::GetRequest>& _msg);
    static void GetResponse(const ::fidl::DecodedMessage<FactoryItems::GetResponse>& _msg);
  };
};

extern "C" const fidl_type_t v1_fuchsia_boot_RootResourceGetRequestTable;
extern "C" const fidl_type_t v1_fuchsia_boot_RootResourceGetResponseTable;

// Protocol for providing the root resource.
class RootResource final {
  RootResource() = delete;
 public:
  static constexpr char Name[] = "fuchsia.boot.RootResource";

  struct GetResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::resource resource;

    static constexpr const fidl_type_t* Type = &v1_fuchsia_boot_RootResourceGetResponseTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
  };
  using GetRequest = ::fidl::AnyZeroArgMessage;


  // Collection of return types of FIDL calls in this interface.
  class ResultOf final {
    ResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  // Collection of return types of FIDL calls in this interface,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  class SyncClient final {
   public:
    explicit SyncClient(::zx::channel channel) : channel_(std::move(channel)) {}
    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::zx::channel& channel() const { return channel_; }

    ::zx::channel* mutable_channel() { return &channel_; }

    // Get the root |resource|.
    // Allocates 40 bytes of message buffer on the stack. No heap allocation necessary.
    ResultOf::Get Get();

    // Get the root |resource|.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    UnownedResultOf::Get Get(::fidl::BytePart _response_buffer);

   private:
    ::zx::channel channel_;
  };

  // Methods to make a sync FIDL call directly on an unowned channel, avoiding setting up a client.
  class Call final {
    Call() = delete;
   public:

    // Get the root |resource|.
    // Allocates 40 bytes of message buffer on the stack. No heap allocation necessary.
    static ResultOf::Get Get(::zx::unowned_channel _client_end);

    // Get the root |resource|.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    static UnownedResultOf::Get Get(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);

  };

  // Messages are encoded and decoded in-place when these methods are used.
  // Additionally, requests must be already laid-out according to the FIDL wire-format.
  class InPlace final {
    InPlace() = delete;
   public:

    // Get the root |resource|.
    static ::fidl::DecodeResult<GetResponse> Get(::zx::unowned_channel _client_end, ::fidl::BytePart response_buffer);

  };

  // Pure-virtual interface to be implemented by a server.
  class Interface {
   public:
    Interface() = default;
    virtual ~Interface() = default;
    using _Outer = RootResource;
    using _Base = ::fidl::CompleterBase;

    class GetCompleterBase : public _Base {
     public:
      void Reply(::zx::resource resource);
      void Reply(::fidl::BytePart _buffer, ::zx::resource resource);
      void Reply(::fidl::DecodedMessage<GetResponse> params);

     protected:
      using ::fidl::CompleterBase::CompleterBase;
    };

    using GetCompleter = ::fidl::Completer<GetCompleterBase>;

    virtual void Get(GetCompleter::Sync _completer) = 0;

  };

  // Attempts to dispatch the incoming message to a handler function in the server implementation.
  // If there is no matching handler, it returns false, leaving the message and transaction intact.
  // In all other cases, it consumes the message and returns true.
  // It is possible to chain multiple TryDispatch functions in this manner.
  static bool TryDispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the interface.
  // If there is no matching handler, it closes all the handles in |msg| and closes the channel with
  // a |ZX_ERR_NOT_SUPPORTED| epitaph, before returning false. The message should then be discarded.
  static bool Dispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of |Interface*|. Only used with |fidl::Bind|
  // to reduce template expansion.
  // Do not call this method manually. Use |Dispatch| instead.
  static bool TypeErasedDispatch(void* impl, fidl_msg_t* msg, ::fidl::Transaction* txn) {
    return Dispatch(static_cast<Interface*>(impl), msg, txn);
  }


  // Helper functions to fill in the transaction header in a |DecodedMessage<TransactionalMessage>|.
  class SetTransactionHeaderFor final {
    SetTransactionHeaderFor() = delete;
   public:
    static void GetRequest(const ::fidl::DecodedMessage<RootResource::GetRequest>& _msg);
    static void GetResponse(const ::fidl::DecodedMessage<RootResource::GetResponse>& _msg);
  };
};

extern "C" const fidl_type_t v1_fuchsia_boot_RootJobGetRequestTable;
extern "C" const fidl_type_t v1_fuchsia_boot_RootJobGetResponseTable;

// Protocol for providing the root job.
//
// TODO(ZX-4072): Do not use this without first consulting the Zircon team.
class RootJob final {
  RootJob() = delete;
 public:
  static constexpr char Name[] = "fuchsia.boot.RootJob";

  struct GetResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::job job;

    static constexpr const fidl_type_t* Type = &v1_fuchsia_boot_RootJobGetResponseTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
  };
  using GetRequest = ::fidl::AnyZeroArgMessage;


  // Collection of return types of FIDL calls in this interface.
  class ResultOf final {
    ResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  // Collection of return types of FIDL calls in this interface,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  class SyncClient final {
   public:
    explicit SyncClient(::zx::channel channel) : channel_(std::move(channel)) {}
    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::zx::channel& channel() const { return channel_; }

    ::zx::channel* mutable_channel() { return &channel_; }

    // Get the root `job`.
    // Allocates 40 bytes of message buffer on the stack. No heap allocation necessary.
    ResultOf::Get Get();

    // Get the root `job`.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    UnownedResultOf::Get Get(::fidl::BytePart _response_buffer);

   private:
    ::zx::channel channel_;
  };

  // Methods to make a sync FIDL call directly on an unowned channel, avoiding setting up a client.
  class Call final {
    Call() = delete;
   public:

    // Get the root `job`.
    // Allocates 40 bytes of message buffer on the stack. No heap allocation necessary.
    static ResultOf::Get Get(::zx::unowned_channel _client_end);

    // Get the root `job`.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    static UnownedResultOf::Get Get(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);

  };

  // Messages are encoded and decoded in-place when these methods are used.
  // Additionally, requests must be already laid-out according to the FIDL wire-format.
  class InPlace final {
    InPlace() = delete;
   public:

    // Get the root `job`.
    static ::fidl::DecodeResult<GetResponse> Get(::zx::unowned_channel _client_end, ::fidl::BytePart response_buffer);

  };

  // Pure-virtual interface to be implemented by a server.
  class Interface {
   public:
    Interface() = default;
    virtual ~Interface() = default;
    using _Outer = RootJob;
    using _Base = ::fidl::CompleterBase;

    class GetCompleterBase : public _Base {
     public:
      void Reply(::zx::job job);
      void Reply(::fidl::BytePart _buffer, ::zx::job job);
      void Reply(::fidl::DecodedMessage<GetResponse> params);

     protected:
      using ::fidl::CompleterBase::CompleterBase;
    };

    using GetCompleter = ::fidl::Completer<GetCompleterBase>;

    virtual void Get(GetCompleter::Sync _completer) = 0;

  };

  // Attempts to dispatch the incoming message to a handler function in the server implementation.
  // If there is no matching handler, it returns false, leaving the message and transaction intact.
  // In all other cases, it consumes the message and returns true.
  // It is possible to chain multiple TryDispatch functions in this manner.
  static bool TryDispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the interface.
  // If there is no matching handler, it closes all the handles in |msg| and closes the channel with
  // a |ZX_ERR_NOT_SUPPORTED| epitaph, before returning false. The message should then be discarded.
  static bool Dispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of |Interface*|. Only used with |fidl::Bind|
  // to reduce template expansion.
  // Do not call this method manually. Use |Dispatch| instead.
  static bool TypeErasedDispatch(void* impl, fidl_msg_t* msg, ::fidl::Transaction* txn) {
    return Dispatch(static_cast<Interface*>(impl), msg, txn);
  }


  // Helper functions to fill in the transaction header in a |DecodedMessage<TransactionalMessage>|.
  class SetTransactionHeaderFor final {
    SetTransactionHeaderFor() = delete;
   public:
    static void GetRequest(const ::fidl::DecodedMessage<RootJob::GetRequest>& _msg);
    static void GetResponse(const ::fidl::DecodedMessage<RootJob::GetResponse>& _msg);
  };
};

extern "C" const fidl_type_t v1_fuchsia_boot_RootJobForInspectGetRequestTable;
extern "C" const fidl_type_t v1_fuchsia_boot_RootJobForInspectGetResponseTable;

// Protocol for providing the root job with restricted rights, specifically:
// INSPECT | ENUMERATE | DUPLICATE | TRANSFER
class RootJobForInspect final {
  RootJobForInspect() = delete;
 public:
  static constexpr char Name[] = "fuchsia.boot.RootJobForInspect";

  struct GetResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::job job;

    static constexpr const fidl_type_t* Type = &v1_fuchsia_boot_RootJobForInspectGetResponseTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 24;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
  };
  using GetRequest = ::fidl::AnyZeroArgMessage;


  // Collection of return types of FIDL calls in this interface.
  class ResultOf final {
    ResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  // Collection of return types of FIDL calls in this interface,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  class SyncClient final {
   public:
    explicit SyncClient(::zx::channel channel) : channel_(std::move(channel)) {}
    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::zx::channel& channel() const { return channel_; }

    ::zx::channel* mutable_channel() { return &channel_; }

    // Get the root `job`.
    // Allocates 40 bytes of message buffer on the stack. No heap allocation necessary.
    ResultOf::Get Get();

    // Get the root `job`.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    UnownedResultOf::Get Get(::fidl::BytePart _response_buffer);

   private:
    ::zx::channel channel_;
  };

  // Methods to make a sync FIDL call directly on an unowned channel, avoiding setting up a client.
  class Call final {
    Call() = delete;
   public:

    // Get the root `job`.
    // Allocates 40 bytes of message buffer on the stack. No heap allocation necessary.
    static ResultOf::Get Get(::zx::unowned_channel _client_end);

    // Get the root `job`.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    static UnownedResultOf::Get Get(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);

  };

  // Messages are encoded and decoded in-place when these methods are used.
  // Additionally, requests must be already laid-out according to the FIDL wire-format.
  class InPlace final {
    InPlace() = delete;
   public:

    // Get the root `job`.
    static ::fidl::DecodeResult<GetResponse> Get(::zx::unowned_channel _client_end, ::fidl::BytePart response_buffer);

  };

  // Pure-virtual interface to be implemented by a server.
  class Interface {
   public:
    Interface() = default;
    virtual ~Interface() = default;
    using _Outer = RootJobForInspect;
    using _Base = ::fidl::CompleterBase;

    class GetCompleterBase : public _Base {
     public:
      void Reply(::zx::job job);
      void Reply(::fidl::BytePart _buffer, ::zx::job job);
      void Reply(::fidl::DecodedMessage<GetResponse> params);

     protected:
      using ::fidl::CompleterBase::CompleterBase;
    };

    using GetCompleter = ::fidl::Completer<GetCompleterBase>;

    virtual void Get(GetCompleter::Sync _completer) = 0;

  };

  // Attempts to dispatch the incoming message to a handler function in the server implementation.
  // If there is no matching handler, it returns false, leaving the message and transaction intact.
  // In all other cases, it consumes the message and returns true.
  // It is possible to chain multiple TryDispatch functions in this manner.
  static bool TryDispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the interface.
  // If there is no matching handler, it closes all the handles in |msg| and closes the channel with
  // a |ZX_ERR_NOT_SUPPORTED| epitaph, before returning false. The message should then be discarded.
  static bool Dispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of |Interface*|. Only used with |fidl::Bind|
  // to reduce template expansion.
  // Do not call this method manually. Use |Dispatch| instead.
  static bool TypeErasedDispatch(void* impl, fidl_msg_t* msg, ::fidl::Transaction* txn) {
    return Dispatch(static_cast<Interface*>(impl), msg, txn);
  }


  // Helper functions to fill in the transaction header in a |DecodedMessage<TransactionalMessage>|.
  class SetTransactionHeaderFor final {
    SetTransactionHeaderFor() = delete;
   public:
    static void GetRequest(const ::fidl::DecodedMessage<RootJobForInspect::GetRequest>& _msg);
    static void GetResponse(const ::fidl::DecodedMessage<RootJobForInspect::GetResponse>& _msg);
  };
};

extern "C" const fidl_type_t v1_fuchsia_boot_ArgumentsGetRequestTable;
extern "C" const fidl_type_t v1_fuchsia_boot_ArgumentsGetResponseTable;

// Protocol for retrieving boot arguments.
class Arguments final {
  Arguments() = delete;
 public:
  static constexpr char Name[] = "fuchsia.boot.Arguments";

  struct GetResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::vmo vmo;
    uint64_t size;

    static constexpr const fidl_type_t* Type = &v1_fuchsia_boot_ArgumentsGetResponseTable;
    static constexpr uint32_t MaxNumHandles = 1;
    static constexpr uint32_t PrimarySize = 32;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr bool ContainsUnion = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
  };
  using GetRequest = ::fidl::AnyZeroArgMessage;


  // Collection of return types of FIDL calls in this interface.
  class ResultOf final {
    ResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  // Collection of return types of FIDL calls in this interface,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;
   private:
    template <typename ResponseType>
    class Get_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
     public:
      Get_Impl(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);
      ~Get_Impl() = default;
      Get_Impl(Get_Impl&& other) = default;
      Get_Impl& operator=(Get_Impl&& other) = default;
      using Super::status;
      using Super::error;
      using Super::ok;
      using Super::Unwrap;
      using Super::value;
      using Super::operator->;
      using Super::operator*;
    };

   public:
    using Get = Get_Impl<GetResponse>;
  };

  class SyncClient final {
   public:
    explicit SyncClient(::zx::channel channel) : channel_(std::move(channel)) {}
    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::zx::channel& channel() const { return channel_; }

    ::zx::channel* mutable_channel() { return &channel_; }

    // Get a `vmo` containing boot arguments, along with the `size` of the boot
    // arguments contained within.
    // Allocates 48 bytes of message buffer on the stack. No heap allocation necessary.
    ResultOf::Get Get();

    // Get a `vmo` containing boot arguments, along with the `size` of the boot
    // arguments contained within.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    UnownedResultOf::Get Get(::fidl::BytePart _response_buffer);

   private:
    ::zx::channel channel_;
  };

  // Methods to make a sync FIDL call directly on an unowned channel, avoiding setting up a client.
  class Call final {
    Call() = delete;
   public:

    // Get a `vmo` containing boot arguments, along with the `size` of the boot
    // arguments contained within.
    // Allocates 48 bytes of message buffer on the stack. No heap allocation necessary.
    static ResultOf::Get Get(::zx::unowned_channel _client_end);

    // Get a `vmo` containing boot arguments, along with the `size` of the boot
    // arguments contained within.
    // Caller provides the backing storage for FIDL message via request and response buffers.
    static UnownedResultOf::Get Get(::zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);

  };

  // Messages are encoded and decoded in-place when these methods are used.
  // Additionally, requests must be already laid-out according to the FIDL wire-format.
  class InPlace final {
    InPlace() = delete;
   public:

    // Get a `vmo` containing boot arguments, along with the `size` of the boot
    // arguments contained within.
    static ::fidl::DecodeResult<GetResponse> Get(::zx::unowned_channel _client_end, ::fidl::BytePart response_buffer);

  };

  // Pure-virtual interface to be implemented by a server.
  class Interface {
   public:
    Interface() = default;
    virtual ~Interface() = default;
    using _Outer = Arguments;
    using _Base = ::fidl::CompleterBase;

    class GetCompleterBase : public _Base {
     public:
      void Reply(::zx::vmo vmo, uint64_t size);
      void Reply(::fidl::BytePart _buffer, ::zx::vmo vmo, uint64_t size);
      void Reply(::fidl::DecodedMessage<GetResponse> params);

     protected:
      using ::fidl::CompleterBase::CompleterBase;
    };

    using GetCompleter = ::fidl::Completer<GetCompleterBase>;

    virtual void Get(GetCompleter::Sync _completer) = 0;

  };

  // Attempts to dispatch the incoming message to a handler function in the server implementation.
  // If there is no matching handler, it returns false, leaving the message and transaction intact.
  // In all other cases, it consumes the message and returns true.
  // It is possible to chain multiple TryDispatch functions in this manner.
  static bool TryDispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the interface.
  // If there is no matching handler, it closes all the handles in |msg| and closes the channel with
  // a |ZX_ERR_NOT_SUPPORTED| epitaph, before returning false. The message should then be discarded.
  static bool Dispatch(Interface* impl, fidl_msg_t* msg, ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of |Interface*|. Only used with |fidl::Bind|
  // to reduce template expansion.
  // Do not call this method manually. Use |Dispatch| instead.
  static bool TypeErasedDispatch(void* impl, fidl_msg_t* msg, ::fidl::Transaction* txn) {
    return Dispatch(static_cast<Interface*>(impl), msg, txn);
  }


  // Helper functions to fill in the transaction header in a |DecodedMessage<TransactionalMessage>|.
  class SetTransactionHeaderFor final {
    SetTransactionHeaderFor() = delete;
   public:
    static void GetRequest(const ::fidl::DecodedMessage<Arguments::GetRequest>& _msg);
    static void GetResponse(const ::fidl::DecodedMessage<Arguments::GetResponse>& _msg);
  };
};

}  // namespace boot
}  // namespace fuchsia
}  // namespace llcpp

namespace fidl {

template <>
struct IsFidlType<::llcpp::fuchsia::boot::WriteOnlyLog::GetResponse> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fuchsia::boot::WriteOnlyLog::GetResponse> : public std::true_type {};
static_assert(sizeof(::llcpp::fuchsia::boot::WriteOnlyLog::GetResponse)
    == ::llcpp::fuchsia::boot::WriteOnlyLog::GetResponse::PrimarySize);
static_assert(offsetof(::llcpp::fuchsia::boot::WriteOnlyLog::GetResponse, log) == 16);

template <>
struct IsFidlType<::llcpp::fuchsia::boot::ReadOnlyLog::GetResponse> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fuchsia::boot::ReadOnlyLog::GetResponse> : public std::true_type {};
static_assert(sizeof(::llcpp::fuchsia::boot::ReadOnlyLog::GetResponse)
    == ::llcpp::fuchsia::boot::ReadOnlyLog::GetResponse::PrimarySize);
static_assert(offsetof(::llcpp::fuchsia::boot::ReadOnlyLog::GetResponse, log) == 16);

template <>
struct IsFidlType<::llcpp::fuchsia::boot::Items::GetRequest> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fuchsia::boot::Items::GetRequest> : public std::true_type {};
static_assert(sizeof(::llcpp::fuchsia::boot::Items::GetRequest)
    == ::llcpp::fuchsia::boot::Items::GetRequest::PrimarySize);
static_assert(offsetof(::llcpp::fuchsia::boot::Items::GetRequest, type) == 16);
static_assert(offsetof(::llcpp::fuchsia::boot::Items::GetRequest, extra) == 20);

template <>
struct IsFidlType<::llcpp::fuchsia::boot::Items::GetResponse> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fuchsia::boot::Items::GetResponse> : public std::true_type {};
static_assert(sizeof(::llcpp::fuchsia::boot::Items::GetResponse)
    == ::llcpp::fuchsia::boot::Items::GetResponse::PrimarySize);
static_assert(offsetof(::llcpp::fuchsia::boot::Items::GetResponse, payload) == 16);
static_assert(offsetof(::llcpp::fuchsia::boot::Items::GetResponse, length) == 20);

template <>
struct IsFidlType<::llcpp::fuchsia::boot::FactoryItems::GetRequest> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fuchsia::boot::FactoryItems::GetRequest> : public std::true_type {};
static_assert(sizeof(::llcpp::fuchsia::boot::FactoryItems::GetRequest)
    == ::llcpp::fuchsia::boot::FactoryItems::GetRequest::PrimarySize);
static_assert(offsetof(::llcpp::fuchsia::boot::FactoryItems::GetRequest, extra) == 16);

template <>
struct IsFidlType<::llcpp::fuchsia::boot::FactoryItems::GetResponse> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fuchsia::boot::FactoryItems::GetResponse> : public std::true_type {};
static_assert(sizeof(::llcpp::fuchsia::boot::FactoryItems::GetResponse)
    == ::llcpp::fuchsia::boot::FactoryItems::GetResponse::PrimarySize);
static_assert(offsetof(::llcpp::fuchsia::boot::FactoryItems::GetResponse, payload) == 16);
static_assert(offsetof(::llcpp::fuchsia::boot::FactoryItems::GetResponse, length) == 20);

template <>
struct IsFidlType<::llcpp::fuchsia::boot::RootResource::GetResponse> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fuchsia::boot::RootResource::GetResponse> : public std::true_type {};
static_assert(sizeof(::llcpp::fuchsia::boot::RootResource::GetResponse)
    == ::llcpp::fuchsia::boot::RootResource::GetResponse::PrimarySize);
static_assert(offsetof(::llcpp::fuchsia::boot::RootResource::GetResponse, resource) == 16);

template <>
struct IsFidlType<::llcpp::fuchsia::boot::RootJob::GetResponse> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fuchsia::boot::RootJob::GetResponse> : public std::true_type {};
static_assert(sizeof(::llcpp::fuchsia::boot::RootJob::GetResponse)
    == ::llcpp::fuchsia::boot::RootJob::GetResponse::PrimarySize);
static_assert(offsetof(::llcpp::fuchsia::boot::RootJob::GetResponse, job) == 16);

template <>
struct IsFidlType<::llcpp::fuchsia::boot::RootJobForInspect::GetResponse> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fuchsia::boot::RootJobForInspect::GetResponse> : public std::true_type {};
static_assert(sizeof(::llcpp::fuchsia::boot::RootJobForInspect::GetResponse)
    == ::llcpp::fuchsia::boot::RootJobForInspect::GetResponse::PrimarySize);
static_assert(offsetof(::llcpp::fuchsia::boot::RootJobForInspect::GetResponse, job) == 16);

template <>
struct IsFidlType<::llcpp::fuchsia::boot::Arguments::GetResponse> : public std::true_type {};
template <>
struct IsFidlMessage<::llcpp::fuchsia::boot::Arguments::GetResponse> : public std::true_type {};
static_assert(sizeof(::llcpp::fuchsia::boot::Arguments::GetResponse)
    == ::llcpp::fuchsia::boot::Arguments::GetResponse::PrimarySize);
static_assert(offsetof(::llcpp::fuchsia::boot::Arguments::GetResponse, vmo) == 16);
static_assert(offsetof(::llcpp::fuchsia::boot::Arguments::GetResponse, size) == 24);

}  // namespace fidl
