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

#pragma once

#include <lib/fidl/internal.h>
#include <lib/fidl/llcpp/array.h>
#include <lib/fidl/llcpp/coding.h>
#include <lib/fidl/llcpp/envelope.h>
#include <lib/fidl/llcpp/errors.h>
#include <lib/fidl/llcpp/message.h>
#include <lib/fidl/llcpp/message_storage.h>
#include <lib/fidl/llcpp/object_view.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/fidl/llcpp/traits.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/fit/function.h>
#include <lib/stdcompat/optional.h>

#include <algorithm>
#include <cstddef>
#include <variant>
#ifdef __Fuchsia__
#include <lib/fidl/llcpp/client.h>
#include <lib/fidl/llcpp/client_end.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/result.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl/llcpp/server_end.h>
#include <lib/fidl/llcpp/service_handler_interface.h>
#include <lib/fidl/llcpp/sync_call.h>
#include <lib/fidl/llcpp/transaction.h>
#include <lib/fidl/llcpp/wire_messaging.h>
#include <lib/fidl/txn_header.h>
#include <lib/zx/channel.h>

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

namespace fidl_test_inheritancewithrecursivedecl {
class Parent;

class Child;

extern "C" const fidl_type_t
    fidl_test_inheritancewithrecursivedecl_ParentFirstRequestTable;

extern "C" const fidl_type_t
    fidl_test_inheritancewithrecursivedecl_ParentFirstResponseTable;

class Parent final {
  Parent() = delete;

 public:
  class First final {
    First() = delete;
  };
};
}  // namespace fidl_test_inheritancewithrecursivedecl
#ifdef __Fuchsia__

template <>
struct ::fidl::internal::ProtocolDetails<
    ::fidl_test_inheritancewithrecursivedecl::Parent> {};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
struct ::fidl::internal::WireDispatcher<
    ::fidl_test_inheritancewithrecursivedecl::Parent>
    final {
  WireDispatcher() = delete;
  static ::fidl::DispatchResult TryDispatch(
      ::fidl::WireInterface<::fidl_test_inheritancewithrecursivedecl::Parent>*
          impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
  static ::fidl::DispatchResult Dispatch(
      ::fidl::WireInterface<::fidl_test_inheritancewithrecursivedecl::Parent>*
          impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
};
#endif  // __Fuchsia__

template <>
struct ::fidl::WireRequest<
    ::fidl_test_inheritancewithrecursivedecl::Parent::First>
    final {
  FIDL_ALIGNDECL
  fidl_message_header_t _hdr;
  ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent> request;
  explicit WireRequest(
      zx_txid_t _txid,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request)
      : request(std::move(request)) {
    _InitHeader(_txid);
  }
  explicit WireRequest(zx_txid_t _txid) { _InitHeader(_txid); }

  static constexpr const fidl_type_t* Type =
      &::fidl_test_inheritancewithrecursivedecl::
          fidl_test_inheritancewithrecursivedecl_ParentFirstRequestTable;
  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<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request)
        : message_(_bytes, _byte_size, sizeof(WireRequest), handles_,
                   std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
      FIDL_ALIGNDECL WireRequest _request(_txid, std::move(request));
      message_.Encode<WireRequest>(&_request);
    }
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          WireRequest* request)
        : message_(bytes, byte_size, sizeof(WireRequest), handles_,
                   std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
      message_.Encode<WireRequest>(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  // __Fuchsia__
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }
#ifdef __Fuchsia__
    template <typename ChannelLike>
    void Write(ChannelLike&& client) {
      message_.Write(std::forward<ChannelLike>(client));
    }
#endif  // __Fuchsia__
   private:
    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<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request)
        : message_(bytes_.data(), bytes_.size(), _txid, std::move(request)) {}
    explicit OwnedEncodedMessage(WireRequest* request)
        : message_(bytes_.data(), bytes_.size(), 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  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() {
      return message_.GetOutgoingMessage();
    }
#ifdef __Fuchsia__
    template <typename ChannelLike>
    void Write(ChannelLike&& client) {
      message_.Write(std::forward<ChannelLike>(client));
    }
#endif  // __Fuchsia__
   private:
    ::fidl::internal::InlineMessageBuffer<24> bytes_;
    UnownedEncodedMessage message_;
  };

 public:
  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<WireRequest>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<WireRequest>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;
    ~DecodedMessage() {
      if (ok() && (PrimaryObject() != nullptr)) {
        PrimaryObject()->_CloseHandles();
      }
    }

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

 private:
  void _InitHeader(zx_txid_t _txid);
};
template <>
class ::fidl::WireResult<
    ::fidl_test_inheritancewithrecursivedecl::Parent::First>
    final : public ::fidl::Result {
 public:
  explicit WireResult(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
          _client,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);
  explicit WireResult(const ::fidl::Result& result) : ::fidl::Result(result) {}
  WireResult(WireResult&&) = delete;
  WireResult(const WireResult&) = delete;
  WireResult* operator=(WireResult&&) = delete;
  WireResult* operator=(const WireResult&) = delete;
  ~WireResult() = default;

 private:
};
template <>
class ::fidl::WireUnownedResult<
    ::fidl_test_inheritancewithrecursivedecl::Parent::First>
    final : public ::fidl::Result {
 public:
  explicit WireUnownedResult(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
          _client,
      uint8_t* _request_bytes, uint32_t _request_byte_capacity,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);
  explicit WireUnownedResult(const ::fidl::Result& result)
      : ::fidl::Result(result) {}
  WireUnownedResult(WireUnownedResult&&) = delete;
  WireUnownedResult(const WireUnownedResult&) = delete;
  WireUnownedResult* operator=(WireUnownedResult&&) = delete;
  WireUnownedResult* operator=(const WireUnownedResult&) = delete;
  ~WireUnownedResult() = default;
};

// Methods to make a sync FIDL call directly on an unowned channel or a
// const reference to a
// |fidl::ClientEnd<::fidl_test_inheritancewithrecursivedecl::Parent>|, avoiding
// setting up a client.
template <>
class ::fidl::internal::WireCaller<
    ::fidl_test_inheritancewithrecursivedecl::Parent>
    final {
 public:
  explicit WireCaller(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
          client_end)
      : client_end_(client_end) {}

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  static ::fidl::WireResult<
      ::fidl_test_inheritancewithrecursivedecl::Parent::First>
  First(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
          _client_end,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request) {
    return ::fidl::WireResult<
        ::fidl_test_inheritancewithrecursivedecl::Parent::First>(
        _client_end, std::move(request));
  }
  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::fidl_test_inheritancewithrecursivedecl::Parent::First>
  First(::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request) && {
    return ::fidl::WireResult<
        ::fidl_test_inheritancewithrecursivedecl::Parent::First>(
        client_end_, std::move(request));
  }

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  static ::fidl::WireUnownedResult<
      ::fidl_test_inheritancewithrecursivedecl::Parent::First>
  First(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
          _client_end,
      ::fidl::BufferSpan _request_buffer,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request) {
    return ::fidl::WireUnownedResult<
        ::fidl_test_inheritancewithrecursivedecl::Parent::First>(
        _client_end, _request_buffer.data, _request_buffer.capacity,
        std::move(request));
  }
  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::WireUnownedResult<
      ::fidl_test_inheritancewithrecursivedecl::Parent::First>
  First(::fidl::BufferSpan _request_buffer,
        ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request) && {
    return ::fidl::WireUnownedResult<
        ::fidl_test_inheritancewithrecursivedecl::Parent::First>(
        client_end_, _request_buffer.data, _request_buffer.capacity,
        std::move(request));
  }

 private:
  ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
      client_end_;
};
#ifdef __Fuchsia__

template <>
class ::fidl::internal::WireEventHandlerInterface<
    ::fidl_test_inheritancewithrecursivedecl::Parent> {
 public:
  WireEventHandlerInterface() = default;
  virtual ~WireEventHandlerInterface() = default;
};

template <>
class ::fidl::WireAsyncEventHandler<
    ::fidl_test_inheritancewithrecursivedecl::Parent>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::fidl_test_inheritancewithrecursivedecl::Parent> {
 public:
  WireAsyncEventHandler() = default;

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

template <>
class ::fidl::WireSyncEventHandler<
    ::fidl_test_inheritancewithrecursivedecl::Parent>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::fidl_test_inheritancewithrecursivedecl::Parent> {
 public:
  WireSyncEventHandler() = default;

  // Method called when an unknown event is found. This methods gives the status
  // which, in this case, is returned by HandleOneEvent.
  virtual zx_status_t Unknown() = 0;

  // Handle all possible events defined in this protocol.
  // Blocks to consume exactly one message from the channel, then call the
  // corresponding virtual method.
  ::fidl::Result HandleOneEvent(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
          client_end);
};
#endif  // __Fuchsia__

template <>
class ::fidl::WireSyncClient<::fidl_test_inheritancewithrecursivedecl::Parent>
    final {
 public:
  WireSyncClient() = default;

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

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

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

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

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::fidl_test_inheritancewithrecursivedecl::Parent::First>
  First(::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request) {
    return ::fidl::WireResult<
        ::fidl_test_inheritancewithrecursivedecl::Parent::First>(
        this->client_end(), std::move(request));
  }

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::WireUnownedResult<
      ::fidl_test_inheritancewithrecursivedecl::Parent::First>
  First(::fidl::BufferSpan _request_buffer,
        ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request) {
    return ::fidl::WireUnownedResult<
        ::fidl_test_inheritancewithrecursivedecl::Parent::First>(
        this->client_end(), _request_buffer.data, _request_buffer.capacity,
        std::move(request));
  }

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

// Pure-virtual interface to be implemented by a server.
// This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
// and |fidl::ServerEnd<SomeProtocol>|).
template <>
class ::fidl::WireInterface<::fidl_test_inheritancewithrecursivedecl::Parent>
    : public ::fidl::internal::IncomingMessageDispatcher {
 public:
  WireInterface() = default;
  virtual ~WireInterface() = default;

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

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

  virtual void First(
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
          request,
      FirstCompleter::Sync& _completer) = 0;

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

namespace fidl_test_inheritancewithrecursivedecl {
extern "C" const fidl_type_t
    fidl_test_inheritancewithrecursivedecl_ChildFirstRequestTable;

extern "C" const fidl_type_t
    fidl_test_inheritancewithrecursivedecl_ChildFirstResponseTable;

extern "C" const fidl_type_t
    fidl_test_inheritancewithrecursivedecl_ChildSecondRequestTable;

extern "C" const fidl_type_t
    fidl_test_inheritancewithrecursivedecl_ChildSecondResponseTable;

class Child final {
  Child() = delete;

 public:
  class First final {
    First() = delete;
  };
  class Second final {
    Second() = delete;
  };
};
}  // namespace fidl_test_inheritancewithrecursivedecl
#ifdef __Fuchsia__

template <>
struct ::fidl::internal::ProtocolDetails<
    ::fidl_test_inheritancewithrecursivedecl::Child> {};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
struct ::fidl::internal::WireDispatcher<
    ::fidl_test_inheritancewithrecursivedecl::Child>
    final {
  WireDispatcher() = delete;
  static ::fidl::DispatchResult TryDispatch(
      ::fidl::WireInterface<::fidl_test_inheritancewithrecursivedecl::Child>*
          impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
  static ::fidl::DispatchResult Dispatch(
      ::fidl::WireInterface<::fidl_test_inheritancewithrecursivedecl::Child>*
          impl,
      fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
};
#endif  // __Fuchsia__

template <>
struct ::fidl::WireRequest<
    ::fidl_test_inheritancewithrecursivedecl::Child::First>
    final {
  FIDL_ALIGNDECL
  fidl_message_header_t _hdr;
  ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent> request;
  explicit WireRequest(
      zx_txid_t _txid,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request)
      : request(std::move(request)) {
    _InitHeader(_txid);
  }
  explicit WireRequest(zx_txid_t _txid) { _InitHeader(_txid); }

  static constexpr const fidl_type_t* Type =
      &::fidl_test_inheritancewithrecursivedecl::
          fidl_test_inheritancewithrecursivedecl_ChildFirstRequestTable;
  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<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request)
        : message_(_bytes, _byte_size, sizeof(WireRequest), handles_,
                   std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
      FIDL_ALIGNDECL WireRequest _request(_txid, std::move(request));
      message_.Encode<WireRequest>(&_request);
    }
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          WireRequest* request)
        : message_(bytes, byte_size, sizeof(WireRequest), handles_,
                   std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
      message_.Encode<WireRequest>(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  // __Fuchsia__
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }
#ifdef __Fuchsia__
    template <typename ChannelLike>
    void Write(ChannelLike&& client) {
      message_.Write(std::forward<ChannelLike>(client));
    }
#endif  // __Fuchsia__
   private:
    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<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request)
        : message_(bytes_.data(), bytes_.size(), _txid, std::move(request)) {}
    explicit OwnedEncodedMessage(WireRequest* request)
        : message_(bytes_.data(), bytes_.size(), 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  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() {
      return message_.GetOutgoingMessage();
    }
#ifdef __Fuchsia__
    template <typename ChannelLike>
    void Write(ChannelLike&& client) {
      message_.Write(std::forward<ChannelLike>(client));
    }
#endif  // __Fuchsia__
   private:
    ::fidl::internal::InlineMessageBuffer<24> bytes_;
    UnownedEncodedMessage message_;
  };

 public:
  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<WireRequest>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<WireRequest>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;
    ~DecodedMessage() {
      if (ok() && (PrimaryObject() != nullptr)) {
        PrimaryObject()->_CloseHandles();
      }
    }

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

 private:
  void _InitHeader(zx_txid_t _txid);
};
template <>
struct ::fidl::WireRequest<
    ::fidl_test_inheritancewithrecursivedecl::Child::Second>
    final {
  FIDL_ALIGNDECL
  fidl_message_header_t _hdr;
  ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent> request;
  explicit WireRequest(
      zx_txid_t _txid,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request)
      : request(std::move(request)) {
    _InitHeader(_txid);
  }
  explicit WireRequest(zx_txid_t _txid) { _InitHeader(_txid); }

  static constexpr const fidl_type_t* Type =
      &::fidl_test_inheritancewithrecursivedecl::
          fidl_test_inheritancewithrecursivedecl_ChildSecondRequestTable;
  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<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request)
        : message_(_bytes, _byte_size, sizeof(WireRequest), handles_,
                   std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
      FIDL_ALIGNDECL WireRequest _request(_txid, std::move(request));
      message_.Encode<WireRequest>(&_request);
    }
    UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                          WireRequest* request)
        : message_(bytes, byte_size, sizeof(WireRequest), handles_,
                   std::min(ZX_CHANNEL_MAX_MSG_HANDLES, MaxNumHandles), 0) {
      message_.Encode<WireRequest>(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  // __Fuchsia__
    bool ok() const { return message_.status() == ZX_OK; }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }
#ifdef __Fuchsia__
    template <typename ChannelLike>
    void Write(ChannelLike&& client) {
      message_.Write(std::forward<ChannelLike>(client));
    }
#endif  // __Fuchsia__
   private:
    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<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request)
        : message_(bytes_.data(), bytes_.size(), _txid, std::move(request)) {}
    explicit OwnedEncodedMessage(WireRequest* request)
        : message_(bytes_.data(), bytes_.size(), 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  // __Fuchsia__
    bool ok() const { return message_.ok(); }
    const char* error() const { return message_.error(); }

    ::fidl::OutgoingMessage& GetOutgoingMessage() {
      return message_.GetOutgoingMessage();
    }
#ifdef __Fuchsia__
    template <typename ChannelLike>
    void Write(ChannelLike&& client) {
      message_.Write(std::forward<ChannelLike>(client));
    }
#endif  // __Fuchsia__
   private:
    ::fidl::internal::InlineMessageBuffer<24> bytes_;
    UnownedEncodedMessage message_;
  };

 public:
  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<WireRequest>();
    }
    DecodedMessage(fidl_incoming_msg_t* msg)
        : ::fidl::internal::IncomingMessage(msg) {
      Decode<WireRequest>();
    }
    DecodedMessage(const DecodedMessage&) = delete;
    DecodedMessage(DecodedMessage&&) = delete;
    DecodedMessage* operator=(const DecodedMessage&) = delete;
    DecodedMessage* operator=(DecodedMessage&&) = delete;
    ~DecodedMessage() {
      if (ok() && (PrimaryObject() != nullptr)) {
        PrimaryObject()->_CloseHandles();
      }
    }

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

 private:
  void _InitHeader(zx_txid_t _txid);
};
template <>
class ::fidl::WireResult<::fidl_test_inheritancewithrecursivedecl::Child::First>
    final : public ::fidl::Result {
 public:
  explicit WireResult(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          _client,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);
  explicit WireResult(const ::fidl::Result& result) : ::fidl::Result(result) {}
  WireResult(WireResult&&) = delete;
  WireResult(const WireResult&) = delete;
  WireResult* operator=(WireResult&&) = delete;
  WireResult* operator=(const WireResult&) = delete;
  ~WireResult() = default;

 private:
};
template <>
class ::fidl::WireUnownedResult<
    ::fidl_test_inheritancewithrecursivedecl::Child::First>
    final : public ::fidl::Result {
 public:
  explicit WireUnownedResult(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          _client,
      uint8_t* _request_bytes, uint32_t _request_byte_capacity,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);
  explicit WireUnownedResult(const ::fidl::Result& result)
      : ::fidl::Result(result) {}
  WireUnownedResult(WireUnownedResult&&) = delete;
  WireUnownedResult(const WireUnownedResult&) = delete;
  WireUnownedResult* operator=(WireUnownedResult&&) = delete;
  WireUnownedResult* operator=(const WireUnownedResult&) = delete;
  ~WireUnownedResult() = default;
};
template <>
class ::fidl::WireResult<
    ::fidl_test_inheritancewithrecursivedecl::Child::Second>
    final : public ::fidl::Result {
 public:
  explicit WireResult(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          _client,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);
  explicit WireResult(const ::fidl::Result& result) : ::fidl::Result(result) {}
  WireResult(WireResult&&) = delete;
  WireResult(const WireResult&) = delete;
  WireResult* operator=(WireResult&&) = delete;
  WireResult* operator=(const WireResult&) = delete;
  ~WireResult() = default;

 private:
};
template <>
class ::fidl::WireUnownedResult<
    ::fidl_test_inheritancewithrecursivedecl::Child::Second>
    final : public ::fidl::Result {
 public:
  explicit WireUnownedResult(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          _client,
      uint8_t* _request_bytes, uint32_t _request_byte_capacity,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);
  explicit WireUnownedResult(const ::fidl::Result& result)
      : ::fidl::Result(result) {}
  WireUnownedResult(WireUnownedResult&&) = delete;
  WireUnownedResult(const WireUnownedResult&) = delete;
  WireUnownedResult* operator=(WireUnownedResult&&) = delete;
  WireUnownedResult* operator=(const WireUnownedResult&) = delete;
  ~WireUnownedResult() = default;
};

// Methods to make a sync FIDL call directly on an unowned channel or a
// const reference to a
// |fidl::ClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>|, avoiding
// setting up a client.
template <>
class ::fidl::internal::WireCaller<
    ::fidl_test_inheritancewithrecursivedecl::Child>
    final {
 public:
  explicit WireCaller(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          client_end)
      : client_end_(client_end) {}

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  static ::fidl::WireResult<
      ::fidl_test_inheritancewithrecursivedecl::Child::First>
  First(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          _client_end,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request) {
    return ::fidl::WireResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::First>(
        _client_end, std::move(request));
  }
  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::fidl_test_inheritancewithrecursivedecl::Child::First>
  First(::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request) && {
    return ::fidl::WireResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::First>(
        client_end_, std::move(request));
  }

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  static ::fidl::WireUnownedResult<
      ::fidl_test_inheritancewithrecursivedecl::Child::First>
  First(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          _client_end,
      ::fidl::BufferSpan _request_buffer,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request) {
    return ::fidl::WireUnownedResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::First>(
        _client_end, _request_buffer.data, _request_buffer.capacity,
        std::move(request));
  }
  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::WireUnownedResult<
      ::fidl_test_inheritancewithrecursivedecl::Child::First>
  First(::fidl::BufferSpan _request_buffer,
        ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request) && {
    return ::fidl::WireUnownedResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::First>(
        client_end_, _request_buffer.data, _request_buffer.capacity,
        std::move(request));
  }

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  static ::fidl::WireResult<
      ::fidl_test_inheritancewithrecursivedecl::Child::Second>
  Second(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          _client_end,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request) {
    return ::fidl::WireResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::Second>(
        _client_end, std::move(request));
  }
  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::fidl_test_inheritancewithrecursivedecl::Child::Second>
  Second(::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
             request) && {
    return ::fidl::WireResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::Second>(
        client_end_, std::move(request));
  }

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  static ::fidl::WireUnownedResult<
      ::fidl_test_inheritancewithrecursivedecl::Child::Second>
  Second(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          _client_end,
      ::fidl::BufferSpan _request_buffer,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request) {
    return ::fidl::WireUnownedResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::Second>(
        _client_end, _request_buffer.data, _request_buffer.capacity,
        std::move(request));
  }
  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::WireUnownedResult<
      ::fidl_test_inheritancewithrecursivedecl::Child::Second>
  Second(::fidl::BufferSpan _request_buffer,
         ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
             request) && {
    return ::fidl::WireUnownedResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::Second>(
        client_end_, _request_buffer.data, _request_buffer.capacity,
        std::move(request));
  }

 private:
  ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
      client_end_;
};
#ifdef __Fuchsia__

template <>
class ::fidl::internal::WireEventHandlerInterface<
    ::fidl_test_inheritancewithrecursivedecl::Child> {
 public:
  WireEventHandlerInterface() = default;
  virtual ~WireEventHandlerInterface() = default;
};

template <>
class ::fidl::WireAsyncEventHandler<
    ::fidl_test_inheritancewithrecursivedecl::Child>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::fidl_test_inheritancewithrecursivedecl::Child> {
 public:
  WireAsyncEventHandler() = default;

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

template <>
class ::fidl::WireSyncEventHandler<
    ::fidl_test_inheritancewithrecursivedecl::Child>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::fidl_test_inheritancewithrecursivedecl::Child> {
 public:
  WireSyncEventHandler() = default;

  // Method called when an unknown event is found. This methods gives the status
  // which, in this case, is returned by HandleOneEvent.
  virtual zx_status_t Unknown() = 0;

  // Handle all possible events defined in this protocol.
  // Blocks to consume exactly one message from the channel, then call the
  // corresponding virtual method.
  ::fidl::Result HandleOneEvent(
      ::fidl::UnownedClientEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          client_end);
};
#endif  // __Fuchsia__

template <>
class ::fidl::WireSyncClient<::fidl_test_inheritancewithrecursivedecl::Child>
    final {
 public:
  WireSyncClient() = default;

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

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

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

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

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::fidl_test_inheritancewithrecursivedecl::Child::First>
  First(::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request) {
    return ::fidl::WireResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::First>(
        this->client_end(), std::move(request));
  }

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::WireUnownedResult<
      ::fidl_test_inheritancewithrecursivedecl::Child::First>
  First(::fidl::BufferSpan _request_buffer,
        ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
            request) {
    return ::fidl::WireUnownedResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::First>(
        this->client_end(), _request_buffer.data, _request_buffer.capacity,
        std::move(request));
  }

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::fidl_test_inheritancewithrecursivedecl::Child::Second>
  Second(::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
             request) {
    return ::fidl::WireResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::Second>(
        this->client_end(), std::move(request));
  }

  // Caller provides the backing storage for FIDL message via request and
  // response buffers.
  ::fidl::WireUnownedResult<
      ::fidl_test_inheritancewithrecursivedecl::Child::Second>
  Second(::fidl::BufferSpan _request_buffer,
         ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
             request) {
    return ::fidl::WireUnownedResult<
        ::fidl_test_inheritancewithrecursivedecl::Child::Second>(
        this->client_end(), _request_buffer.data, _request_buffer.capacity,
        std::move(request));
  }

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

// Pure-virtual interface to be implemented by a server.
// This interface uses typed channels (i.e. |fidl::ClientEnd<SomeProtocol>|
// and |fidl::ServerEnd<SomeProtocol>|).
template <>
class ::fidl::WireInterface<::fidl_test_inheritancewithrecursivedecl::Child>
    : public ::fidl::internal::IncomingMessageDispatcher {
 public:
  WireInterface() = default;
  virtual ~WireInterface() = default;

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

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

  virtual void First(
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
          request,
      FirstCompleter::Sync& _completer) = 0;

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

  virtual void Second(
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
          request,
      SecondCompleter::Sync& _completer) = 0;

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

namespace fidl {

template <>
struct IsFidlType<::fidl::WireRequest<
    ::fidl_test_inheritancewithrecursivedecl::Parent::First>>
    : public std::true_type {};
template <>
struct IsFidlMessage<::fidl::WireRequest<
    ::fidl_test_inheritancewithrecursivedecl::Parent::First>>
    : public std::true_type {};
static_assert(
    sizeof(::fidl::WireRequest<
           ::fidl_test_inheritancewithrecursivedecl::Parent::First>) ==
    ::fidl::WireRequest<
        ::fidl_test_inheritancewithrecursivedecl::Parent::First>::PrimarySize);
static_assert(
    offsetof(::fidl::WireRequest<
                 ::fidl_test_inheritancewithrecursivedecl::Parent::First>,
             request) == 16);

template <>
struct IsFidlType<
    ::fidl::WireRequest<::fidl_test_inheritancewithrecursivedecl::Child::First>>
    : public std::true_type {};
template <>
struct IsFidlMessage<
    ::fidl::WireRequest<::fidl_test_inheritancewithrecursivedecl::Child::First>>
    : public std::true_type {};
static_assert(
    sizeof(::fidl::WireRequest<
           ::fidl_test_inheritancewithrecursivedecl::Child::First>) ==
    ::fidl::WireRequest<
        ::fidl_test_inheritancewithrecursivedecl::Child::First>::PrimarySize);
static_assert(
    offsetof(::fidl::WireRequest<
                 ::fidl_test_inheritancewithrecursivedecl::Child::First>,
             request) == 16);

template <>
struct IsFidlType<::fidl::WireRequest<
    ::fidl_test_inheritancewithrecursivedecl::Child::Second>>
    : public std::true_type {};
template <>
struct IsFidlMessage<::fidl::WireRequest<
    ::fidl_test_inheritancewithrecursivedecl::Child::Second>>
    : public std::true_type {};
static_assert(
    sizeof(::fidl::WireRequest<
           ::fidl_test_inheritancewithrecursivedecl::Child::Second>) ==
    ::fidl::WireRequest<
        ::fidl_test_inheritancewithrecursivedecl::Child::Second>::PrimarySize);
static_assert(
    offsetof(::fidl::WireRequest<
                 ::fidl_test_inheritancewithrecursivedecl::Child::Second>,
             request) == 16);

#ifdef __Fuchsia__
}  // namespace fidl
template <>
class ::fidl::internal::WireClientImpl<
    ::fidl_test_inheritancewithrecursivedecl::Parent>
    final : private ::fidl::internal::ClientBase {
 public:
  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Result First(
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);

  // Caller provides the backing storage for FIDL message via request buffer.
  ::fidl::Result First(
      ::fidl::BufferSpan _request_buffer,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);

  ::fidl::WireAsyncEventHandler<
      ::fidl_test_inheritancewithrecursivedecl::Parent>*
  event_handler() const {
    return event_handler_.get();
  }

 private:
  friend class ::fidl::Client<::fidl_test_inheritancewithrecursivedecl::Parent>;
  friend class ::fidl::internal::ControlBlock<
      ::fidl_test_inheritancewithrecursivedecl::Parent>;

  explicit WireClientImpl(std::shared_ptr<::fidl::WireAsyncEventHandler<
                              ::fidl_test_inheritancewithrecursivedecl::Parent>>
                              event_handler)
      : event_handler_(std::move(event_handler)) {}

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

  std::shared_ptr<::fidl::WireAsyncEventHandler<
      ::fidl_test_inheritancewithrecursivedecl::Parent>>
      event_handler_;
};
namespace fidl {
#endif  // __Fuchsia__

}  // namespace fidl
#ifdef __Fuchsia__
// |EventSender| owns a server endpoint of a channel speaking
// the Parent protocol, and can send events in that protocol.
template <>
class ::fidl::WireEventSender<
    ::fidl_test_inheritancewithrecursivedecl::Parent> {
 public:
  // Constructs an event sender with an invalid channel.
  WireEventSender() = default;

  explicit WireEventSender(
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>
          server_end)
      : server_end_(std::move(server_end)) {}

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

template <>
class ::fidl::internal::WireWeakEventSender<
    ::fidl_test_inheritancewithrecursivedecl::Parent> {
 public:
 private:
  friend class ::fidl::ServerBindingRef<
      ::fidl_test_inheritancewithrecursivedecl::Parent>;

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

  std::weak_ptr<::fidl::internal::AsyncServerBinding<
      ::fidl_test_inheritancewithrecursivedecl::Parent>>
      binding_;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
class ::fidl::internal::WireClientImpl<
    ::fidl_test_inheritancewithrecursivedecl::Child>
    final : private ::fidl::internal::ClientBase {
 public:
  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Result First(
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);

  // Caller provides the backing storage for FIDL message via request buffer.
  ::fidl::Result First(
      ::fidl::BufferSpan _request_buffer,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);

  // Allocates 24 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Result Second(
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);

  // Caller provides the backing storage for FIDL message via request buffer.
  ::fidl::Result Second(
      ::fidl::BufferSpan _request_buffer,
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Parent>&&
          request);

  ::fidl::WireAsyncEventHandler<
      ::fidl_test_inheritancewithrecursivedecl::Child>*
  event_handler() const {
    return event_handler_.get();
  }

 private:
  friend class ::fidl::Client<::fidl_test_inheritancewithrecursivedecl::Child>;
  friend class ::fidl::internal::ControlBlock<
      ::fidl_test_inheritancewithrecursivedecl::Child>;

  explicit WireClientImpl(std::shared_ptr<::fidl::WireAsyncEventHandler<
                              ::fidl_test_inheritancewithrecursivedecl::Child>>
                              event_handler)
      : event_handler_(std::move(event_handler)) {}

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

  std::shared_ptr<::fidl::WireAsyncEventHandler<
      ::fidl_test_inheritancewithrecursivedecl::Child>>
      event_handler_;
};
#endif  // __Fuchsia__

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

  explicit WireEventSender(
      ::fidl::ServerEnd<::fidl_test_inheritancewithrecursivedecl::Child>
          server_end)
      : server_end_(std::move(server_end)) {}

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

template <>
class ::fidl::internal::WireWeakEventSender<
    ::fidl_test_inheritancewithrecursivedecl::Child> {
 public:
 private:
  friend class ::fidl::ServerBindingRef<
      ::fidl_test_inheritancewithrecursivedecl::Child>;

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

  std::weak_ptr<::fidl::internal::AsyncServerBinding<
      ::fidl_test_inheritancewithrecursivedecl::Child>>
      binding_;
};
#endif  // __Fuchsia__
