// 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 transitivedependenciescompose {

class Top;

extern "C" const fidl_type_t
    fidl_test_transitivedependenciescompose_TopGetFooRequestTable;
extern "C" const fidl_type_t
    fidl_test_transitivedependenciescompose_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_transitivedependenciescompose_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 transitivedependenciescompose
}  // namespace test
}  // namespace fidl
}  // namespace llcpp

namespace fidl {

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

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

}  // namespace fidl

namespace llcpp {

namespace fidl {
namespace test {
namespace transitivedependenciescompose {

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 transitivedependenciescompose
}  // namespace test
}  // namespace fidl
}  // namespace llcpp
