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

#include <test/service/cpp/fidl.h>

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

//
// Domain objects definitions
//

//
// Proxies and stubs definitions
//
#ifdef __Fuchsia__

namespace test {
namespace service {
SecondProtocol::~SecondProtocol() = default;

const fidl_type_t* ::test::service::SecondProtocol_RequestDecoder::GetType(uint64_t ordinal, bool* out_needs_response) {
  *out_needs_response = false;
  switch (ordinal) {
    case ::test::service::internal::kSecondProtocol_MethodOnSecond_Ordinal:
      return nullptr;
      ;
    default:
      return nullptr;
  }
}

const fidl_type_t* SecondProtocol_ResponseDecoder::GetType(uint64_t ordinal) {
  switch (ordinal) {
    default:
      return nullptr;
  }
}

SecondProtocol_EventSender::~SecondProtocol_EventSender() = default;

SecondProtocol_Sync::~SecondProtocol_Sync() = default;

SecondProtocol_Proxy::SecondProtocol_Proxy(::fidl::internal::ProxyController* controller)
    : controller_(controller) {
  (void)controller_;
}

SecondProtocol_Proxy::~SecondProtocol_Proxy() = default;

zx_status_t SecondProtocol_Proxy::Dispatch_(::fidl::HLCPPIncomingMessage message) {
  zx_status_t status = ZX_OK;
  switch (message.ordinal()) {
    default: {
      status = ZX_ERR_NOT_SUPPORTED;
      break;
    }
  }
  return status;
}

void SecondProtocol_Proxy::MethodOnSecond() {
  ::fidl::MessageEncoder _encoder(::test::service::internal::kSecondProtocol_MethodOnSecond_Ordinal, ::test::service::internal::kSecondProtocol_MethodOnSecond_DynamicFlags);
  const fidl_type_t* req_type = nullptr;
  controller_->Send(req_type, ::test::service::SecondProtocol_RequestEncoder::MethodOnSecond(&_encoder), nullptr);
}

SecondProtocol_Stub::SecondProtocol_Stub(::test::service::SecondProtocol_Stub::SecondProtocol_clazz* impl) : impl_(impl) {
  (void)impl_;
}

SecondProtocol_Stub::~SecondProtocol_Stub() = default;

namespace {

}  // namespace

zx_status_t SecondProtocol_Stub::Dispatch_(
    ::fidl::HLCPPIncomingMessage message,
    ::fidl::internal::PendingResponse response) {
  bool needs_response;
  const fidl_type_t* request_type = ::test::service::SecondProtocol_RequestDecoder::GetType(message.ordinal(), &needs_response);
  if (!message.has_only_header()) {
    if (request_type == nullptr) {
      return ZX_ERR_NOT_SUPPORTED;
    }
    const char* error_msg = nullptr;
    zx_status_t status = message.Decode(request_type, &error_msg);
    if (status != ZX_OK) {
      FIDL_REPORT_DECODING_ERROR(message, request_type, error_msg);
      return status;
    }
  }

  if (response.needs_response() != needs_response) {
    if (needs_response) {
      FIDL_REPORT_DECODING_ERROR(message, request_type, "Message needing a response with no txid");
    } else {
      FIDL_REPORT_DECODING_ERROR(message, request_type, "Message not needing a response with a txid");
    }
    return ZX_ERR_INVALID_ARGS;
  }

  uint64_t ordinal = message.ordinal();
  switch (ordinal) {
    case ::test::service::internal::kSecondProtocol_MethodOnSecond_Ordinal: {
      impl_->MethodOnSecond();
      break;
    }
    default: {
      return ZX_ERR_NOT_SUPPORTED;
    }
  }
  return ZX_OK;
}

SecondProtocol_SyncProxy::SecondProtocol_SyncProxy(::zx::channel channel)
    : proxy_(::std::move(channel)) {}

SecondProtocol_SyncProxy::~SecondProtocol_SyncProxy() = default;

zx_status_t SecondProtocol_SyncProxy::MethodOnSecond() {
  ::fidl::MessageEncoder _encoder(::test::service::internal::kSecondProtocol_MethodOnSecond_Ordinal, ::test::service::internal::kSecondProtocol_MethodOnSecond_DynamicFlags);
  const fidl_type_t* req_type = nullptr;
  return proxy_.Send(req_type, ::test::service::SecondProtocol_RequestEncoder::MethodOnSecond(&_encoder));
}
}  // namespace service
}  // namespace test
#endif  // __Fuchsia__

#ifdef __Fuchsia__

namespace test {
namespace service {
FirstProtocol::~FirstProtocol() = default;

const fidl_type_t* ::test::service::FirstProtocol_RequestDecoder::GetType(uint64_t ordinal, bool* out_needs_response) {
  *out_needs_response = false;
  switch (ordinal) {
    case ::test::service::internal::kFirstProtocol_MethodOnFirst_Ordinal:
      return nullptr;
      ;
    default:
      return nullptr;
  }
}

const fidl_type_t* FirstProtocol_ResponseDecoder::GetType(uint64_t ordinal) {
  switch (ordinal) {
    default:
      return nullptr;
  }
}

FirstProtocol_EventSender::~FirstProtocol_EventSender() = default;

FirstProtocol_Sync::~FirstProtocol_Sync() = default;

FirstProtocol_Proxy::FirstProtocol_Proxy(::fidl::internal::ProxyController* controller)
    : controller_(controller) {
  (void)controller_;
}

FirstProtocol_Proxy::~FirstProtocol_Proxy() = default;

zx_status_t FirstProtocol_Proxy::Dispatch_(::fidl::HLCPPIncomingMessage message) {
  zx_status_t status = ZX_OK;
  switch (message.ordinal()) {
    default: {
      status = ZX_ERR_NOT_SUPPORTED;
      break;
    }
  }
  return status;
}

void FirstProtocol_Proxy::MethodOnFirst() {
  ::fidl::MessageEncoder _encoder(::test::service::internal::kFirstProtocol_MethodOnFirst_Ordinal, ::test::service::internal::kFirstProtocol_MethodOnFirst_DynamicFlags);
  const fidl_type_t* req_type = nullptr;
  controller_->Send(req_type, ::test::service::FirstProtocol_RequestEncoder::MethodOnFirst(&_encoder), nullptr);
}

FirstProtocol_Stub::FirstProtocol_Stub(::test::service::FirstProtocol_Stub::FirstProtocol_clazz* impl) : impl_(impl) {
  (void)impl_;
}

FirstProtocol_Stub::~FirstProtocol_Stub() = default;

namespace {

}  // namespace

zx_status_t FirstProtocol_Stub::Dispatch_(
    ::fidl::HLCPPIncomingMessage message,
    ::fidl::internal::PendingResponse response) {
  bool needs_response;
  const fidl_type_t* request_type = ::test::service::FirstProtocol_RequestDecoder::GetType(message.ordinal(), &needs_response);
  if (!message.has_only_header()) {
    if (request_type == nullptr) {
      return ZX_ERR_NOT_SUPPORTED;
    }
    const char* error_msg = nullptr;
    zx_status_t status = message.Decode(request_type, &error_msg);
    if (status != ZX_OK) {
      FIDL_REPORT_DECODING_ERROR(message, request_type, error_msg);
      return status;
    }
  }

  if (response.needs_response() != needs_response) {
    if (needs_response) {
      FIDL_REPORT_DECODING_ERROR(message, request_type, "Message needing a response with no txid");
    } else {
      FIDL_REPORT_DECODING_ERROR(message, request_type, "Message not needing a response with a txid");
    }
    return ZX_ERR_INVALID_ARGS;
  }

  uint64_t ordinal = message.ordinal();
  switch (ordinal) {
    case ::test::service::internal::kFirstProtocol_MethodOnFirst_Ordinal: {
      impl_->MethodOnFirst();
      break;
    }
    default: {
      return ZX_ERR_NOT_SUPPORTED;
    }
  }
  return ZX_OK;
}

FirstProtocol_SyncProxy::FirstProtocol_SyncProxy(::zx::channel channel)
    : proxy_(::std::move(channel)) {}

FirstProtocol_SyncProxy::~FirstProtocol_SyncProxy() = default;

zx_status_t FirstProtocol_SyncProxy::MethodOnFirst() {
  ::fidl::MessageEncoder _encoder(::test::service::internal::kFirstProtocol_MethodOnFirst_Ordinal, ::test::service::internal::kFirstProtocol_MethodOnFirst_DynamicFlags);
  const fidl_type_t* req_type = nullptr;
  return proxy_.Send(req_type, ::test::service::FirstProtocol_RequestEncoder::MethodOnFirst(&_encoder));
}
}  // namespace service
}  // namespace test
#endif  // __Fuchsia__
