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

#pragma once

#include "lib/fidl/cpp/internal/header.h"

namespace test {
namespace service {

//
// Domain objects declarations
//

#ifdef __Fuchsia__
class SingleMemberService;
#endif  // __Fuchsia__

#ifdef __Fuchsia__

class SecondProtocol;
using SecondProtocolHandle = ::fidl::InterfaceHandle<SecondProtocol>;
#endif  // __Fuchsia__

#ifdef __Fuchsia__
class MultiHomogeneousMemberService;
#endif  // __Fuchsia__

#ifdef __Fuchsia__
class MultiHeterogeneousMemberService;
#endif  // __Fuchsia__

#ifdef __Fuchsia__

class FirstProtocol;
using FirstProtocolHandle = ::fidl::InterfaceHandle<FirstProtocol>;
#endif  // __Fuchsia__

#ifdef __Fuchsia__
class EmptyService;
#endif  // __Fuchsia__

#ifdef __Fuchsia__

class SecondProtocol_RequestEncoder {
 public:
  static ::fidl::HLCPPOutgoingMessage MethodOnSecond(::fidl::MessageEncoder* _encoder) {
    return _encoder->GetMessage();
  }
};

class SecondProtocol_ResponseEncoder {
 public:
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

class FirstProtocol_RequestEncoder {
 public:
  static ::fidl::HLCPPOutgoingMessage MethodOnFirst(::fidl::MessageEncoder* _encoder) {
    return _encoder->GetMessage();
  }
};

class FirstProtocol_ResponseEncoder {
 public:
};
#endif  // __Fuchsia__

}  // namespace service
}  // namespace test
namespace fidl {

//
// Proxies and stubs declarations
//
}  // namespace fidl
namespace test {
namespace service {
#ifdef __Fuchsia__
class SingleMemberService;
#endif  // __Fuchsia__

#ifdef __Fuchsia__

using SecondProtocolPtr = ::fidl::InterfacePtr<SecondProtocol>;
class SecondProtocol_Proxy;
class SecondProtocol_Stub;
class SecondProtocol_EventSender;
class SecondProtocol_Sync;
using SecondProtocolSyncPtr = ::fidl::SynchronousInterfacePtr<SecondProtocol>;
class SecondProtocol_SyncProxy;

namespace internal {
constexpr uint64_t kSecondProtocol_MethodOnSecond_Ordinal = 0x70b439758de25c44lu;
constexpr ::fidl::MessageDynamicFlags kSecondProtocol_MethodOnSecond_DynamicFlags = ::fidl::MessageDynamicFlags::kStrictMethod;
}  // namespace internal
#endif  // __Fuchsia__

#ifdef __Fuchsia__
class MultiHomogeneousMemberService;
#endif  // __Fuchsia__

#ifdef __Fuchsia__
class MultiHeterogeneousMemberService;
#endif  // __Fuchsia__

#ifdef __Fuchsia__

using FirstProtocolPtr = ::fidl::InterfacePtr<FirstProtocol>;
class FirstProtocol_Proxy;
class FirstProtocol_Stub;
class FirstProtocol_EventSender;
class FirstProtocol_Sync;
using FirstProtocolSyncPtr = ::fidl::SynchronousInterfacePtr<FirstProtocol>;
class FirstProtocol_SyncProxy;

namespace internal {
constexpr uint64_t kFirstProtocol_MethodOnFirst_Ordinal = 0x5828c91b57492931lu;
constexpr ::fidl::MessageDynamicFlags kFirstProtocol_MethodOnFirst_DynamicFlags = ::fidl::MessageDynamicFlags::kStrictMethod;
}  // namespace internal
#endif  // __Fuchsia__

#ifdef __Fuchsia__
class EmptyService;
#endif  // __Fuchsia__

#ifdef __Fuchsia__

class SingleMemberService final {
 public:
  class Handler;

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

  explicit SingleMemberService(std::unique_ptr<::fidl::ServiceConnector> service)
      : service_(std::move(service)) {}

  explicit operator bool() const { return !!service_; }
  /// Returns a |fidl::MemberConnector| which can be used to connect to the member protocol "single_member".
  ::fidl::MemberConnector<::test::service::FirstProtocol> single_member() const {
    return ::fidl::MemberConnector<::test::service::FirstProtocol>(service_.get(), "single_member");
  }

 private:
  std::unique_ptr<::fidl::ServiceConnector> service_;
};

/// Facilitates member protocol registration for servers.
class SingleMemberService::Handler final {
 public:
  /// Constructs a new |Handler|. Does not take ownership of |service|.
  explicit Handler(::fidl::ServiceHandlerBase* service)
      : service_(service) {}
  /// Adds member "single_member" to the service instance. |handler| is invoked when a connection
  /// is made to the member protocol.
  ///
  /// # Errors
  ///
  /// Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
  zx_status_t add_single_member(::fidl::InterfaceRequestHandler<::test::service::FirstProtocol> handler) {
    return service_->AddMember("single_member", std::move(handler));
  }

 private:
  ::fidl::ServiceHandlerBase* const service_;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

class SecondProtocol {
 public:
  using Proxy_ = ::test::service::SecondProtocol_Proxy;
  using Stub_ = ::test::service::SecondProtocol_Stub;
  using EventSender_ = ::test::service::SecondProtocol_EventSender;
  using Sync_ = ::test::service::SecondProtocol_Sync;
  virtual ~SecondProtocol();

  virtual void MethodOnSecond() = 0;
};

class SecondProtocol_RequestDecoder {
 public:
  SecondProtocol_RequestDecoder() = default;
  virtual ~SecondProtocol_RequestDecoder() = default;
  static const fidl_type_t* GetType(uint64_t ordinal, bool* out_needs_response);
  virtual void MethodOnSecond() = 0;
};

class SecondProtocol_ResponseDecoder {
 public:
  SecondProtocol_ResponseDecoder() = default;
  virtual ~SecondProtocol_ResponseDecoder() = default;
  static const fidl_type_t* GetType(uint64_t ordinal);
};

class SecondProtocol_EventSender {
 public:
  virtual ~SecondProtocol_EventSender();
};

class SecondProtocol_Sync {
 public:
  using Proxy_ = ::test::service::SecondProtocol_SyncProxy;
  virtual ~SecondProtocol_Sync();
  virtual zx_status_t MethodOnSecond() = 0;
};

class SecondProtocol_Proxy final : public ::fidl::internal::Proxy, public SecondProtocol {
 public:
  explicit SecondProtocol_Proxy(::fidl::internal::ProxyController* controller);
  ~SecondProtocol_Proxy() override;

  zx_status_t Dispatch_(::fidl::HLCPPIncomingMessage message) override;
  // cts-coverage-fidl-name:test.service/SecondProtocol.MethodOnSecond
  void MethodOnSecond() override;

 private:
  SecondProtocol_Proxy(const ::test::service::SecondProtocol_Proxy&) = delete;
  SecondProtocol_Proxy& operator=(const ::test::service::SecondProtocol_Proxy&) = delete;

  ::fidl::internal::ProxyController* controller_;
};

class SecondProtocol_Stub final : public ::fidl::internal::Stub, public ::test::service::SecondProtocol_EventSender {
 public:
  typedef class ::test::service::SecondProtocol SecondProtocol_clazz;
  explicit SecondProtocol_Stub(::test::service::SecondProtocol_Stub::SecondProtocol_clazz* impl);
  ~SecondProtocol_Stub() override;

  zx_status_t Dispatch_(::fidl::HLCPPIncomingMessage message,
                        ::fidl::internal::PendingResponse response) override;

 private:
  ::test::service::SecondProtocol_Stub::SecondProtocol_clazz* impl_;
};

class SecondProtocol_SyncProxy : public ::test::service::SecondProtocol_Sync {
 public:
  explicit SecondProtocol_SyncProxy(::zx::channel channel);
  ~SecondProtocol_SyncProxy() override;
  // cts-coverage-fidl-name:test.service/SecondProtocol.MethodOnSecond
  zx_status_t MethodOnSecond() override;

 private:
  ::fidl::internal::SynchronousProxy proxy_;
  friend class ::fidl::SynchronousInterfacePtr<SecondProtocol>;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

class MultiHomogeneousMemberService final {
 public:
  class Handler;

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

  explicit MultiHomogeneousMemberService(std::unique_ptr<::fidl::ServiceConnector> service)
      : service_(std::move(service)) {}

  explicit operator bool() const { return !!service_; }
  /// Returns a |fidl::MemberConnector| which can be used to connect to the member protocol "first_member".
  ::fidl::MemberConnector<::test::service::FirstProtocol> first_member() const {
    return ::fidl::MemberConnector<::test::service::FirstProtocol>(service_.get(), "first_member");
  }
  /// Returns a |fidl::MemberConnector| which can be used to connect to the member protocol "second_member".
  ::fidl::MemberConnector<::test::service::FirstProtocol> second_member() const {
    return ::fidl::MemberConnector<::test::service::FirstProtocol>(service_.get(), "second_member");
  }

 private:
  std::unique_ptr<::fidl::ServiceConnector> service_;
};

/// Facilitates member protocol registration for servers.
class MultiHomogeneousMemberService::Handler final {
 public:
  /// Constructs a new |Handler|. Does not take ownership of |service|.
  explicit Handler(::fidl::ServiceHandlerBase* service)
      : service_(service) {}
  /// Adds member "first_member" to the service instance. |handler| is invoked when a connection
  /// is made to the member protocol.
  ///
  /// # Errors
  ///
  /// Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
  zx_status_t add_first_member(::fidl::InterfaceRequestHandler<::test::service::FirstProtocol> handler) {
    return service_->AddMember("first_member", std::move(handler));
  }
  /// Adds member "second_member" to the service instance. |handler| is invoked when a connection
  /// is made to the member protocol.
  ///
  /// # Errors
  ///
  /// Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
  zx_status_t add_second_member(::fidl::InterfaceRequestHandler<::test::service::FirstProtocol> handler) {
    return service_->AddMember("second_member", std::move(handler));
  }

 private:
  ::fidl::ServiceHandlerBase* const service_;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

class MultiHeterogeneousMemberService final {
 public:
  class Handler;

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

  explicit MultiHeterogeneousMemberService(std::unique_ptr<::fidl::ServiceConnector> service)
      : service_(std::move(service)) {}

  explicit operator bool() const { return !!service_; }
  /// Returns a |fidl::MemberConnector| which can be used to connect to the member protocol "first_member".
  ::fidl::MemberConnector<::test::service::FirstProtocol> first_member() const {
    return ::fidl::MemberConnector<::test::service::FirstProtocol>(service_.get(), "first_member");
  }
  /// Returns a |fidl::MemberConnector| which can be used to connect to the member protocol "second_member".
  ::fidl::MemberConnector<::test::service::SecondProtocol> second_member() const {
    return ::fidl::MemberConnector<::test::service::SecondProtocol>(service_.get(), "second_member");
  }

 private:
  std::unique_ptr<::fidl::ServiceConnector> service_;
};

/// Facilitates member protocol registration for servers.
class MultiHeterogeneousMemberService::Handler final {
 public:
  /// Constructs a new |Handler|. Does not take ownership of |service|.
  explicit Handler(::fidl::ServiceHandlerBase* service)
      : service_(service) {}
  /// Adds member "first_member" to the service instance. |handler| is invoked when a connection
  /// is made to the member protocol.
  ///
  /// # Errors
  ///
  /// Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
  zx_status_t add_first_member(::fidl::InterfaceRequestHandler<::test::service::FirstProtocol> handler) {
    return service_->AddMember("first_member", std::move(handler));
  }
  /// Adds member "second_member" to the service instance. |handler| is invoked when a connection
  /// is made to the member protocol.
  ///
  /// # Errors
  ///
  /// Returns ZX_ERR_ALREADY_EXISTS if the member was already added.
  zx_status_t add_second_member(::fidl::InterfaceRequestHandler<::test::service::SecondProtocol> handler) {
    return service_->AddMember("second_member", std::move(handler));
  }

 private:
  ::fidl::ServiceHandlerBase* const service_;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

class FirstProtocol {
 public:
  using Proxy_ = ::test::service::FirstProtocol_Proxy;
  using Stub_ = ::test::service::FirstProtocol_Stub;
  using EventSender_ = ::test::service::FirstProtocol_EventSender;
  using Sync_ = ::test::service::FirstProtocol_Sync;
  virtual ~FirstProtocol();

  virtual void MethodOnFirst() = 0;
};

class FirstProtocol_RequestDecoder {
 public:
  FirstProtocol_RequestDecoder() = default;
  virtual ~FirstProtocol_RequestDecoder() = default;
  static const fidl_type_t* GetType(uint64_t ordinal, bool* out_needs_response);
  virtual void MethodOnFirst() = 0;
};

class FirstProtocol_ResponseDecoder {
 public:
  FirstProtocol_ResponseDecoder() = default;
  virtual ~FirstProtocol_ResponseDecoder() = default;
  static const fidl_type_t* GetType(uint64_t ordinal);
};

class FirstProtocol_EventSender {
 public:
  virtual ~FirstProtocol_EventSender();
};

class FirstProtocol_Sync {
 public:
  using Proxy_ = ::test::service::FirstProtocol_SyncProxy;
  virtual ~FirstProtocol_Sync();
  virtual zx_status_t MethodOnFirst() = 0;
};

class FirstProtocol_Proxy final : public ::fidl::internal::Proxy, public FirstProtocol {
 public:
  explicit FirstProtocol_Proxy(::fidl::internal::ProxyController* controller);
  ~FirstProtocol_Proxy() override;

  zx_status_t Dispatch_(::fidl::HLCPPIncomingMessage message) override;
  // cts-coverage-fidl-name:test.service/FirstProtocol.MethodOnFirst
  void MethodOnFirst() override;

 private:
  FirstProtocol_Proxy(const ::test::service::FirstProtocol_Proxy&) = delete;
  FirstProtocol_Proxy& operator=(const ::test::service::FirstProtocol_Proxy&) = delete;

  ::fidl::internal::ProxyController* controller_;
};

class FirstProtocol_Stub final : public ::fidl::internal::Stub, public ::test::service::FirstProtocol_EventSender {
 public:
  typedef class ::test::service::FirstProtocol FirstProtocol_clazz;
  explicit FirstProtocol_Stub(::test::service::FirstProtocol_Stub::FirstProtocol_clazz* impl);
  ~FirstProtocol_Stub() override;

  zx_status_t Dispatch_(::fidl::HLCPPIncomingMessage message,
                        ::fidl::internal::PendingResponse response) override;

 private:
  ::test::service::FirstProtocol_Stub::FirstProtocol_clazz* impl_;
};

class FirstProtocol_SyncProxy : public ::test::service::FirstProtocol_Sync {
 public:
  explicit FirstProtocol_SyncProxy(::zx::channel channel);
  ~FirstProtocol_SyncProxy() override;
  // cts-coverage-fidl-name:test.service/FirstProtocol.MethodOnFirst
  zx_status_t MethodOnFirst() override;

 private:
  ::fidl::internal::SynchronousProxy proxy_;
  friend class ::fidl::SynchronousInterfacePtr<FirstProtocol>;
};
#endif  // __Fuchsia__

#ifdef __Fuchsia__

class EmptyService final {
 public:
  class Handler;

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

  explicit EmptyService(std::unique_ptr<::fidl::ServiceConnector> service)
      : service_(std::move(service)) {}

  explicit operator bool() const { return !!service_; }

 private:
  std::unique_ptr<::fidl::ServiceConnector> service_;
};

/// Facilitates member protocol registration for servers.
class EmptyService::Handler final {
 public:
  /// Constructs a new |Handler|. Does not take ownership of |service|.
  explicit Handler(::fidl::ServiceHandlerBase* service) { (void)service; }

 private:
};
#endif  // __Fuchsia__

}  // namespace service
}  // namespace test
