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

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

#include <memory>

namespace llcpp {

namespace fidl {
namespace test {
namespace service {

namespace {

[[maybe_unused]] constexpr uint64_t kSecondProtocol_MethodOnSecond_Ordinal =
    6118813307380259369lu;
extern "C" const fidl_type_t
    fidl_test_service_SecondProtocolMethodOnSecondRequestTable;
extern "C" const fidl_type_t
    fidl_test_service_SecondProtocolMethodOnSecondResponseTable;

}  // namespace
SecondProtocol::ResultOf::MethodOnSecond::MethodOnSecond(zx_handle_t _client) {
  MethodOnSecondRequest::OwnedEncodedMessage _request(zx_txid_t(0));
  _request.GetOutgoingMessage().Write(_client);
  status_ = _request.status();
  error_ = _request.error();
}

::fidl::Result SecondProtocol::ClientImpl::MethodOnSecond() {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    auto _res = ResultOf::MethodOnSecond(_channel->handle());
    return ::fidl::Result(_res.status(), _res.error());
  }
  return ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound);
}

std::optional<::fidl::UnbindInfo> SecondProtocol::ClientImpl::DispatchEvent(
    fidl_incoming_msg_t* msg) {
  fidl_message_header_t* hdr =
      reinterpret_cast<fidl_message_header_t*>(msg->bytes);
  switch (hdr->ordinal) {
    default:
      FidlHandleInfoCloseMany(msg->handles, msg->num_handles);
      return ::fidl::UnbindInfo{::fidl::UnbindInfo::kUnexpectedMessage,
                                ZX_ERR_NOT_SUPPORTED};
  }
  return {};
}

namespace methods {

void SecondProtocolDispatchMethodOnSecond(void* interface, void* bytes,
                                          ::fidl::Transaction* txn) {
  SecondProtocol::Interface::MethodOnSecondCompleter::Sync completer(txn);
  reinterpret_cast<SecondProtocol::Interface*>(interface)->MethodOnSecond(
      completer);
}

}  // namespace methods

namespace entries {

::fidl::internal::MethodEntry SecondProtocol[] = {
    {kSecondProtocol_MethodOnSecond_Ordinal,
     SecondProtocol::MethodOnSecondRequest::Type,
     methods::SecondProtocolDispatchMethodOnSecond},
};

}  // namespace entries

::fidl::DispatchResult SecondProtocol::TryDispatch(Interface* impl,
                                                   fidl_incoming_msg_t* msg,
                                                   ::fidl::Transaction* txn) {
  return ::fidl::internal::TryDispatch(
      impl, msg, txn, entries::SecondProtocol,
      entries::SecondProtocol + sizeof(entries::SecondProtocol) /
                                    sizeof(::fidl::internal::MethodEntry));
}

::fidl::DispatchResult SecondProtocol::Dispatch(Interface* impl,
                                                fidl_incoming_msg_t* msg,
                                                ::fidl::Transaction* txn) {
  ::fidl::DispatchResult dispatch_result = TryDispatch(impl, msg, txn);
  if (dispatch_result == ::fidl::DispatchResult::kNotFound) {
    FidlHandleInfoCloseMany(msg->handles, msg->num_handles);
    txn->InternalError(
        {::fidl::UnbindInfo::kUnexpectedMessage, ZX_ERR_NOT_SUPPORTED});
  }
  return dispatch_result;
}

::fidl::DispatchResult SecondProtocol::Interface::dispatch_message(
    fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  return SecondProtocol::Dispatch(this, msg, txn);
}

void SecondProtocol::MethodOnSecondRequest::_InitHeader(zx_txid_t _txid) {
  fidl_init_txn_header(&_hdr, _txid, kSecondProtocol_MethodOnSecond_Ordinal);
}

namespace {

[[maybe_unused]] constexpr uint64_t kFirstProtocol_MethodOnFirst_Ordinal =
    6590661047173168036lu;
extern "C" const fidl_type_t
    fidl_test_service_FirstProtocolMethodOnFirstRequestTable;
extern "C" const fidl_type_t
    fidl_test_service_FirstProtocolMethodOnFirstResponseTable;

}  // namespace
FirstProtocol::ResultOf::MethodOnFirst::MethodOnFirst(zx_handle_t _client) {
  MethodOnFirstRequest::OwnedEncodedMessage _request(zx_txid_t(0));
  _request.GetOutgoingMessage().Write(_client);
  status_ = _request.status();
  error_ = _request.error();
}

::fidl::Result FirstProtocol::ClientImpl::MethodOnFirst() {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    auto _res = ResultOf::MethodOnFirst(_channel->handle());
    return ::fidl::Result(_res.status(), _res.error());
  }
  return ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound);
}

std::optional<::fidl::UnbindInfo> FirstProtocol::ClientImpl::DispatchEvent(
    fidl_incoming_msg_t* msg) {
  fidl_message_header_t* hdr =
      reinterpret_cast<fidl_message_header_t*>(msg->bytes);
  switch (hdr->ordinal) {
    default:
      FidlHandleInfoCloseMany(msg->handles, msg->num_handles);
      return ::fidl::UnbindInfo{::fidl::UnbindInfo::kUnexpectedMessage,
                                ZX_ERR_NOT_SUPPORTED};
  }
  return {};
}

namespace methods {

void FirstProtocolDispatchMethodOnFirst(void* interface, void* bytes,
                                        ::fidl::Transaction* txn) {
  FirstProtocol::Interface::MethodOnFirstCompleter::Sync completer(txn);
  reinterpret_cast<FirstProtocol::Interface*>(interface)->MethodOnFirst(
      completer);
}

}  // namespace methods

namespace entries {

::fidl::internal::MethodEntry FirstProtocol[] = {
    {kFirstProtocol_MethodOnFirst_Ordinal,
     FirstProtocol::MethodOnFirstRequest::Type,
     methods::FirstProtocolDispatchMethodOnFirst},
};

}  // namespace entries

::fidl::DispatchResult FirstProtocol::TryDispatch(Interface* impl,
                                                  fidl_incoming_msg_t* msg,
                                                  ::fidl::Transaction* txn) {
  return ::fidl::internal::TryDispatch(
      impl, msg, txn, entries::FirstProtocol,
      entries::FirstProtocol + sizeof(entries::FirstProtocol) /
                                   sizeof(::fidl::internal::MethodEntry));
}

::fidl::DispatchResult FirstProtocol::Dispatch(Interface* impl,
                                               fidl_incoming_msg_t* msg,
                                               ::fidl::Transaction* txn) {
  ::fidl::DispatchResult dispatch_result = TryDispatch(impl, msg, txn);
  if (dispatch_result == ::fidl::DispatchResult::kNotFound) {
    FidlHandleInfoCloseMany(msg->handles, msg->num_handles);
    txn->InternalError(
        {::fidl::UnbindInfo::kUnexpectedMessage, ZX_ERR_NOT_SUPPORTED});
  }
  return dispatch_result;
}

::fidl::DispatchResult FirstProtocol::Interface::dispatch_message(
    fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  return FirstProtocol::Dispatch(this, msg, txn);
}

void FirstProtocol::MethodOnFirstRequest::_InitHeader(zx_txid_t _txid) {
  fidl_init_txn_header(&_hdr, _txid, kFirstProtocol_MethodOnFirst_Ordinal);
}

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