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

#pragma once

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

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

namespace llcpp {

namespace fidl {
namespace test {
namespace foreigntypeinresponseusedthroughcompose {

class Top;

extern "C" const fidl_type_t
    fidl_test_foreigntypeinresponseusedthroughcompose_TopGetFooRequestTable;
extern "C" const fidl_type_t
    fidl_test_foreigntypeinresponseusedthroughcompose_TopGetFooResponseTable;

class Top final {
  Top() = delete;

 public:
  struct GetFooResponse final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    ::llcpp::bottom::Foo foo;
    explicit GetFooResponse(::llcpp::bottom::Foo& foo) : foo(std::move(foo)) {
      _InitHeader();
    }
    GetFooResponse() { _InitHeader(); }

    static constexpr const fidl_type_t* Type =
        &fidl_test_foreigntypeinresponseusedthroughcompose_TopGetFooResponseTable;
    static constexpr uint32_t MaxNumHandles = 0;
    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;

    class UnownedEncodedMessage final {
     public:
      UnownedEncodedMessage(uint8_t* _bytes, uint32_t _byte_size,
                            ::llcpp::bottom::Foo& foo)
          : message_(_bytes, _byte_size, sizeof(GetFooResponse), nullptr, 0,
                     0) {
        FIDL_ALIGNDECL GetFooResponse _response{foo};
        message_.LinearizeAndEncode<GetFooResponse>(&_response);
      }
      UnownedEncodedMessage(uint8_t* bytes, uint32_t byte_size,
                            GetFooResponse* response)
          : message_(bytes, byte_size, sizeof(GetFooResponse), nullptr, 0, 0) {
        message_.LinearizeAndEncode<GetFooResponse>(response);
      }
      UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
      UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
      UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

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

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

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

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

    class OwnedEncodedMessage final {
     public:
      explicit OwnedEncodedMessage(::llcpp::bottom::Foo& foo)
          : message_(bytes_, sizeof(bytes_), foo) {}
      explicit OwnedEncodedMessage(GetFooResponse* response)
          : message_(bytes_, sizeof(bytes_), response) {}
      OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
      OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
      OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

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

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

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

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

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

      GetFooResponse* PrimaryObject() {
        ZX_DEBUG_ASSERT(ok());
        return reinterpret_cast<GetFooResponse*>(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) {
        Init(outgoing_message, nullptr, 0);
        if (ok()) {
          Decode<GetFooResponse>();
        }
      }
    };

   private:
    void _InitHeader();
  };
  struct GetFooRequest final {
    FIDL_ALIGNDECL
    fidl_message_header_t _hdr;
    explicit GetFooRequest(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 = GetFooResponse;

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

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

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

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

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

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

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

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

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

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

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

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

   private:
    void _InitHeader(zx_txid_t _txid);
  };

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

   public:
    class GetFoo final : public ::fidl::Result {
     public:
      explicit GetFoo(zx_handle_t _client);
      GetFoo(zx_handle_t _client, zx_time_t _deadline);
      explicit GetFoo(const ::fidl::Result& result) : ::fidl::Result(result) {}
      GetFoo(GetFoo&&) = delete;
      GetFoo(const GetFoo&) = delete;
      GetFoo* operator=(GetFoo&&) = delete;
      GetFoo* operator=(const GetFoo&) = delete;
      ~GetFoo() = default;

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

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

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

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

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

  // 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 GetFoo final : public ::fidl::Result {
     public:
      explicit GetFoo(zx_handle_t _client, uint8_t* _response_bytes,
                      uint32_t _response_byte_capacity);
      explicit GetFoo(const ::fidl::Result& result) : ::fidl::Result(result) {}
      GetFoo(GetFoo&&) = delete;
      GetFoo(const GetFoo&) = delete;
      GetFoo* operator=(GetFoo&&) = delete;
      GetFoo* operator=(const GetFoo&) = delete;
      ~GetFoo() = default;

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

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

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

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

     private:
      uint8_t* bytes_;
    };
  };

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

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

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

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

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

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

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

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

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

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

  struct AsyncEventHandlers;
  class GetFooResponseContext;
  class ClientImpl;

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

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

    class GetFooCompleterBase : 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(::llcpp::bottom::Foo foo);
      ::fidl::Result Reply(::fidl::BufferSpan _buffer,
                           ::llcpp::bottom::Foo foo);

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

    using GetFooCompleter = ::fidl::Completer<GetFooCompleterBase>;

    virtual void GetFoo(GetFooCompleter::Sync& _completer) = 0;

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

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

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

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

  class EventSender;
  class WeakEventSender;
};

}  // namespace foreigntypeinresponseusedthroughcompose
}  // namespace test
}  // namespace fidl
}  // namespace llcpp

namespace fidl {

template <>
struct IsFidlType<::llcpp::fidl::test::foreigntypeinresponseusedthroughcompose::
                      Top::GetFooRequest> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::foreigntypeinresponseusedthroughcompose::Top::
        GetFooRequest> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::foreigntypeinresponseusedthroughcompose::Top::
               GetFooRequest) ==
    ::llcpp::fidl::test::foreigntypeinresponseusedthroughcompose::Top::
        GetFooRequest::PrimarySize);

template <>
struct IsFidlType<::llcpp::fidl::test::foreigntypeinresponseusedthroughcompose::
                      Top::GetFooResponse> : public std::true_type {};
template <>
struct IsFidlMessage<
    ::llcpp::fidl::test::foreigntypeinresponseusedthroughcompose::Top::
        GetFooResponse> : public std::true_type {};
static_assert(
    sizeof(::llcpp::fidl::test::foreigntypeinresponseusedthroughcompose::Top::
               GetFooResponse) ==
    ::llcpp::fidl::test::foreigntypeinresponseusedthroughcompose::Top::
        GetFooResponse::PrimarySize);
static_assert(
    offsetof(::llcpp::fidl::test::foreigntypeinresponseusedthroughcompose::Top::
                 GetFooResponse,
             foo) == 16);

}  // namespace fidl

namespace llcpp {

namespace fidl {
namespace test {
namespace foreigntypeinresponseusedthroughcompose {

struct Top::AsyncEventHandlers {};

class Top::GetFooResponseContext : public ::fidl::internal::ResponseContext {
 public:
  GetFooResponseContext();

  virtual void OnReply(Top::GetFooResponse* message) = 0;

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

class Top::ClientImpl final : private ::fidl::internal::ClientBase {
 public:
  // Asynchronous variant of |Top.GetFoo()|. Allocates 16 bytes of request
  // buffer on the stack. The callback is stored on the heap.
  ::fidl::Result GetFoo(::fit::callback<void(GetFooResponse* response)> _cb);
  // Asynchronous variant of |Top.GetFoo()|. 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 GetFoo(GetFooResponseContext* _context);
  // Synchronous variant of |Top.GetFoo()|. Allocates 40 bytes of message buffer
  // on the stack. No heap allocation necessary.
  ResultOf::GetFoo GetFoo_Sync();

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

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

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

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

  AsyncEventHandlers handlers_;
};

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

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

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

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

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

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

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

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

}  // namespace foreigntypeinresponseusedthroughcompose
}  // namespace test
}  // namespace fidl
}  // namespace llcpp
