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

#pragma once

#include <fidl/test.service/cpp/markers.h>
#include <fidl/test.service/cpp/wire_types.h>
#include <lib/fidl/llcpp/wire_messaging.h>

#ifdef __Fuchsia__

#include <lib/fidl/llcpp/client.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl/llcpp/service_handler_interface.h>
#include <lib/fidl/llcpp/sync_call.h>

#endif  // __Fuchsia__

namespace test_service {
class SecondProtocol;

class FirstProtocol;

class SingleMemberService;

class MultiHomogeneousMemberService;

class MultiHeterogeneousMemberService;

class EmptyService;

}  // namespace test_service
template <>
struct ::fidl::internal::WireOrdinal<
    ::test_service::SecondProtocol::MethodOnSecond>
    final {
  static constexpr uint64_t value = 8121179205110225988lu;
};

namespace test_service {}  // namespace test_service
#ifdef __Fuchsia__

template <>
struct ::fidl::internal::ProtocolDetails<::test_service::SecondProtocol> {};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
struct ::fidl::internal::WireServerDispatcher<::test_service::SecondProtocol>
    final {
  WireServerDispatcher() = delete;
  static ::fidl::DispatchResult TryDispatch(
      ::fidl::WireServer<::test_service::SecondProtocol>* impl,
      ::fidl::IncomingMessage& msg,
      internal::IncomingTransportContext transport_context,
      ::fidl::Transaction* txn);
  static void Dispatch(::fidl::WireServer<::test_service::SecondProtocol>* impl,
                       ::fidl::IncomingMessage&& msg,
                       internal::IncomingTransportContext transport_context,
                       ::fidl::Transaction* txn);

 private:
  static const ::fidl::internal::MethodEntry entries_[];
  static const ::fidl::internal::MethodEntry* entries_end_;
};
#endif  // __Fuchsia__

template <>
struct ::fidl::WireRequest<::test_service::SecondProtocol::MethodOnSecond>
    final {
  WireRequest() = default;
};

template <>
struct ::fidl::internal::TransactionalRequest<
    ::test_service::SecondProtocol::MethodOnSecond>
    final {
  FIDL_ALIGNDECL
  fidl_message_header_t header;

  TransactionalRequest() { _InitHeader(); }

 private:
  void _InitHeader();
};

namespace fidl {

template <>
struct IsFidlType<::fidl::internal::TransactionalRequest<
    ::test_service::SecondProtocol::MethodOnSecond>> : public std::true_type {};
template <>
struct IsFidlType<
    ::fidl::WireRequest<::test_service::SecondProtocol::MethodOnSecond>>
    : public std::true_type {};
template <>
struct IsFidlTransactionalMessage<::fidl::internal::TransactionalRequest<
    ::test_service::SecondProtocol::MethodOnSecond>> : public std::true_type {};
template <>
struct IsFidlTransactionalMessage<
    ::fidl::WireRequest<::test_service::SecondProtocol::MethodOnSecond>>
    : public std::false_type {};

template <>
struct TypeTraits<::fidl::internal::TransactionalRequest<
    ::test_service::SecondProtocol::MethodOnSecond>> {
  static constexpr const fidl_type_t* kType = nullptr;
  static constexpr uint32_t kMaxNumHandles = 0;
  static constexpr uint32_t kPrimarySize =
      FIDL_ALIGN(0 + sizeof(fidl_message_header_t));
  static constexpr uint32_t kPrimarySizeV1 =
      FIDL_ALIGN(0 + sizeof(fidl_message_header_t));
  static constexpr uint32_t kMaxOutOfLine = 0;
  static constexpr uint32_t kMaxOutOfLineV1 = 0;
  static constexpr bool kHasFlexibleEnvelope = false;
  static constexpr bool kHasPointer = false;
  static constexpr ::fidl::internal::TransactionalMessageKind kMessageKind =
      ::fidl::internal::TransactionalMessageKind::kRequest;
};

static_assert(
    sizeof(::fidl::internal::TransactionalRequest<
           ::test_service::SecondProtocol::MethodOnSecond>) ==
    TypeTraits<::fidl::internal::TransactionalRequest<
        ::test_service::SecondProtocol::MethodOnSecond>>::kPrimarySize);
static_assert(offsetof(::fidl::internal::TransactionalRequest<
                           ::test_service::SecondProtocol::MethodOnSecond>,
                       header) == 0);

template <>
struct TypeTraits<
    ::fidl::WireRequest<::test_service::SecondProtocol::MethodOnSecond>> {
  static constexpr const fidl_type_t* kType = nullptr;
  static constexpr uint32_t kMaxNumHandles = 0;
  static constexpr uint32_t kPrimarySize = 0;
  static constexpr uint32_t kPrimarySizeV1 = 0;
  static constexpr uint32_t kMaxOutOfLine = 0;
  static constexpr uint32_t kMaxOutOfLineV1 = 0;
  static constexpr bool kHasFlexibleEnvelope = false;
  static constexpr bool kHasPointer = false;
  static constexpr ::fidl::internal::TransactionalMessageKind kMessageKind =
      ::fidl::internal::TransactionalMessageKind::kRequest;
};

}  // namespace fidl
namespace test_service {
#ifdef __Fuchsia__
}  // namespace test_service
template <>
class [[nodiscard]] ::fidl::WireResult<
    ::test_service::SecondProtocol::MethodOnSecond>
    final : public ::fidl::Status {
 public:
  WireResult(::fidl::UnownedClientEnd<::test_service::SecondProtocol> client,
             ::fidl::internal::TransactionalRequest<
                 ::test_service::SecondProtocol::MethodOnSecond>* request);
  explicit WireResult(const ::fidl::Status& result) : ::fidl::Status(result) {}
  WireResult(WireResult&&) = delete;
  WireResult(const WireResult&) = delete;
  WireResult* operator=(WireResult&&) = delete;
  WireResult* operator=(const WireResult&) = delete;
  ~WireResult() = default;

 private:
};
template <>
class [[nodiscard]] ::fidl::WireUnownedResult<
    ::test_service::SecondProtocol::MethodOnSecond>
    final : public ::fidl::Status {
 public:
  explicit WireUnownedResult(
      ::fidl::UnownedClientEnd<::test_service::SecondProtocol> client_end,
      ::fidl::internal::AnyBufferAllocator& allocator,
      ::fidl::internal::TransactionalRequest<
          ::test_service::SecondProtocol::MethodOnSecond>* request);
  explicit WireUnownedResult(const ::fidl::Status& result)
      : ::fidl::Status(result) {}
  WireUnownedResult(WireUnownedResult&&) = delete;
  WireUnownedResult(const WireUnownedResult&) = delete;
  WireUnownedResult* operator=(WireUnownedResult&&) = delete;
  WireUnownedResult* operator=(const WireUnownedResult&) = delete;
  ~WireUnownedResult() = default;
};
template <>
class ::fidl::internal::WireEventHandlerInterface<
    ::test_service::SecondProtocol> {
 public:
  WireEventHandlerInterface() = default;
  virtual ~WireEventHandlerInterface() = default;
};

template <>
class ::fidl::WireAsyncEventHandler<::test_service::SecondProtocol>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::test_service::SecondProtocol>,
      public ::fidl::internal::AsyncEventHandler {
 public:
  WireAsyncEventHandler() = default;
};

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

  // Handle all possible events defined in this protocol.
  // Blocks to consume exactly one message from the channel, then call the
  // corresponding virtual method.
  ::fidl::Status HandleOneEvent(
      ::fidl::UnownedClientEnd<::test_service::SecondProtocol> client_end);

 private:
  [[maybe_unused]] bool got_transitional_ = false;
};

template <>
class ::fidl::internal::WireEventDispatcher<::test_service::SecondProtocol>
    final : public ::fidl::internal::IncomingEventDispatcher<
                ::fidl::WireAsyncEventHandler<::test_service::SecondProtocol>> {
 public:
  explicit WireEventDispatcher(
      ::fidl::WireAsyncEventHandler<::test_service::SecondProtocol>*
          event_handler)
      : IncomingEventDispatcher(event_handler) {}

 private:
  std::optional<::fidl::UnbindInfo> DispatchEvent(
      ::fidl::IncomingMessage& msg,
      ::fidl::internal::IncomingTransportContext transport_context) override;
};

// Methods to make a sync FIDL call directly on an unowned handle or a
// const reference to a |fidl::ClientEnd<::test_service::SecondProtocol>|,
// avoiding setting up a client.
template <>
class ::fidl::internal::WireSyncClientImpl<::test_service::SecondProtocol> final
    : public ::fidl::internal::SyncEndpointManagedVeneer<
          ::fidl::internal::WireSyncClientImpl<
              ::test_service::SecondProtocol>> {
 public:
  // Allocates 32 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::test_service::SecondProtocol::MethodOnSecond>
  MethodOnSecond() {
    ::fidl::internal::TransactionalRequest<
        ::test_service::SecondProtocol::MethodOnSecond>
        _request{};
    return ::fidl::WireResult<::test_service::SecondProtocol::MethodOnSecond>(
        _client_end(), &_request);
  }

 private:
  ::fidl::UnownedClientEnd<::test_service::SecondProtocol> _client_end() const {
    return ::fidl::UnownedClientEnd<::test_service::SecondProtocol>(
        _transport().get<::fidl::internal::ChannelTransport>());
  }
};

template <>
class ::fidl::internal::WireSyncBufferClientImpl<::test_service::SecondProtocol>
    final : public ::fidl::internal::SyncEndpointBufferVeneer<
                ::fidl::internal::WireSyncBufferClientImpl<
                    ::test_service::SecondProtocol>> {
 public:
  // Caller provides the backing storage for FIDL message via an argument to
  // `.buffer()`.
  ::fidl::WireUnownedResult<::test_service::SecondProtocol::MethodOnSecond>
  MethodOnSecond() {
    ::fidl::internal::TransactionalRequest<
        ::test_service::SecondProtocol::MethodOnSecond>
        _request{};
    return ::fidl::WireUnownedResult<
        ::test_service::SecondProtocol::MethodOnSecond>(
        _client_end(), _allocator(), &_request);
  }

 private:
  ::fidl::UnownedClientEnd<::test_service::SecondProtocol> _client_end() const {
    return ::fidl::UnownedClientEnd<::test_service::SecondProtocol>(
        _transport().get<::fidl::internal::ChannelTransport>());
  }
};

// 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::WireServer<::test_service::SecondProtocol>
    : public ::fidl::internal::IncomingMessageDispatcher {
 public:
  WireServer() = default;
  virtual ~WireServer() = default;

  // The FIDL protocol type that is implemented by this server.
  using _EnclosingProtocol = ::test_service::SecondProtocol;

  using MethodOnSecondCompleter = ::fidl::internal::WireCompleter<
      ::test_service::SecondProtocol::MethodOnSecond>;
  using MethodOnSecondRequestView = ::fidl::internal::WireRequestView<
      ::test_service::SecondProtocol::MethodOnSecond>;

  virtual void MethodOnSecond(MethodOnSecondRequestView request,
                              MethodOnSecondCompleter::Sync& completer) = 0;

 private:
  void dispatch_message(
      ::fidl::IncomingMessage&& msg, ::fidl::Transaction* txn,
      ::fidl::internal::IncomingTransportContext transport_context) final;
};
namespace test_service {
#endif  // __Fuchsia__

}  // namespace test_service
template <>
struct ::fidl::internal::WireOrdinal<
    ::test_service::FirstProtocol::MethodOnFirst>
    final {
  static constexpr uint64_t value = 6352548393671797041lu;
};

namespace test_service {}  // namespace test_service
#ifdef __Fuchsia__

template <>
struct ::fidl::internal::ProtocolDetails<::test_service::FirstProtocol> {};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
struct ::fidl::internal::WireServerDispatcher<::test_service::FirstProtocol>
    final {
  WireServerDispatcher() = delete;
  static ::fidl::DispatchResult TryDispatch(
      ::fidl::WireServer<::test_service::FirstProtocol>* impl,
      ::fidl::IncomingMessage& msg,
      internal::IncomingTransportContext transport_context,
      ::fidl::Transaction* txn);
  static void Dispatch(::fidl::WireServer<::test_service::FirstProtocol>* impl,
                       ::fidl::IncomingMessage&& msg,
                       internal::IncomingTransportContext transport_context,
                       ::fidl::Transaction* txn);

 private:
  static const ::fidl::internal::MethodEntry entries_[];
  static const ::fidl::internal::MethodEntry* entries_end_;
};
#endif  // __Fuchsia__

template <>
struct ::fidl::WireRequest<::test_service::FirstProtocol::MethodOnFirst> final {
  WireRequest() = default;
};

template <>
struct ::fidl::internal::TransactionalRequest<
    ::test_service::FirstProtocol::MethodOnFirst>
    final {
  FIDL_ALIGNDECL
  fidl_message_header_t header;

  TransactionalRequest() { _InitHeader(); }

 private:
  void _InitHeader();
};

namespace fidl {

template <>
struct IsFidlType<::fidl::internal::TransactionalRequest<
    ::test_service::FirstProtocol::MethodOnFirst>> : public std::true_type {};
template <>
struct IsFidlType<
    ::fidl::WireRequest<::test_service::FirstProtocol::MethodOnFirst>>
    : public std::true_type {};
template <>
struct IsFidlTransactionalMessage<::fidl::internal::TransactionalRequest<
    ::test_service::FirstProtocol::MethodOnFirst>> : public std::true_type {};
template <>
struct IsFidlTransactionalMessage<
    ::fidl::WireRequest<::test_service::FirstProtocol::MethodOnFirst>>
    : public std::false_type {};

template <>
struct TypeTraits<::fidl::internal::TransactionalRequest<
    ::test_service::FirstProtocol::MethodOnFirst>> {
  static constexpr const fidl_type_t* kType = nullptr;
  static constexpr uint32_t kMaxNumHandles = 0;
  static constexpr uint32_t kPrimarySize =
      FIDL_ALIGN(0 + sizeof(fidl_message_header_t));
  static constexpr uint32_t kPrimarySizeV1 =
      FIDL_ALIGN(0 + sizeof(fidl_message_header_t));
  static constexpr uint32_t kMaxOutOfLine = 0;
  static constexpr uint32_t kMaxOutOfLineV1 = 0;
  static constexpr bool kHasFlexibleEnvelope = false;
  static constexpr bool kHasPointer = false;
  static constexpr ::fidl::internal::TransactionalMessageKind kMessageKind =
      ::fidl::internal::TransactionalMessageKind::kRequest;
};

static_assert(sizeof(::fidl::internal::TransactionalRequest<
                     ::test_service::FirstProtocol::MethodOnFirst>) ==
              TypeTraits<::fidl::internal::TransactionalRequest<
                  ::test_service::FirstProtocol::MethodOnFirst>>::kPrimarySize);
static_assert(offsetof(::fidl::internal::TransactionalRequest<
                           ::test_service::FirstProtocol::MethodOnFirst>,
                       header) == 0);

template <>
struct TypeTraits<
    ::fidl::WireRequest<::test_service::FirstProtocol::MethodOnFirst>> {
  static constexpr const fidl_type_t* kType = nullptr;
  static constexpr uint32_t kMaxNumHandles = 0;
  static constexpr uint32_t kPrimarySize = 0;
  static constexpr uint32_t kPrimarySizeV1 = 0;
  static constexpr uint32_t kMaxOutOfLine = 0;
  static constexpr uint32_t kMaxOutOfLineV1 = 0;
  static constexpr bool kHasFlexibleEnvelope = false;
  static constexpr bool kHasPointer = false;
  static constexpr ::fidl::internal::TransactionalMessageKind kMessageKind =
      ::fidl::internal::TransactionalMessageKind::kRequest;
};

}  // namespace fidl
namespace test_service {
#ifdef __Fuchsia__
}  // namespace test_service
template <>
class [[nodiscard]] ::fidl::WireResult<
    ::test_service::FirstProtocol::MethodOnFirst>
    final : public ::fidl::Status {
 public:
  WireResult(::fidl::UnownedClientEnd<::test_service::FirstProtocol> client,
             ::fidl::internal::TransactionalRequest<
                 ::test_service::FirstProtocol::MethodOnFirst>* request);
  explicit WireResult(const ::fidl::Status& result) : ::fidl::Status(result) {}
  WireResult(WireResult&&) = delete;
  WireResult(const WireResult&) = delete;
  WireResult* operator=(WireResult&&) = delete;
  WireResult* operator=(const WireResult&) = delete;
  ~WireResult() = default;

 private:
};
template <>
class [[nodiscard]] ::fidl::WireUnownedResult<
    ::test_service::FirstProtocol::MethodOnFirst>
    final : public ::fidl::Status {
 public:
  explicit WireUnownedResult(
      ::fidl::UnownedClientEnd<::test_service::FirstProtocol> client_end,
      ::fidl::internal::AnyBufferAllocator& allocator,
      ::fidl::internal::TransactionalRequest<
          ::test_service::FirstProtocol::MethodOnFirst>* request);
  explicit WireUnownedResult(const ::fidl::Status& result)
      : ::fidl::Status(result) {}
  WireUnownedResult(WireUnownedResult&&) = delete;
  WireUnownedResult(const WireUnownedResult&) = delete;
  WireUnownedResult* operator=(WireUnownedResult&&) = delete;
  WireUnownedResult* operator=(const WireUnownedResult&) = delete;
  ~WireUnownedResult() = default;
};
template <>
class ::fidl::internal::WireEventHandlerInterface<
    ::test_service::FirstProtocol> {
 public:
  WireEventHandlerInterface() = default;
  virtual ~WireEventHandlerInterface() = default;
};

template <>
class ::fidl::WireAsyncEventHandler<::test_service::FirstProtocol>
    : public ::fidl::internal::WireEventHandlerInterface<
          ::test_service::FirstProtocol>,
      public ::fidl::internal::AsyncEventHandler {
 public:
  WireAsyncEventHandler() = default;
};

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

  // Handle all possible events defined in this protocol.
  // Blocks to consume exactly one message from the channel, then call the
  // corresponding virtual method.
  ::fidl::Status HandleOneEvent(
      ::fidl::UnownedClientEnd<::test_service::FirstProtocol> client_end);

 private:
  [[maybe_unused]] bool got_transitional_ = false;
};

template <>
class ::fidl::internal::WireEventDispatcher<::test_service::FirstProtocol> final
    : public ::fidl::internal::IncomingEventDispatcher<
          ::fidl::WireAsyncEventHandler<::test_service::FirstProtocol>> {
 public:
  explicit WireEventDispatcher(
      ::fidl::WireAsyncEventHandler<::test_service::FirstProtocol>*
          event_handler)
      : IncomingEventDispatcher(event_handler) {}

 private:
  std::optional<::fidl::UnbindInfo> DispatchEvent(
      ::fidl::IncomingMessage& msg,
      ::fidl::internal::IncomingTransportContext transport_context) override;
};

// Methods to make a sync FIDL call directly on an unowned handle or a
// const reference to a |fidl::ClientEnd<::test_service::FirstProtocol>|,
// avoiding setting up a client.
template <>
class ::fidl::internal::WireSyncClientImpl<::test_service::FirstProtocol> final
    : public ::fidl::internal::SyncEndpointManagedVeneer<
          ::fidl::internal::WireSyncClientImpl<::test_service::FirstProtocol>> {
 public:
  // Allocates 32 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::WireResult<::test_service::FirstProtocol::MethodOnFirst>
  MethodOnFirst() {
    ::fidl::internal::TransactionalRequest<
        ::test_service::FirstProtocol::MethodOnFirst>
        _request{};
    return ::fidl::WireResult<::test_service::FirstProtocol::MethodOnFirst>(
        _client_end(), &_request);
  }

 private:
  ::fidl::UnownedClientEnd<::test_service::FirstProtocol> _client_end() const {
    return ::fidl::UnownedClientEnd<::test_service::FirstProtocol>(
        _transport().get<::fidl::internal::ChannelTransport>());
  }
};

template <>
class ::fidl::internal::WireSyncBufferClientImpl<::test_service::FirstProtocol>
    final : public ::fidl::internal::SyncEndpointBufferVeneer<
                ::fidl::internal::WireSyncBufferClientImpl<
                    ::test_service::FirstProtocol>> {
 public:
  // Caller provides the backing storage for FIDL message via an argument to
  // `.buffer()`.
  ::fidl::WireUnownedResult<::test_service::FirstProtocol::MethodOnFirst>
  MethodOnFirst() {
    ::fidl::internal::TransactionalRequest<
        ::test_service::FirstProtocol::MethodOnFirst>
        _request{};
    return ::fidl::WireUnownedResult<
        ::test_service::FirstProtocol::MethodOnFirst>(_client_end(),
                                                      _allocator(), &_request);
  }

 private:
  ::fidl::UnownedClientEnd<::test_service::FirstProtocol> _client_end() const {
    return ::fidl::UnownedClientEnd<::test_service::FirstProtocol>(
        _transport().get<::fidl::internal::ChannelTransport>());
  }
};

// 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::WireServer<::test_service::FirstProtocol>
    : public ::fidl::internal::IncomingMessageDispatcher {
 public:
  WireServer() = default;
  virtual ~WireServer() = default;

  // The FIDL protocol type that is implemented by this server.
  using _EnclosingProtocol = ::test_service::FirstProtocol;

  using MethodOnFirstCompleter = ::fidl::internal::WireCompleter<
      ::test_service::FirstProtocol::MethodOnFirst>;
  using MethodOnFirstRequestView = ::fidl::internal::WireRequestView<
      ::test_service::FirstProtocol::MethodOnFirst>;

  virtual void MethodOnFirst(MethodOnFirstRequestView request,
                             MethodOnFirstCompleter::Sync& completer) = 0;

 private:
  void dispatch_message(
      ::fidl::IncomingMessage&& msg, ::fidl::Transaction* txn,
      ::fidl::internal::IncomingTransportContext transport_context) final;
};
namespace test_service {
#endif  // __Fuchsia__

class SingleMemberService final {
  SingleMemberService() = default;

 public:
  static constexpr char Name[] = "test.service.SingleMemberService";

  // Client protocol for connecting to member protocols of a service instance.
  class ServiceClient final {
    ServiceClient() = delete;

   public:
    ServiceClient(::zx::channel dir,
                  ::fidl::internal::ConnectMemberFunc connect_func)
        : dir_(std::move(dir)), connect_func_(connect_func) {}

    // Connects to the member protocol "single_member".
    // Returns a |fidl::ClientEnd<::test_service::FirstProtocol>| on success,
    // which can be used with |fidl::BindSyncClient| to create a synchronous
    // client, or |fidl::WireClient| or |fidl::WireSharedClient| to create a
    // client that supports both asynchronous and synchronous operations.
    //
    // # Errors
    //
    // On failure, returns a |zx::error| with status != ZX_OK.
    // Failures can occur if channel creation failed, or if there was an issue
    // making a |fuchsia.io.Directory/Open| call.
    //
    // Since the call to |Open| is asynchronous, an error sent by the remote end
    // will not result in a failure of this method. Any errors sent by the
    // remote will appear on the |ClientEnd| returned from this method.
    ::zx::status<::fidl::ClientEnd<::test_service::FirstProtocol>>
    connect_single_member() {
      auto endpoints = ::fidl::CreateEndpoints<::test_service::FirstProtocol>();
      if (endpoints.is_error()) {
        return endpoints.take_error();
      }
      auto connection = connect_func_(::zx::unowned_channel(dir_),
                                      ::fidl::StringView("single_member"),
                                      endpoints->server.TakeChannel());
      if (connection.is_error()) {
        return connection.take_error();
      }
      return ::zx::ok(std::move(endpoints->client));
    }

   private:
    ::zx::channel dir_;
    ::fidl::internal::ConnectMemberFunc connect_func_;
  };

  // Facilitates member protocol registration for servers.
  class Handler final {
   public:
    // Constructs a FIDL Service-typed handler. Does not take ownership of
    // |service_handler|.
    explicit Handler(::fidl::ServiceHandlerInterface* service_handler)
        : service_handler_(service_handler) {}

    // Adds member "single_member" to the service instance. |handler| will be
    // invoked on connection attempts.
    //
    // # Errors
    //
    // Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
    ::zx::status<> add_single_member(
        ::fidl::ServiceHandlerInterface::MemberHandler<
            ::test_service::FirstProtocol>
            handler) {
      return service_handler_->AddMember("single_member", std::move(handler));
    }

   private:
    ::fidl::ServiceHandlerInterface* service_handler_;  // Not owned.
  };
};

class MultiHomogeneousMemberService final {
  MultiHomogeneousMemberService() = default;

 public:
  static constexpr char Name[] = "test.service.MultiHomogeneousMemberService";

  // Client protocol for connecting to member protocols of a service instance.
  class ServiceClient final {
    ServiceClient() = delete;

   public:
    ServiceClient(::zx::channel dir,
                  ::fidl::internal::ConnectMemberFunc connect_func)
        : dir_(std::move(dir)), connect_func_(connect_func) {}

    // Connects to the member protocol "first_member".
    // Returns a |fidl::ClientEnd<::test_service::FirstProtocol>| on success,
    // which can be used with |fidl::BindSyncClient| to create a synchronous
    // client, or |fidl::WireClient| or |fidl::WireSharedClient| to create a
    // client that supports both asynchronous and synchronous operations.
    //
    // # Errors
    //
    // On failure, returns a |zx::error| with status != ZX_OK.
    // Failures can occur if channel creation failed, or if there was an issue
    // making a |fuchsia.io.Directory/Open| call.
    //
    // Since the call to |Open| is asynchronous, an error sent by the remote end
    // will not result in a failure of this method. Any errors sent by the
    // remote will appear on the |ClientEnd| returned from this method.
    ::zx::status<::fidl::ClientEnd<::test_service::FirstProtocol>>
    connect_first_member() {
      auto endpoints = ::fidl::CreateEndpoints<::test_service::FirstProtocol>();
      if (endpoints.is_error()) {
        return endpoints.take_error();
      }
      auto connection = connect_func_(::zx::unowned_channel(dir_),
                                      ::fidl::StringView("first_member"),
                                      endpoints->server.TakeChannel());
      if (connection.is_error()) {
        return connection.take_error();
      }
      return ::zx::ok(std::move(endpoints->client));
    }

    // Connects to the member protocol "second_member".
    // Returns a |fidl::ClientEnd<::test_service::FirstProtocol>| on success,
    // which can be used with |fidl::BindSyncClient| to create a synchronous
    // client, or |fidl::WireClient| or |fidl::WireSharedClient| to create a
    // client that supports both asynchronous and synchronous operations.
    //
    // # Errors
    //
    // On failure, returns a |zx::error| with status != ZX_OK.
    // Failures can occur if channel creation failed, or if there was an issue
    // making a |fuchsia.io.Directory/Open| call.
    //
    // Since the call to |Open| is asynchronous, an error sent by the remote end
    // will not result in a failure of this method. Any errors sent by the
    // remote will appear on the |ClientEnd| returned from this method.
    ::zx::status<::fidl::ClientEnd<::test_service::FirstProtocol>>
    connect_second_member() {
      auto endpoints = ::fidl::CreateEndpoints<::test_service::FirstProtocol>();
      if (endpoints.is_error()) {
        return endpoints.take_error();
      }
      auto connection = connect_func_(::zx::unowned_channel(dir_),
                                      ::fidl::StringView("second_member"),
                                      endpoints->server.TakeChannel());
      if (connection.is_error()) {
        return connection.take_error();
      }
      return ::zx::ok(std::move(endpoints->client));
    }

   private:
    ::zx::channel dir_;
    ::fidl::internal::ConnectMemberFunc connect_func_;
  };

  // Facilitates member protocol registration for servers.
  class Handler final {
   public:
    // Constructs a FIDL Service-typed handler. Does not take ownership of
    // |service_handler|.
    explicit Handler(::fidl::ServiceHandlerInterface* service_handler)
        : service_handler_(service_handler) {}

    // Adds member "first_member" to the service instance. |handler| will be
    // invoked on connection attempts.
    //
    // # Errors
    //
    // Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
    ::zx::status<> add_first_member(
        ::fidl::ServiceHandlerInterface::MemberHandler<
            ::test_service::FirstProtocol>
            handler) {
      return service_handler_->AddMember("first_member", std::move(handler));
    }

    // Adds member "second_member" to the service instance. |handler| will be
    // invoked on connection attempts.
    //
    // # Errors
    //
    // Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
    ::zx::status<> add_second_member(
        ::fidl::ServiceHandlerInterface::MemberHandler<
            ::test_service::FirstProtocol>
            handler) {
      return service_handler_->AddMember("second_member", std::move(handler));
    }

   private:
    ::fidl::ServiceHandlerInterface* service_handler_;  // Not owned.
  };
};

class MultiHeterogeneousMemberService final {
  MultiHeterogeneousMemberService() = default;

 public:
  static constexpr char Name[] = "test.service.MultiHeterogeneousMemberService";

  // Client protocol for connecting to member protocols of a service instance.
  class ServiceClient final {
    ServiceClient() = delete;

   public:
    ServiceClient(::zx::channel dir,
                  ::fidl::internal::ConnectMemberFunc connect_func)
        : dir_(std::move(dir)), connect_func_(connect_func) {}

    // Connects to the member protocol "first_member".
    // Returns a |fidl::ClientEnd<::test_service::FirstProtocol>| on success,
    // which can be used with |fidl::BindSyncClient| to create a synchronous
    // client, or |fidl::WireClient| or |fidl::WireSharedClient| to create a
    // client that supports both asynchronous and synchronous operations.
    //
    // # Errors
    //
    // On failure, returns a |zx::error| with status != ZX_OK.
    // Failures can occur if channel creation failed, or if there was an issue
    // making a |fuchsia.io.Directory/Open| call.
    //
    // Since the call to |Open| is asynchronous, an error sent by the remote end
    // will not result in a failure of this method. Any errors sent by the
    // remote will appear on the |ClientEnd| returned from this method.
    ::zx::status<::fidl::ClientEnd<::test_service::FirstProtocol>>
    connect_first_member() {
      auto endpoints = ::fidl::CreateEndpoints<::test_service::FirstProtocol>();
      if (endpoints.is_error()) {
        return endpoints.take_error();
      }
      auto connection = connect_func_(::zx::unowned_channel(dir_),
                                      ::fidl::StringView("first_member"),
                                      endpoints->server.TakeChannel());
      if (connection.is_error()) {
        return connection.take_error();
      }
      return ::zx::ok(std::move(endpoints->client));
    }

    // Connects to the member protocol "second_member".
    // Returns a |fidl::ClientEnd<::test_service::SecondProtocol>| on success,
    // which can be used with |fidl::BindSyncClient| to create a synchronous
    // client, or |fidl::WireClient| or |fidl::WireSharedClient| to create a
    // client that supports both asynchronous and synchronous operations.
    //
    // # Errors
    //
    // On failure, returns a |zx::error| with status != ZX_OK.
    // Failures can occur if channel creation failed, or if there was an issue
    // making a |fuchsia.io.Directory/Open| call.
    //
    // Since the call to |Open| is asynchronous, an error sent by the remote end
    // will not result in a failure of this method. Any errors sent by the
    // remote will appear on the |ClientEnd| returned from this method.
    ::zx::status<::fidl::ClientEnd<::test_service::SecondProtocol>>
    connect_second_member() {
      auto endpoints =
          ::fidl::CreateEndpoints<::test_service::SecondProtocol>();
      if (endpoints.is_error()) {
        return endpoints.take_error();
      }
      auto connection = connect_func_(::zx::unowned_channel(dir_),
                                      ::fidl::StringView("second_member"),
                                      endpoints->server.TakeChannel());
      if (connection.is_error()) {
        return connection.take_error();
      }
      return ::zx::ok(std::move(endpoints->client));
    }

   private:
    ::zx::channel dir_;
    ::fidl::internal::ConnectMemberFunc connect_func_;
  };

  // Facilitates member protocol registration for servers.
  class Handler final {
   public:
    // Constructs a FIDL Service-typed handler. Does not take ownership of
    // |service_handler|.
    explicit Handler(::fidl::ServiceHandlerInterface* service_handler)
        : service_handler_(service_handler) {}

    // Adds member "first_member" to the service instance. |handler| will be
    // invoked on connection attempts.
    //
    // # Errors
    //
    // Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
    ::zx::status<> add_first_member(
        ::fidl::ServiceHandlerInterface::MemberHandler<
            ::test_service::FirstProtocol>
            handler) {
      return service_handler_->AddMember("first_member", std::move(handler));
    }

    // Adds member "second_member" to the service instance. |handler| will be
    // invoked on connection attempts.
    //
    // # Errors
    //
    // Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
    ::zx::status<> add_second_member(
        ::fidl::ServiceHandlerInterface::MemberHandler<
            ::test_service::SecondProtocol>
            handler) {
      return service_handler_->AddMember("second_member", std::move(handler));
    }

   private:
    ::fidl::ServiceHandlerInterface* service_handler_;  // Not owned.
  };
};

class EmptyService final {
  EmptyService() = default;

 public:
  static constexpr char Name[] = "test.service.EmptyService";

  // Client protocol for connecting to member protocols of a service instance.
  class ServiceClient final {
    ServiceClient() = delete;

   public:
    ServiceClient(::zx::channel dir,
                  ::fidl::internal::ConnectMemberFunc connect_func) {
      (void)dir;
      (void)connect_func;
    }

   private:
  };

  // Facilitates member protocol registration for servers.
  class Handler final {
   public:
    // Constructs a FIDL Service-typed handler. Does not take ownership of
    // |service_handler|.
    explicit Handler(::fidl::ServiceHandlerInterface* service_handler) {
      (void)service_handler;
    }

   private:
  };
};

}  // namespace test_service
namespace fidl {

#ifdef __Fuchsia__
}  // namespace fidl
template <>
class ::fidl::internal::WireWeakOnewayClientImpl<::test_service::SecondProtocol>
    : public ::fidl::internal::ClientImplBase {
 public:
  using ClientImplBase::ClientImplBase;

  // Allocates 32 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Status MethodOnSecond();
};

template <>
class ::fidl::internal::WireWeakAsyncClientImpl<::test_service::SecondProtocol>
    final : public ::fidl::internal::WireWeakOnewayClientImpl<
                ::test_service::SecondProtocol> {
 public:
  using WireWeakOnewayClientImpl::WireWeakOnewayClientImpl;
};

template <>
class ::fidl::internal::WireWeakOnewayBufferClientImpl<
    ::test_service::SecondProtocol>
    : public ::fidl::internal::BufferClientImplBase {
 public:
  using BufferClientImplBase::BufferClientImplBase;

  // Caller provides the backing storage for FIDL message.
  ::fidl::Status MethodOnSecond();
};

template <>
class ::fidl::internal::WireWeakAsyncBufferClientImpl<
    ::test_service::SecondProtocol>
    final : public ::fidl::internal::WireWeakOnewayBufferClientImpl<
                ::test_service::SecondProtocol> {
 public:
  using WireWeakOnewayBufferClientImpl::WireWeakOnewayBufferClientImpl;
};
template <>
class ::fidl::internal::WireWeakSyncClientImpl<::test_service::SecondProtocol>
    final : public ::fidl::internal::WireWeakOnewayClientImpl<
                ::test_service::SecondProtocol> {
 public:
  using WireWeakOnewayClientImpl::WireWeakOnewayClientImpl;
};
namespace fidl {
#endif  // __Fuchsia__

}  // namespace fidl
#ifdef __Fuchsia__
template <>
class ::fidl::internal::WireWeakEventSender<::test_service::SecondProtocol>
    : public ::fidl::internal::WeakEventSenderBase {
 public:
  using WeakEventSenderBase::WeakEventSenderBase;
};

template <>
class ::fidl::internal::WireWeakBufferEventSender<
    ::test_service::SecondProtocol>
    : public ::fidl::internal::WeakBufferEventSenderBase {
 public:
  using WeakBufferEventSenderBase::WeakBufferEventSenderBase;
};

template <>
class ::fidl::internal::WireEventSender<::test_service::SecondProtocol>
    : public ::fidl::internal::SyncEndpointManagedVeneer<
          ::fidl::internal::WireEventSender<::test_service::SecondProtocol>> {
 public:
  using SyncEndpointManagedVeneer::SyncEndpointManagedVeneer;
};

template <>
class ::fidl::internal::WireBufferEventSender<::test_service::SecondProtocol>
    : public ::fidl::internal::SyncEndpointBufferVeneer<
          ::fidl::internal::WireBufferEventSender<
              ::test_service::SecondProtocol>> {
 public:
  using SyncEndpointBufferVeneer::SyncEndpointBufferVeneer;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

template <>
class ::fidl::internal::WireWeakOnewayClientImpl<::test_service::FirstProtocol>
    : public ::fidl::internal::ClientImplBase {
 public:
  using ClientImplBase::ClientImplBase;

  // Allocates 32 bytes of message buffer on the stack. No heap allocation
  // necessary.
  ::fidl::Status MethodOnFirst();
};

template <>
class ::fidl::internal::WireWeakAsyncClientImpl<::test_service::FirstProtocol>
    final : public ::fidl::internal::WireWeakOnewayClientImpl<
                ::test_service::FirstProtocol> {
 public:
  using WireWeakOnewayClientImpl::WireWeakOnewayClientImpl;
};

template <>
class ::fidl::internal::WireWeakOnewayBufferClientImpl<
    ::test_service::FirstProtocol>
    : public ::fidl::internal::BufferClientImplBase {
 public:
  using BufferClientImplBase::BufferClientImplBase;

  // Caller provides the backing storage for FIDL message.
  ::fidl::Status MethodOnFirst();
};

template <>
class ::fidl::internal::WireWeakAsyncBufferClientImpl<
    ::test_service::FirstProtocol>
    final : public ::fidl::internal::WireWeakOnewayBufferClientImpl<
                ::test_service::FirstProtocol> {
 public:
  using WireWeakOnewayBufferClientImpl::WireWeakOnewayBufferClientImpl;
};
template <>
class ::fidl::internal::WireWeakSyncClientImpl<::test_service::FirstProtocol>
    final : public ::fidl::internal::WireWeakOnewayClientImpl<
                ::test_service::FirstProtocol> {
 public:
  using WireWeakOnewayClientImpl::WireWeakOnewayClientImpl;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__
template <>
class ::fidl::internal::WireWeakEventSender<::test_service::FirstProtocol>
    : public ::fidl::internal::WeakEventSenderBase {
 public:
  using WeakEventSenderBase::WeakEventSenderBase;
};

template <>
class ::fidl::internal::WireWeakBufferEventSender<::test_service::FirstProtocol>
    : public ::fidl::internal::WeakBufferEventSenderBase {
 public:
  using WeakBufferEventSenderBase::WeakBufferEventSenderBase;
};

template <>
class ::fidl::internal::WireEventSender<::test_service::FirstProtocol>
    : public ::fidl::internal::SyncEndpointManagedVeneer<
          ::fidl::internal::WireEventSender<::test_service::FirstProtocol>> {
 public:
  using SyncEndpointManagedVeneer::SyncEndpointManagedVeneer;
};

template <>
class ::fidl::internal::WireBufferEventSender<::test_service::FirstProtocol>
    : public ::fidl::internal::SyncEndpointBufferVeneer<
          ::fidl::internal::WireBufferEventSender<
              ::test_service::FirstProtocol>> {
 public:
  using SyncEndpointBufferVeneer::SyncEndpointBufferVeneer;
};
#endif  // __Fuchsia__
