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

// fidl_experiment = output_index_json

#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 {

FirstProtocol::~FirstProtocol() = default;

const fidl_type_t* ::test::service::FirstProtocol_RequestDecoder::GetType(uint64_t ordinal, bool* out_needs_response, bool* out_is_known) {
  *out_needs_response = false;
  *out_is_known = false;
  switch (ordinal) {
    case ::test::service::internal::kFirstProtocol_MethodOnFirst_Ordinal:
      *out_is_known = true;
      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;
  bool is_known;
  const fidl_type_t* request_type = ::test::service::FirstProtocol_RequestDecoder::GetType(message.ordinal(), &needs_response, &is_known);

  if (!is_known) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  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: {
      // Unknown ordinals are handled at the beginning of dispatching, so this
      // should be unreachable.
      ZX_PANIC("Unreachable: unknown ordinals handled earlier.");
    }
  }
  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__

#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, bool* out_is_known) {
  *out_needs_response = false;
  *out_is_known = false;
  switch (ordinal) {
    case ::test::service::internal::kSecondProtocol_MethodOnSecond_Ordinal:
      *out_is_known = true;
      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;
  bool is_known;
  const fidl_type_t* request_type = ::test::service::SecondProtocol_RequestDecoder::GetType(message.ordinal(), &needs_response, &is_known);

  if (!is_known) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  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: {
      // Unknown ordinals are handled at the beginning of dispatching, so this
      // should be unreachable.
      ZX_PANIC("Unreachable: unknown ordinals handled earlier.");
    }
  }
  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__
