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

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

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

//
// Domain objects definitions (i.e. "natural types" in unified bindings)
//
namespace fidl {
namespace test {
namespace service {}  // namespace service
}  // namespace test
}  // namespace fidl

//
// Proxies and stubs definitions
//
namespace fidl {
namespace test {
namespace service {

#ifdef __Fuchsia__
namespace {

extern "C" const fidl_type_t
    fidl_test_service_SecondProtocolMethodOnSecondRequestTable;

}  // namespace

SecondProtocol::~SecondProtocol() = default;

const fidl_type_t* SecondProtocol_RequestDecoder::GetType(
    uint64_t ordinal, bool* out_needs_response) {
  switch (ordinal) {
    case internal::kSecondProtocol_MethodOnSecond_Ordinal:
      *out_needs_response = false;
      return &fidl_test_service_SecondProtocolMethodOnSecondRequestTable;
    default:
      *out_needs_response = false;
      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::Encoder _encoder(internal::kSecondProtocol_MethodOnSecond_Ordinal);
  controller_->Send(&fidl_test_service_SecondProtocolMethodOnSecondRequestTable,
                    SecondProtocol_RequestEncoder::MethodOnSecond(&_encoder),
                    nullptr);
}

SecondProtocol_Stub::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 = SecondProtocol_RequestDecoder::GetType(
      message.ordinal(), &needs_response);
  if (request_type == nullptr) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  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;
  }
  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;
  }
  uint64_t ordinal = message.ordinal();
  switch (ordinal) {
    case internal::kSecondProtocol_MethodOnSecond_Ordinal: {
      impl_->MethodOnSecond();
      break;
    }
    default: {
      status = ZX_ERR_NOT_SUPPORTED;
      break;
    }
  }
  return status;
}

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

SecondProtocol_SyncProxy::~SecondProtocol_SyncProxy() = default;

zx_status_t SecondProtocol_SyncProxy::MethodOnSecond() {
  ::fidl::Encoder _encoder(internal::kSecondProtocol_MethodOnSecond_Ordinal);
  return proxy_.Send(
      &fidl_test_service_SecondProtocolMethodOnSecondRequestTable,
      SecondProtocol_RequestEncoder::MethodOnSecond(&_encoder));
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__
namespace {

extern "C" const fidl_type_t
    fidl_test_service_FirstProtocolMethodOnFirstRequestTable;

}  // namespace

FirstProtocol::~FirstProtocol() = default;

const fidl_type_t* FirstProtocol_RequestDecoder::GetType(
    uint64_t ordinal, bool* out_needs_response) {
  switch (ordinal) {
    case internal::kFirstProtocol_MethodOnFirst_Ordinal:
      *out_needs_response = false;
      return &fidl_test_service_FirstProtocolMethodOnFirstRequestTable;
    default:
      *out_needs_response = false;
      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::Encoder _encoder(internal::kFirstProtocol_MethodOnFirst_Ordinal);
  controller_->Send(&fidl_test_service_FirstProtocolMethodOnFirstRequestTable,
                    FirstProtocol_RequestEncoder::MethodOnFirst(&_encoder),
                    nullptr);
}

FirstProtocol_Stub::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 =
      FirstProtocol_RequestDecoder::GetType(message.ordinal(), &needs_response);
  if (request_type == nullptr) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  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;
  }
  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;
  }
  uint64_t ordinal = message.ordinal();
  switch (ordinal) {
    case internal::kFirstProtocol_MethodOnFirst_Ordinal: {
      impl_->MethodOnFirst();
      break;
    }
    default: {
      status = ZX_ERR_NOT_SUPPORTED;
      break;
    }
  }
  return status;
}

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

FirstProtocol_SyncProxy::~FirstProtocol_SyncProxy() = default;

zx_status_t FirstProtocol_SyncProxy::MethodOnFirst() {
  ::fidl::Encoder _encoder(internal::kFirstProtocol_MethodOnFirst_Ordinal);
  return proxy_.Send(&fidl_test_service_FirstProtocolMethodOnFirstRequestTable,
                     FirstProtocol_RequestEncoder::MethodOnFirst(&_encoder));
}

#endif  // __Fuchsia__

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