// 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/object_view.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 <algorithm>
#include <cstddef>
#include <variant>
#ifdef __Fuchsia__
#include <lib/fidl/llcpp/client.h>
#include <lib/fidl/llcpp/client_end.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/result.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl/llcpp/server_end.h>
#include <lib/fidl/llcpp/service_handler_interface.h>
#include <lib/fidl/llcpp/sync_call.h>
#include <lib/fidl/llcpp/transaction.h>
#include <lib/fidl/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;
    ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c;
    explicit GetChildResponse(
        ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child>& 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,
          ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child>& 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_; }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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(
          ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child>& 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();
      }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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_; }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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();
      }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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;
    ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r;
    explicit GetChildRequestResponse(
        ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child>& 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,
          ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child>& 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_; }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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(
          ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child>& 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();
      }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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_; }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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();
      }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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;
    ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c;
    explicit TakeChildRequest(
        zx_txid_t _txid,
        ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child>& 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,
          ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child>& 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_; }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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,
          ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child>& 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();
      }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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;
    ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r;
    explicit TakeChildRequestRequest(
        zx_txid_t _txid,
        ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child>& 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,
          ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child>& 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_; }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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,
          ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child>& 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();
      }

      template <typename ChannelLike>
      void Write(ChannelLike&& client) {
        message_.Write(std::forward<ChannelLike>(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);
  };

  class EventHandlerInterface {
   public:
    EventHandlerInterface() = default;
    virtual ~EventHandlerInterface() = default;
  };

  // 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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::protocolrequest::Parent>
              _client);
      GetChild(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::protocolrequest::Parent>
              _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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::protocolrequest::Parent>
              _client);
      GetChildRequest(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::protocolrequest::Parent>
              _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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::protocolrequest::Parent>
              _client,
          ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child>& 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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::protocolrequest::Parent>
              _client,
          ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child>& 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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::protocolrequest::Parent>
              _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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::protocolrequest::Parent>
              _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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::protocolrequest::Parent>
              _client,
          uint8_t* _request_bytes, uint32_t _request_byte_capacity,
          ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child>& 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(
          ::fidl::UnownedClientEnd<::llcpp::fidl::test::protocolrequest::Parent>
              _client,
          uint8_t* _request_bytes, uint32_t _request_byte_capacity,
          ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child>& 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 or a
  // const reference to a
  // |fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Parent>|, 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(
        ::fidl::UnownedClientEnd<Parent> _client_end) {
      return ResultOf::GetChild(_client_end);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::GetChild GetChild(
        ::fidl::UnownedClientEnd<Parent> _client_end,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::GetChild(_client_end, _response_buffer.data,
                                       _response_buffer.capacity);
    }

    // Allocates 40 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::GetChildRequest GetChildRequest(
        ::fidl::UnownedClientEnd<Parent> _client_end) {
      return ResultOf::GetChildRequest(_client_end);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::GetChildRequest GetChildRequest(
        ::fidl::UnownedClientEnd<Parent> _client_end,
        ::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::GetChildRequest(
          _client_end, _response_buffer.data, _response_buffer.capacity);
    }

    // Allocates 24 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::TakeChild TakeChild(
        ::fidl::UnownedClientEnd<Parent> _client_end,
        ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c) {
      return ResultOf::TakeChild(_client_end, c);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::TakeChild TakeChild(
        ::fidl::UnownedClientEnd<Parent> _client_end,
        ::fidl::BufferSpan _request_buffer,
        ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c) {
      return UnownedResultOf::TakeChild(_client_end, _request_buffer.data,
                                        _request_buffer.capacity, c);
    }

    // Allocates 24 bytes of message buffer on the stack. No heap allocation
    // necessary.
    static ResultOf::TakeChildRequest TakeChildRequest(
        ::fidl::UnownedClientEnd<Parent> _client_end,
        ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r) {
      return ResultOf::TakeChildRequest(_client_end, r);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    static UnownedResultOf::TakeChildRequest TakeChildRequest(
        ::fidl::UnownedClientEnd<Parent> _client_end,
        ::fidl::BufferSpan _request_buffer,
        ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r) {
      return UnownedResultOf::TakeChildRequest(
          _client_end, _request_buffer.data, _request_buffer.capacity, r);
    }
  };

  class SyncClient final {
   public:
    SyncClient() = default;

    explicit SyncClient(::fidl::ClientEnd<Parent> client_end)
        : client_end_(std::move(client_end)) {}

    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::fidl::ClientEnd<Parent>& client_end() const { return client_end_; }
    ::fidl::ClientEnd<Parent>& client_end() { return client_end_; }

    const ::zx::channel& channel() const { return client_end_.channel(); }
    ::zx::channel* mutable_channel() { return &client_end_.channel(); }

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

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::GetChild GetChild(::fidl::BufferSpan _response_buffer) {
      return UnownedResultOf::GetChild(
          this->client_end(), _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->client_end());
    }

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

    // Allocates 24 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::TakeChild TakeChild(
        ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c) {
      return ResultOf::TakeChild(this->client_end(), c);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::TakeChild TakeChild(
        ::fidl::BufferSpan _request_buffer,
        ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c) {
      return UnownedResultOf::TakeChild(this->client_end(),
                                        _request_buffer.data,
                                        _request_buffer.capacity, c);
    }

    // Allocates 24 bytes of message buffer on the stack. No heap allocation
    // necessary.
    ResultOf::TakeChildRequest TakeChildRequest(
        ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r) {
      return ResultOf::TakeChildRequest(this->client_end(), r);
    }

    // Caller provides the backing storage for FIDL message via request and
    // response buffers.
    UnownedResultOf::TakeChildRequest TakeChildRequest(
        ::fidl::BufferSpan _request_buffer,
        ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r) {
      return UnownedResultOf::TakeChildRequest(this->client_end(),
                                               _request_buffer.data,
                                               _request_buffer.capacity, r);
    }

   private:
    ::fidl::ClientEnd<Parent> client_end_;
  };

  class AsyncEventHandler;
  class GetChildResponseContext;
  class GetChildRequestResponseContext;
  class ClientImpl;

  // Pure-virtual interface to be implemented by a server.
  // This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
  // and |fidl::ServerEnd<SomeProtocol>|).
  // TODO(fxbug.dev/65212): Rename this to |Interface| after all users have
  // migrated to the typed channels API.
  class TypedChannelInterface
      : public ::fidl::internal::IncomingMessageDispatcher {
   public:
    TypedChannelInterface() = default;
    virtual ~TypedChannelInterface() = default;

    // The marker protocol type within which this |TypedChannelInterface| 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(
          ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c);
      ::fidl::Result Reply(
          ::fidl::BufferSpan _buffer,
          ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> 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(
          ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r);
      ::fidl::Result Reply(
          ::fidl::BufferSpan _buffer,
          ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> 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(
        ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c,
        TakeChildCompleter::Sync& _completer) = 0;

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

    virtual void TakeChildRequest(
        ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r,
        TakeChildRequestCompleter::Sync& _completer) = 0;

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

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

    // The marker protocol type within which this |Interface| class is defined.
    using TypedChannelInterface::_EnclosingProtocol;
    using TypedChannelInterface::GetChildCompleter;

    using TypedChannelInterface::GetChildRequestCompleter;

    using TypedChannelInterface::TakeChildCompleter;

    virtual void TakeChild(
        ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c,
        TakeChildCompleter::Sync& _completer) final {
      TakeChild(std::move(c.channel()), _completer);
    }

    // TODO(fxbug.dev/65212): Overriding this method is discouraged since it
    // uses raw channels instead of |fidl::ClientEnd| and |fidl::ServerEnd|.
    // Please move to overriding the typed channel overload above instead.
    virtual void TakeChild(::zx::channel c,
                           TakeChildCompleter::Sync& _completer) = 0;

    using TypedChannelInterface::TakeChildRequestCompleter;

    virtual void TakeChildRequest(
        ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r,
        TakeChildRequestCompleter::Sync& _completer) final {
      TakeChildRequest(std::move(r.channel()), _completer);
    }

    // TODO(fxbug.dev/65212): Overriding this method is discouraged since it
    // uses raw channels instead of |fidl::ClientEnd| and |fidl::ServerEnd|.
    // Please move to overriding the typed channel overload above instead.
    virtual void TakeChildRequest(
        ::zx::channel r, TakeChildRequestCompleter::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 ::fidl::DispatchResult TryDispatch(TypedChannelInterface* 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(TypedChannelInterface* impl,
                                         fidl_incoming_msg_t* msg,
                                         ::fidl::Transaction* txn);

  // Same as |Dispatch|, but takes a |void*| instead of
  // |TypedChannelInterface*|. 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<TypedChannelInterface*>(impl), msg, txn);
  }

  class EventSender;
  class WeakEventSender;
};

class Child final {
  Child() = delete;

 public:
  class EventHandlerInterface {
   public:
    EventHandlerInterface() = default;
    virtual ~EventHandlerInterface() = default;
  };

  // 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 or a
  // const reference to a
  // |fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child>|, avoiding
  // setting up a client.
  class Call final {
    Call() = delete;

   public:
  };

  class SyncClient final {
   public:
    SyncClient() = default;

    explicit SyncClient(::fidl::ClientEnd<Child> client_end)
        : client_end_(std::move(client_end)) {}

    ~SyncClient() = default;
    SyncClient(SyncClient&&) = default;
    SyncClient& operator=(SyncClient&&) = default;

    const ::fidl::ClientEnd<Child>& client_end() const { return client_end_; }
    ::fidl::ClientEnd<Child>& client_end() { return client_end_; }

    const ::zx::channel& channel() const { return client_end_.channel(); }
    ::zx::channel* mutable_channel() { return &client_end_.channel(); }

   private:
    ::fidl::ClientEnd<Child> client_end_;
  };

  class AsyncEventHandler;
  class ClientImpl;

  // Pure-virtual interface to be implemented by a server.
  // This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
  // and |fidl::ServerEnd<SomeProtocol>|).
  // TODO(fxbug.dev/65212): Rename this to |Interface| after all users have
  // migrated to the typed channels API.
  class TypedChannelInterface
      : public ::fidl::internal::IncomingMessageDispatcher {
   public:
    TypedChannelInterface() = default;
    virtual ~TypedChannelInterface() = default;

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

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

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

    // The marker protocol type within which this |Interface| class is defined.
    using TypedChannelInterface::_EnclosingProtocol;
  };

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

  // Same as |Dispatch|, but takes a |void*| instead of
  // |TypedChannelInterface*|. 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<TypedChannelInterface*>(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 {

class Parent::AsyncEventHandler : public Parent::EventHandlerInterface {
 public:
  AsyncEventHandler() = default;

  virtual void Unbound(::fidl::UnbindInfo info) {}
};

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(
      ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c);

  // Caller provides the backing storage for FIDL message via request buffer.
  ::fidl::Result TakeChild(
      ::fidl::BufferSpan _request_buffer,
      ::fidl::ClientEnd<::llcpp::fidl::test::protocolrequest::Child> c);

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Result TakeChildRequest(
      ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r);

  // Caller provides the backing storage for FIDL message via request buffer.
  ::fidl::Result TakeChildRequest(
      ::fidl::BufferSpan _request_buffer,
      ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> r);

  AsyncEventHandler* event_handler() const { return event_handler_.get(); }

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

  explicit ClientImpl(std::shared_ptr<AsyncEventHandler> event_handler)
      : event_handler_(std::move(event_handler)) {}

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

  std::shared_ptr<AsyncEventHandler> event_handler_;
};

// |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;

  explicit EventSender(
      ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Parent>
          server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::fidl::ServerEnd<Parent>& server_end() const { return server_end_; }
  ::fidl::ServerEnd<Parent>& server_end() { return server_end_; }

  const ::zx::channel& channel() const { return server_end_.channel(); }
  ::zx::channel& channel() { return server_end_.channel(); }

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

 private:
  ::fidl::ServerEnd<Parent> 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_;
};

class Child::AsyncEventHandler : public Child::EventHandlerInterface {
 public:
  AsyncEventHandler() = default;

  virtual void Unbound(::fidl::UnbindInfo info) {}
};

class Child::ClientImpl final : private ::fidl::internal::ClientBase {
 public:
  AsyncEventHandler* event_handler() const { return event_handler_.get(); }

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

  explicit ClientImpl(std::shared_ptr<AsyncEventHandler> event_handler)
      : event_handler_(std::move(event_handler)) {}

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

  std::shared_ptr<AsyncEventHandler> event_handler_;
};

// |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;

  explicit EventSender(
      ::fidl::ServerEnd<::llcpp::fidl::test::protocolrequest::Child> server_end)
      : server_end_(std::move(server_end)) {}

  // The underlying server channel endpoint, which may be replaced at run-time.
  const ::fidl::ServerEnd<Child>& server_end() const { return server_end_; }
  ::fidl::ServerEnd<Child>& server_end() { return server_end_; }

  const ::zx::channel& channel() const { return server_end_.channel(); }
  ::zx::channel& channel() { return server_end_.channel(); }

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

 private:
  ::fidl::ServerEnd<Child> 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
