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

#pragma once

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

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

namespace llcpp {

namespace fidl {
namespace test {
namespace protocolrequest {

class Parent;
class Child;

extern "C" const fidl_type_t
    fidl_test_protocolrequest_ParentGetChildRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocolrequest_ParentGetChildResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocolrequest_ParentGetChildRequestRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocolrequest_ParentGetChildRequestResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocolrequest_ParentTakeChildRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocolrequest_ParentTakeChildResponseTable;
extern "C" const fidl_type_t
    fidl_test_protocolrequest_ParentTakeChildRequestRequestTable;
extern "C" const fidl_type_t
    fidl_test_protocolrequest_ParentTakeChildRequestResponseTable;

class Parent final {
  Parent() = delete;

 public:
  struct GetChildResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::channel c;
    explicit GetChildResponse(::zx::channel& c) : c(std::move(c)) {
      _InitHeader();
    }
    GetChildResponse() { _InitHeader(); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocolrequest_ParentGetChildResponseTable;
    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 ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
    void _CloseHandles();

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            ::zx::channel& c)
          : message_(_bytes, _byte_size, sizeof(GetChildResponse), handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        FIDL_ALIGNDECL GetChildResponse _response{c};
        message_.LinearizeAndEncode<GetChildResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            GetChildResponse* response)
          : message_(bytes, byte_size, sizeof(GetChildResponse), handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        message_.LinearizeAndEncode<GetChildResponse>(response);
      }
      UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
      UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      GetChildResponse& Message() {
        return *reinterpret_cast<GetChildResponse*>(message_.bytes());
      }
      zx_handle_disposition_t
          handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(::zx::channel& c)
          : message_(bytes_, sizeof(bytes_), c) {}
      explicit OwnedEncodedMessage(GetChildResponse* response)
          : message_(bytes_, sizeof(bytes_), response) {}
      OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
      OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

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

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

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

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

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

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

   private:
    void _InitHeader();
  };
  struct GetChildRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit GetChildRequest(zx_txid_t _txid) { _InitHeader(_txid); }

    static constexpr const fidl_type_t* Type =
        &::fidl::_llcpp_coding_AnyZeroArgMessageTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 16;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr uint32_t AltPrimarySize = 16;
    static constexpr uint32_t AltMaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kRequest;
    using ResponseType = GetChildResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid)
          : message_(_bytes, _byte_size, sizeof(GetChildRequest), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL GetChildRequest _request(_txid);
        message_.LinearizeAndEncode<GetChildRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            GetChildRequest* request)
          : message_(bytes, byte_size, sizeof(GetChildRequest), nullptr, 0, 0) {
        message_.LinearizeAndEncode<GetChildRequest>(request);
      }
      UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
      UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      GetChildRequest& Message() {
        return *reinterpret_cast<GetChildRequest*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(GetChildRequest* request)
          : message_(bytes_, sizeof(bytes_), request) {}
      OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
      OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

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

    class DecodedMessage final : public ::fidl::internal::IncomingMessage {
     public:
      DecodedMessage(uint8_t* bytes, uint32_t byte_actual,
                     zx_handle_info_t* handles = nullptr,
                     uint32_t handle_actual = 0)
          : ::fidl::internal::IncomingMessage(bytes, byte_actual, handles,
                                              handle_actual) {
        Decode<GetChildRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<GetChildRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

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

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

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

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<GetChildRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct GetChildRequestResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::channel r;
    explicit GetChildRequestResponse(::zx::channel& r) : r(std::move(r)) {
      _InitHeader();
    }
    GetChildRequestResponse() { _InitHeader(); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocolrequest_ParentGetChildRequestResponseTable;
    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 ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kResponse;
    void _CloseHandles();

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            ::zx::channel& r)
          : message_(_bytes, _byte_size, sizeof(GetChildRequestResponse),
                     handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        FIDL_ALIGNDECL GetChildRequestResponse _response{r};
        message_.LinearizeAndEncode<GetChildRequestResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            GetChildRequestResponse* response)
          : message_(bytes, byte_size, sizeof(GetChildRequestResponse),
                     handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        message_.LinearizeAndEncode<GetChildRequestResponse>(response);
      }
      UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
      UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      GetChildRequestResponse& Message() {
        return *reinterpret_cast<GetChildRequestResponse*>(message_.bytes());
      }
      zx_handle_disposition_t
          handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(::zx::channel& r)
          : message_(bytes_, sizeof(bytes_), r) {}
      explicit OwnedEncodedMessage(GetChildRequestResponse* response)
          : message_(bytes_, sizeof(bytes_), response) {}
      OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
      OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

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

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

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

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

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

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

   private:
    void _InitHeader();
  };
  struct GetChildRequestRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit GetChildRequestRequest(zx_txid_t _txid) { _InitHeader(_txid); }

    static constexpr const fidl_type_t* Type =
        &::fidl::_llcpp_coding_AnyZeroArgMessageTable;
    static constexpr uint32_t MaxNumHandles = 0;
    static constexpr uint32_t PrimarySize = 16;
    static constexpr uint32_t MaxOutOfLine = 0;
    static constexpr uint32_t AltPrimarySize = 16;
    static constexpr uint32_t AltMaxOutOfLine = 0;
    static constexpr bool HasFlexibleEnvelope = false;
    static constexpr bool HasPointer = false;
    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kRequest;
    using ResponseType = GetChildRequestResponse;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid)
          : message_(_bytes, _byte_size, sizeof(GetChildRequestRequest),
                     nullptr, 0, 0) {
        FIDL_ALIGNDECL GetChildRequestRequest _request(_txid);
        message_.LinearizeAndEncode<GetChildRequestRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            GetChildRequestRequest* request)
          : message_(bytes, byte_size, sizeof(GetChildRequestRequest), nullptr,
                     0, 0) {
        message_.LinearizeAndEncode<GetChildRequestRequest>(request);
      }
      UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
      UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      GetChildRequestRequest& Message() {
        return *reinterpret_cast<GetChildRequestRequest*>(message_.bytes());
      }
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid)
          : message_(bytes_, sizeof(bytes_), _txid) {}
      explicit OwnedEncodedMessage(GetChildRequestRequest* request)
          : message_(bytes_, sizeof(bytes_), request) {}
      OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
      OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

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

    class DecodedMessage final : public ::fidl::internal::IncomingMessage {
     public:
      DecodedMessage(uint8_t* bytes, uint32_t byte_actual,
                     zx_handle_info_t* handles = nullptr,
                     uint32_t handle_actual = 0)
          : ::fidl::internal::IncomingMessage(bytes, byte_actual, handles,
                                              handle_actual) {
        Decode<GetChildRequestRequest>();
      }
      DecodedMessage(fidl_incoming_msg_t* msg)
          : ::fidl::internal::IncomingMessage(msg) {
        Decode<GetChildRequestRequest>();
      }
      DecodedMessage(const DecodedMessage&) = delete;
      DecodedMessage(DecodedMessage&&) = delete;
      DecodedMessage* operator=(const DecodedMessage&) = delete;
      DecodedMessage* operator=(DecodedMessage&&) = delete;

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

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

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

     private:
      DecodedMessage(::fidl::OutgoingMessage& outgoing_message) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<GetChildRequestRequest>();
        }
      }
    };

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct TakeChildRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::channel c;
    explicit TakeChildRequest(zx_txid_t _txid, ::zx::channel& c)
        : c(std::move(c)) {
      _InitHeader(_txid);
    }
    explicit TakeChildRequest(zx_txid_t _txid) { _InitHeader(_txid); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocolrequest_ParentTakeChildRequestTable;
    static constexpr uint32_t MaxNumHandles = 1;
    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 ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kRequest;
    void _CloseHandles();

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, ::zx::channel& c)
          : message_(_bytes, _byte_size, sizeof(TakeChildRequest), handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        FIDL_ALIGNDECL TakeChildRequest _request(_txid, c);
        message_.LinearizeAndEncode<TakeChildRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            TakeChildRequest* request)
          : message_(bytes, byte_size, sizeof(TakeChildRequest), handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        message_.LinearizeAndEncode<TakeChildRequest>(request);
      }
      UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
      UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      TakeChildRequest& Message() {
        return *reinterpret_cast<TakeChildRequest*>(message_.bytes());
      }
      zx_handle_disposition_t
          handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid, ::zx::channel& c)
          : message_(bytes_, sizeof(bytes_), _txid, c) {}
      explicit OwnedEncodedMessage(TakeChildRequest* request)
          : message_(bytes_, sizeof(bytes_), request) {}
      OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
      OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

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

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

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

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

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

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

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  struct TakeChildRequestRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::zx::channel r;
    explicit TakeChildRequestRequest(zx_txid_t _txid, ::zx::channel& r)
        : r(std::move(r)) {
      _InitHeader(_txid);
    }
    explicit TakeChildRequestRequest(zx_txid_t _txid) { _InitHeader(_txid); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_protocolrequest_ParentTakeChildRequestRequestTable;
    static constexpr uint32_t MaxNumHandles = 1;
    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 ::fidl::internal::TransactionalMessageKind MessageKind =
        ::fidl::internal::TransactionalMessageKind::kRequest;
    void _CloseHandles();

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            zx_txid_t _txid, ::zx::channel& r)
          : message_(_bytes, _byte_size, sizeof(TakeChildRequestRequest),
                     handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        FIDL_ALIGNDECL TakeChildRequestRequest _request(_txid, r);
        message_.LinearizeAndEncode<TakeChildRequestRequest>(&_request);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            TakeChildRequestRequest* request)
          : message_(bytes, byte_size, sizeof(TakeChildRequestRequest),
                     handles_,
                     std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
        message_.LinearizeAndEncode<TakeChildRequestRequest>(request);
      }
      UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
      UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

     private:
      TakeChildRequestRequest& Message() {
        return *reinterpret_cast<TakeChildRequestRequest*>(message_.bytes());
      }
      zx_handle_disposition_t
          handles_[std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles)];
      ::fidl::OutgoingMessage message_;
    };

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(zx_txid_t _txid, ::zx::channel& r)
          : message_(bytes_, sizeof(bytes_), _txid, r) {}
      explicit OwnedEncodedMessage(TakeChildRequestRequest* request)
          : message_(bytes_, sizeof(bytes_), request) {}
      OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
      OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

      void Write(zx_handle_t client) { message_.Write(client); }

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

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

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

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

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

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

   private:
    void _InitHeader(zx_txid_t _txid);
  };

  // Collection of return types of FIDL calls in this protocol.
  class ResultOf final {
    ResultOf() = delete;

   public:
    class GetChild final : public ::fidl::Result {
     public:
      explicit GetChild(zx_handle_t _client);
      GetChild(zx_handle_t _client, zx_time_t _deadline);
      explicit GetChild(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      GetChild(GetChild&&) = delete;
      GetChild(const GetChild&) = delete;
      GetChild* operator=(GetChild&&) = delete;
      GetChild* operator=(const GetChild&) = delete;
      ~GetChild() {
        if (ok()) {
          Unwrap()->_CloseHandles();
        }
      }

      GetChildResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<GetChildResponse*>(bytes_);
      }
      const GetChildResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const GetChildResponse*>(bytes_);
      }

      GetChildResponse& value() { return *Unwrap(); }
      const GetChildResponse& value() const { return *Unwrap(); }

      GetChildResponse* operator->() { return &value(); }
      const GetChildResponse* operator->() const { return &value(); }

      GetChildResponse& operator*() { return value(); }
      const GetChildResponse& operator*() const { return value(); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[GetChildResponse::PrimarySize +
                     GetChildResponse::MaxOutOfLine];
    };
    class GetChildRequest final : public ::fidl::Result {
     public:
      explicit GetChildRequest(zx_handle_t _client);
      GetChildRequest(zx_handle_t _client, zx_time_t _deadline);
      explicit GetChildRequest(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      GetChildRequest(GetChildRequest&&) = delete;
      GetChildRequest(const GetChildRequest&) = delete;
      GetChildRequest* operator=(GetChildRequest&&) = delete;
      GetChildRequest* operator=(const GetChildRequest&) = delete;
      ~GetChildRequest() {
        if (ok()) {
          Unwrap()->_CloseHandles();
        }
      }

      GetChildRequestResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<GetChildRequestResponse*>(bytes_);
      }
      const GetChildRequestResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const GetChildRequestResponse*>(bytes_);
      }

      GetChildRequestResponse& value() { return *Unwrap(); }
      const GetChildRequestResponse& value() const { return *Unwrap(); }

      GetChildRequestResponse* operator->() { return &value(); }
      const GetChildRequestResponse* operator->() const { return &value(); }

      GetChildRequestResponse& operator*() { return value(); }
      const GetChildRequestResponse& operator*() const { return value(); }

     private:
      FIDL_ALIGNDECL
      uint8_t bytes_[GetChildRequestResponse::PrimarySize +
                     GetChildRequestResponse::MaxOutOfLine];
    };
    class TakeChild final : public ::fidl::Result {
     public:
      explicit TakeChild(zx_handle_t _client, ::zx::channel& c);
      explicit TakeChild(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      TakeChild(TakeChild&&) = delete;
      TakeChild(const TakeChild&) = delete;
      TakeChild* operator=(TakeChild&&) = delete;
      TakeChild* operator=(const TakeChild&) = delete;
      ~TakeChild() = default;

     private:
    };
    class TakeChildRequest final : public ::fidl::Result {
     public:
      explicit TakeChildRequest(zx_handle_t _client, ::zx::channel& r);
      explicit TakeChildRequest(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      TakeChildRequest(TakeChildRequest&&) = delete;
      TakeChildRequest(const TakeChildRequest&) = delete;
      TakeChildRequest* operator=(TakeChildRequest&&) = delete;
      TakeChildRequest* operator=(const TakeChildRequest&) = delete;
      ~TakeChildRequest() = default;

     private:
    };
  };

  // Collection of return types of FIDL calls in this protocol,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;

   public:
    class GetChild final : public ::fidl::Result {
     public:
      explicit GetChild(zx_handle_t _client, uint8_t* _response_bytes,
                        uint32_t _response_byte_capacity);
      explicit GetChild(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      GetChild(GetChild&&) = delete;
      GetChild(const GetChild&) = delete;
      GetChild* operator=(GetChild&&) = delete;
      GetChild* operator=(const GetChild&) = delete;
      ~GetChild() {
        if (ok()) {
          Unwrap()->_CloseHandles();
        }
      }

      GetChildResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<GetChildResponse*>(bytes_);
      }
      const GetChildResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const GetChildResponse*>(bytes_);
      }

      GetChildResponse& value() { return *Unwrap(); }
      const GetChildResponse& value() const { return *Unwrap(); }

      GetChildResponse* operator->() { return &value(); }
      const GetChildResponse* operator->() const { return &value(); }

      GetChildResponse& operator*() { return value(); }
      const GetChildResponse& operator*() const { return value(); }

     private:
      uint8_t* bytes_;
    };
    class GetChildRequest final : public ::fidl::Result {
     public:
      explicit GetChildRequest(zx_handle_t _client, uint8_t* _response_bytes,
                               uint32_t _response_byte_capacity);
      explicit GetChildRequest(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      GetChildRequest(GetChildRequest&&) = delete;
      GetChildRequest(const GetChildRequest&) = delete;
      GetChildRequest* operator=(GetChildRequest&&) = delete;
      GetChildRequest* operator=(const GetChildRequest&) = delete;
      ~GetChildRequest() {
        if (ok()) {
          Unwrap()->_CloseHandles();
        }
      }

      GetChildRequestResponse* Unwrap() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<GetChildRequestResponse*>(bytes_);
      }
      const GetChildRequestResponse* Unwrap() const {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<const GetChildRequestResponse*>(bytes_);
      }

      GetChildRequestResponse& value() { return *Unwrap(); }
      const GetChildRequestResponse& value() const { return *Unwrap(); }

      GetChildRequestResponse* operator->() { return &value(); }
      const GetChildRequestResponse* operator->() const { return &value(); }

      GetChildRequestResponse& operator*() { return value(); }
      const GetChildRequestResponse& operator*() const { return value(); }

     private:
      uint8_t* bytes_;
    };
    class TakeChild final : public ::fidl::Result {
     public:
      explicit TakeChild(zx_handle_t _client, uint8_t* _request_bytes,
                         uint32_t _request_byte_capacity, ::zx::channel& c);
      explicit TakeChild(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      TakeChild(TakeChild&&) = delete;
      TakeChild(const TakeChild&) = delete;
      TakeChild* operator=(TakeChild&&) = delete;
      TakeChild* operator=(const TakeChild&) = delete;
      ~TakeChild() = default;
    };
    class TakeChildRequest final : public ::fidl::Result {
     public:
      explicit TakeChildRequest(zx_handle_t _client, uint8_t* _request_bytes,
                                uint32_t _request_byte_capacity,
                                ::zx::channel& r);
      explicit TakeChildRequest(const ::fidl::Result& result)
          : ::fidl::Result(result) {}
      TakeChildRequest(TakeChildRequest&&) = delete;
      TakeChildRequest(const TakeChildRequest&) = delete;
      TakeChildRequest* operator=(TakeChildRequest&&) = delete;
      TakeChildRequest* operator=(const TakeChildRequest&) = delete;
      ~TakeChildRequest() = default;
    };
  };

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

   public:
    // Allocates 40 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::GetChild GetChild(::zx::unowned_channel _client_end) {
      return ResultOf::GetChild(_client_end->get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::GetChild GetChild(
        ::zx::unowned_channel _client_end

        ,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::GetChild(
          _client_end->get(), _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 40 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::GetChildRequest GetChildRequest(
        ::zx::unowned_channel _client_end) {
      return ResultOf::GetChildRequest(_client_end->get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::GetChildRequest GetChildRequest(
        ::zx::unowned_channel _client_end

        ,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::GetChildRequest(
          _client_end->get(), _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 24 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::TakeChild TakeChild(::zx::unowned_channel _client_end,
                                         ::zx::channel c) {
      return ResultOf::TakeChild(_client_end->get(), c);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::TakeChild TakeChild(
        ::zx::unowned_channel _client_end, ::fidl::BufferSpan _request_buffer,
        ::zx::channel c) {
      return UnownedResultOf::TakeChild(_client_end->get(),
                                        _request_buffer.data,
                                        _request_buffer.capacity, c);
    }

    // Allocates 24 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::TakeChildRequest TakeChildRequest(
        ::zx::unowned_channel _client_end, ::zx::channel r) {
      return ResultOf::TakeChildRequest(_client_end->get(), r);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::TakeChildRequest TakeChildRequest(
        ::zx::unowned_channel _client_end, ::fidl::BufferSpan _request_buffer,
        ::zx::channel r) {
      return UnownedResultOf::TakeChildRequest(_client_end->get(),
                                               _request_buffer.data,
                                               _request_buffer.capacity, r);
    }
  };

  class SyncClient final {
   public:
    SyncClient() = default;
    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_; }

    // Allocates 40 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::GetChild GetChild() {
      return ResultOf::GetChild(this->channel().get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::GetChild GetChild(::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::GetChild(this->channel().get(),
                                       _response_buffer.data,
                                       _response_buffer.capacity);
    }

    // Allocates 40 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::GetChildRequest GetChildRequest() {
      return ResultOf::GetChildRequest(this->channel().get());
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::GetChildRequest GetChildRequest(
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::GetChildRequest(this->channel().get(),
                                              _response_buffer.data,
                                              _response_buffer.capacity);
    }

    // Allocates 24 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::TakeChild TakeChild(::zx::channel c) {
      return ResultOf::TakeChild(this->channel().get(), c);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::TakeChild TakeChild(::fidl::BufferSpan _request_buffer,
                                         ::zx::channel c) {
      return UnownedResultOf::TakeChild(this->channel().get(),
                                        _request_buffer.data,
                                        _request_buffer.capacity, c);
    }

    // Allocates 24 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::TakeChildRequest TakeChildRequest(::zx::channel r) {
      return ResultOf::TakeChildRequest(this->channel().get(), r);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::TakeChildRequest TakeChildRequest(
        ::fidl::BufferSpan _request_buffer, ::zx::channel r) {
      return UnownedResultOf::TakeChildRequest(this->channel().get(),
                                               _request_buffer.data,
                                               _request_buffer.capacity, r);
    }

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

  struct AsyncEventHandlers;
  class GetChildResponseContext;
  class GetChildRequestResponseContext;
  class ClientImpl;

  // Pure-virtual interface to be implemented by a server.
  class Interface : public ::fidl::internal::IncomingMessageDispatcher {
   public:
    Interface() = default;
    virtual ~Interface() = default;

    // The marker protocol type within which this |Interface| class is defined.
    using _EnclosingProtocol = Parent;

    class GetChildCompleterBase : public ::fidl::CompleterBase {
     public:
      // In the following methods, the return value indicates internal errors
      // during the reply, such as encoding or writing to the transport. Note
      // that any error will automatically lead to the destruction of the
      // binding, after which the |on_unbound| callback will be triggered with a
      // detailed reason.
      //
      // See //zircon/system/ulib/fidl/include/lib/fidl/llcpp/server.h.
      //
      // Because the reply status is identical to the unbinding status, it can
      // be safely ignored.
      ::fidl::Result Reply(::zx::channel c);
      ::fidl::Result Reply(::fidl::BufferSpan _buffer, ::zx::channel c);

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

    using GetChildCompleter = ::fidl::Completer<GetChildCompleterBase>;

    virtual void GetChild(GetChildCompleter::Sync& _completer) = 0;

    class GetChildRequestCompleterBase : public ::fidl::CompleterBase {
     public:
      // In the following methods, the return value indicates internal errors
      // during the reply, such as encoding or writing to the transport. Note
      // that any error will automatically lead to the destruction of the
      // binding, after which the |on_unbound| callback will be triggered with a
      // detailed reason.
      //
      // See //zircon/system/ulib/fidl/include/lib/fidl/llcpp/server.h.
      //
      // Because the reply status is identical to the unbinding status, it can
      // be safely ignored.
      ::fidl::Result Reply(::zx::channel r);
      ::fidl::Result Reply(::fidl::BufferSpan _buffer, ::zx::channel r);

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

    using GetChildRequestCompleter =
        ::fidl::Completer<GetChildRequestCompleterBase>;

    virtual void GetChildRequest(
        GetChildRequestCompleter::Sync& _completer) = 0;

    using TakeChildCompleter = ::fidl::Completer<>;

    virtual void TakeChild(::zx::channel c,
                           TakeChildCompleter::Sync& _completer) = 0;

    using TakeChildRequestCompleter = ::fidl::Completer<>;

    virtual void TakeChildRequest(
        ::zx::channel r, TakeChildRequestCompleter::Sync& _completer) = 0;

   private:
    ::fidl::DispatchResult dispatch_message(fidl_incoming_msg_t* msg,
                                            ::fidl::Transaction* txn) final;
  };

  // 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 ::fidl::DispatchResult TryDispatch(Interface* impl,
                                            fidl_incoming_msg_t* msg,
                                            ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the
  // protocol. 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 ::fidl::DispatchResult Dispatch(Interface* impl,
                                         fidl_incoming_msg_t* msg,
                                         ::fidl::Transaction* txn);

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

  class EventSender;
  class WeakEventSender;
};

class Child final {
  Child() = delete;

 public:
  // Collection of return types of FIDL calls in this protocol.
  class ResultOf final {
    ResultOf() = delete;

   public:
  };

  // Collection of return types of FIDL calls in this protocol,
  // when the caller-allocate flavor or in-place call is used.
  class UnownedResultOf final {
    UnownedResultOf() = delete;

   public:
  };

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

   public:
  };

  class SyncClient final {
   public:
    SyncClient() = default;
    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_; }

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

  struct AsyncEventHandlers;
  class ClientImpl;

  // Pure-virtual interface to be implemented by a server.
  class Interface : public ::fidl::internal::IncomingMessageDispatcher {
   public:
    Interface() = default;
    virtual ~Interface() = default;

    // The marker protocol type within which this |Interface| class is defined.
    using _EnclosingProtocol = Child;

   private:
    ::fidl::DispatchResult dispatch_message(fidl_incoming_msg_t* msg,
                                            ::fidl::Transaction* txn) final;
  };

  // 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 ::fidl::DispatchResult TryDispatch(Interface* impl,
                                            fidl_incoming_msg_t* msg,
                                            ::fidl::Transaction* txn);

  // Dispatches the incoming message to one of the handlers functions in the
  // protocol. 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 ::fidl::DispatchResult Dispatch(Interface* impl,
                                         fidl_incoming_msg_t* msg,
                                         ::fidl::Transaction* txn);

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

  class EventSender;
  class WeakEventSender;
};

}  // namespace protocolrequest
}  // namespace test
}  // namespace fidl
}  // namespace llcpp

namespace fidl {

template <>
struct IsFidlType<::llcpp::fidl::test::protocolrequest::Parent::GetChildRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocolrequest::Parent::GetChildRequest>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocolrequest::Parent::GetChildRequest) ==
    ::llcpp::fidl::test::protocolrequest::Parent::GetChildRequest::PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocolrequest::Parent::GetChildResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocolrequest::Parent::GetChildResponse>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocolrequest::Parent::GetChildResponse) ==
    ::llcpp::fidl::test::protocolrequest::Parent::GetChildResponse::
        PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocolrequest::Parent::GetChildResponse,
             c) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocolrequest::Parent::GetChildRequestRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocolrequest::Parent::GetChildRequestRequest>
    : public std::true_type {};
static_assert(
    sizeof(
        ::llcpp::fidl::test::protocolrequest::Parent::GetChildRequestRequest) ==
    ::llcpp::fidl::test::protocolrequest::Parent::GetChildRequestRequest::
        PrimarySize);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocolrequest::Parent::GetChildRequestResponse>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocolrequest::Parent::GetChildRequestResponse>
    : public std::true_type {};
static_assert(sizeof(::llcpp::fidl::test::protocolrequest::Parent::
                         GetChildRequestResponse) ==
              ::llcpp::fidl::test::protocolrequest::Parent::
                  GetChildRequestResponse::PrimarySize);
static_assert(
    offsetof(
        ::llcpp::fidl::test::protocolrequest::Parent::GetChildRequestResponse,
        r) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocolrequest::Parent::TakeChildRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocolrequest::Parent::TakeChildRequest>
    : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::protocolrequest::Parent::TakeChildRequest) ==
    ::llcpp::fidl::test::protocolrequest::Parent::TakeChildRequest::
        PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::protocolrequest::Parent::TakeChildRequest,
             c) == 16);

template <>
struct IsFidlType<
    ::llcpp::fidl::test::protocolrequest::Parent::TakeChildRequestRequest>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::protocolrequest::Parent::TakeChildRequestRequest>
    : public std::true_type {};
static_assert(sizeof(::llcpp::fidl::test::protocolrequest::Parent::
                         TakeChildRequestRequest) ==
              ::llcpp::fidl::test::protocolrequest::Parent::
                  TakeChildRequestRequest::PrimarySize);
static_assert(
    offsetof(
        ::llcpp::fidl::test::protocolrequest::Parent::TakeChildRequestRequest,
        r) == 16);

}  // namespace fidl

namespace llcpp {

namespace fidl {
namespace test {
namespace protocolrequest {

struct Parent::AsyncEventHandlers {};

class Parent::GetChildResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  GetChildResponseContext();

  virtual void OnReply(Parent::GetChildResponse* message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class Parent::GetChildRequestResponseContext
    : public ::fidl::internal::ResponseContext {
 public:
  GetChildRequestResponseContext();

  virtual void OnReply(Parent::GetChildRequestResponse* message) = 0;

 private:
  void OnReply(uint8_t* reply) override;
};

class Parent::ClientImpl final : private ::fidl::internal::ClientBase {
 public:
  // Asynchronous variant of |Parent.GetChild()|. Allocates 16 bytes of request
  // buffer on the stack. The callback is stored on the heap.
  ::fidl::Result GetChild(
      ::fit::callback<void(GetChildResponse* response)> _cb);
  // Asynchronous variant of |Parent.GetChild()|. Caller provides the backing
  // storage for FIDL message via request buffer. Ownership of _context is given
  // unsafely to the binding until OnError() or OnReply() are called on it.
  ::fidl::Result GetChild(GetChildResponseContext* _context);
  // Synchronous variant of |Parent.GetChild()|. Allocates 40 bytes of message
  // buffer on the stack. No heap allocation necessary.
  ResultOf::GetChild GetChild_Sync();

  // Synchronous variant of |Parent.GetChild()|. Caller provides the backing
  // storage for FIDL message via request and response buffers.
  UnownedResultOf::GetChild GetChild_Sync(::fidl::BufferSpan _response_buffer);

  // Asynchronous variant of |Parent.GetChildRequest()|. Allocates 16 bytes of
  // request buffer on the stack. The callback is stored on the heap.
  ::fidl::Result GetChildRequest(
      ::fit::callback<void(GetChildRequestResponse* response)> _cb);
  // Asynchronous variant of |Parent.GetChildRequest()|. Caller provides the
  // backing storage for FIDL message via request buffer. Ownership of _context
  // is given unsafely to the binding until OnError() or OnReply() are called on
  // it.
  ::fidl::Result GetChildRequest(GetChildRequestResponseContext* _context);
  // Synchronous variant of |Parent.GetChildRequest()|. Allocates 40 bytes of
  // message buffer on the stack. No heap allocation necessary.
  ResultOf::GetChildRequest GetChildRequest_Sync();

  // Synchronous variant of |Parent.GetChildRequest()|. Caller provides the
  // backing storage for FIDL message via request and response buffers.
  UnownedResultOf::GetChildRequest GetChildRequest_Sync(
      ::fidl::BufferSpan _response_buffer);

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Result TakeChild(::zx::channel c);

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::Result TakeChild(::fidl::BufferSpan _request_buffer, ::zx::channel c);

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Result TakeChildRequest(::zx::channel r);

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::Result TakeChildRequest(::fidl::BufferSpan _request_buffer,
                                  ::zx::channel r);

 private:
  friend class ::fidl::Client<Parent>;

  explicit ClientImpl(AsyncEventHandlers handlers)
      : handlers_(std::move(handlers)) {}

  std::optional<::fidl::UnbindInfo> DispatchEvent(
      fidl_incoming_msg_t* msg) override;

  AsyncEventHandlers handlers_;
};

// |EventSender| owns a server endpoint of a channel speaking
// the Parent protocol, and can send events in that protocol.
class Parent::EventSender {
 public:
  // Constructs an event sender with an invalid channel.
  EventSender() = default;

  // TODO(fxbug.dev/65212): EventSender should take a ::fidl::ServerEnd.
  explicit EventSender(::zx::channel server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::zx::channel& channel() const { return server_end_; }
  ::zx::channel& channel() { return server_end_; }

  // Whether the underlying channel is valid.
  bool is_valid() const { return server_end_.is_valid(); }

 private:
  ::zx::channel server_end_;
};

class Parent::WeakEventSender {
 public:
 private:
  friend class ::fidl::ServerBindingRef<Parent>;

  explicit WeakEventSender(
      std::weak_ptr<::fidl::internal::AsyncServerBinding<Parent>> binding)
      : binding_(std::move(binding)) {}

  std::weak_ptr<::fidl::internal::AsyncServerBinding<Parent>> binding_;
};

struct Child::AsyncEventHandlers {};

class Child::ClientImpl final : private ::fidl::internal::ClientBase {
 public:
 private:
  friend class ::fidl::Client<Child>;

  explicit ClientImpl(AsyncEventHandlers handlers)
      : handlers_(std::move(handlers)) {}

  std::optional<::fidl::UnbindInfo> DispatchEvent(
      fidl_incoming_msg_t* msg) override;

  AsyncEventHandlers handlers_;
};

// |EventSender| owns a server endpoint of a channel speaking
// the Child protocol, and can send events in that protocol.
class Child::EventSender {
 public:
  // Constructs an event sender with an invalid channel.
  EventSender() = default;

  // TODO(fxbug.dev/65212): EventSender should take a ::fidl::ServerEnd.
  explicit EventSender(::zx::channel server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::zx::channel& channel() const { return server_end_; }
  ::zx::channel& channel() { return server_end_; }

  // Whether the underlying channel is valid.
  bool is_valid() const { return server_end_.is_valid(); }

 private:
  ::zx::channel server_end_;
};

class Child::WeakEventSender {
 public:
 private:
  friend class ::fidl::ServerBindingRef<Child>;

  explicit WeakEventSender(
      std::weak_ptr<::fidl::internal::AsyncServerBinding<Child>> binding)
      : binding_(std::move(binding)) {}

  std::weak_ptr<::fidl::internal::AsyncServerBinding<Child>> binding_;
};

}  // namespace protocolrequest
}  // namespace test
}  // namespace fidl
}  // namespace llcpp
