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

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

#include <memory>

namespace fidl_test_service {
[[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;
#ifdef __Fuchsia__
}  // namespace fidl_test_service
::fidl::WireResult<::fidl_test_service::SecondProtocol::MethodOnSecond>::
    WireResult(
        ::fidl::UnownedClientEnd<::fidl_test_service::SecondProtocol> _client) {
  ::fidl::OwnedEncodedMessage<
      ::fidl::WireRequest<::fidl_test_service::SecondProtocol::MethodOnSecond>>
      _request(zx_txid_t(0));
  _request.GetOutgoingMessage().Write(_client);
  status_ = _request.status();
  error_ = _request.error();
}
namespace fidl_test_service {
#endif  // __Fuchsia__

}  // namespace fidl_test_service
#ifdef __Fuchsia__
::fidl::Result fidl::internal::WireClientImpl<
    ::fidl_test_service::SecondProtocol>::MethodOnSecond() {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    auto _res =
        ::fidl::WireResult<::fidl_test_service::SecondProtocol::MethodOnSecond>(
            ::fidl::UnownedClientEnd<::fidl_test_service::SecondProtocol>(
                _channel->handle()));
    return ::fidl::Result(_res.status(), _res.error());
  }
  return ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound);
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__
std::optional<::fidl::UnbindInfo> fidl::internal::WireClientImpl<
    ::fidl_test_service::SecondProtocol>::DispatchEvent(fidl_incoming_msg_t*
                                                            msg) {
  FidlHandleInfoCloseMany(msg->handles, msg->num_handles);
  return ::fidl::UnbindInfo{::fidl::UnbindInfo::kUnexpectedMessage,
                            ZX_ERR_NOT_SUPPORTED};
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__

::fidl::DispatchResult fidl::internal::
    WireServerDispatcher<::fidl_test_service::SecondProtocol>::TryDispatch(
        ::fidl::WireServer<::fidl_test_service::SecondProtocol>* impl,
        fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  static const ::fidl::internal::MethodEntry entries[] = {
      {
          ::fidl_test_service::kSecondProtocol_MethodOnSecond_Ordinal,
          ::fidl::WireRequest<
              ::fidl_test_service::SecondProtocol::MethodOnSecond>::Type,
          [](void* interface, void* bytes, ::fidl::Transaction* txn) {
            ::fidl::WireServer<::fidl_test_service::SecondProtocol>::
                MethodOnSecondCompleter::Sync completer(txn);
            reinterpret_cast<
                ::fidl::WireServer<::fidl_test_service::SecondProtocol>*>(
                interface)
                ->MethodOnSecond(
                    reinterpret_cast<::fidl::WireRequest<
                        ::fidl_test_service::SecondProtocol::MethodOnSecond>*>(
                        bytes),
                    completer);
          },
      },
  };
  return ::fidl::internal::TryDispatch(
      impl, msg, txn, entries,
      entries + sizeof(entries) / sizeof(::fidl::internal::MethodEntry));
}

::fidl::DispatchResult fidl::internal::
    WireServerDispatcher<::fidl_test_service::SecondProtocol>::Dispatch(
        ::fidl::WireServer<::fidl_test_service::SecondProtocol>* 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
fidl::WireServer<::fidl_test_service::SecondProtocol>::dispatch_message(
    fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  return ::fidl::internal::WireServerDispatcher<
      ::fidl_test_service::SecondProtocol>::Dispatch(this, msg, txn);
}

::fidl::DispatchResult fidl::internal::
    WireDispatcher<::fidl_test_service::SecondProtocol>::TryDispatch(
        ::fidl::WireInterface<::fidl_test_service::SecondProtocol>* impl,
        fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  static const ::fidl::internal::MethodEntry entries[] = {
      {
          ::fidl_test_service::kSecondProtocol_MethodOnSecond_Ordinal,
          ::fidl::WireRequest<
              ::fidl_test_service::SecondProtocol::MethodOnSecond>::Type,
          [](void* interface, void* bytes, ::fidl::Transaction* txn) {
            ::fidl::WireServer<::fidl_test_service::SecondProtocol>::
                MethodOnSecondCompleter::Sync completer(txn);
            reinterpret_cast<
                ::fidl::WireInterface<::fidl_test_service::SecondProtocol>*>(
                interface)
                ->MethodOnSecond(completer);
          },
      },
  };
  return ::fidl::internal::TryDispatch(
      impl, msg, txn, entries,
      entries + sizeof(entries) / sizeof(::fidl::internal::MethodEntry));
}

::fidl::DispatchResult
fidl::internal::WireDispatcher<::fidl_test_service::SecondProtocol>::Dispatch(
    ::fidl::WireInterface<::fidl_test_service::SecondProtocol>* 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
fidl::WireInterface<::fidl_test_service::SecondProtocol>::dispatch_message(
    fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  return ::fidl::internal::WireDispatcher<
      ::fidl_test_service::SecondProtocol>::Dispatch(this, msg, txn);
}
#endif  // __Fuchsia__

void ::fidl::WireRequest<::fidl_test_service::SecondProtocol::MethodOnSecond>::
    _InitHeader(zx_txid_t _txid) {
  fidl_init_txn_header(
      &_hdr, _txid,
      ::fidl_test_service::kSecondProtocol_MethodOnSecond_Ordinal);
}

#ifdef __Fuchsia__

#endif  // __Fuchsia__

namespace fidl_test_service {
[[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;
#ifdef __Fuchsia__
}  // namespace fidl_test_service
::fidl::WireResult<::fidl_test_service::FirstProtocol::MethodOnFirst>::
    WireResult(
        ::fidl::UnownedClientEnd<::fidl_test_service::FirstProtocol> _client) {
  ::fidl::OwnedEncodedMessage<
      ::fidl::WireRequest<::fidl_test_service::FirstProtocol::MethodOnFirst>>
      _request(zx_txid_t(0));
  _request.GetOutgoingMessage().Write(_client);
  status_ = _request.status();
  error_ = _request.error();
}
namespace fidl_test_service {
#endif  // __Fuchsia__

}  // namespace fidl_test_service
#ifdef __Fuchsia__
::fidl::Result fidl::internal::WireClientImpl<
    ::fidl_test_service::FirstProtocol>::MethodOnFirst() {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    auto _res =
        ::fidl::WireResult<::fidl_test_service::FirstProtocol::MethodOnFirst>(
            ::fidl::UnownedClientEnd<::fidl_test_service::FirstProtocol>(
                _channel->handle()));
    return ::fidl::Result(_res.status(), _res.error());
  }
  return ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound);
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__
std::optional<::fidl::UnbindInfo> fidl::internal::WireClientImpl<
    ::fidl_test_service::FirstProtocol>::DispatchEvent(fidl_incoming_msg_t*
                                                           msg) {
  FidlHandleInfoCloseMany(msg->handles, msg->num_handles);
  return ::fidl::UnbindInfo{::fidl::UnbindInfo::kUnexpectedMessage,
                            ZX_ERR_NOT_SUPPORTED};
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__

::fidl::DispatchResult fidl::internal::
    WireServerDispatcher<::fidl_test_service::FirstProtocol>::TryDispatch(
        ::fidl::WireServer<::fidl_test_service::FirstProtocol>* impl,
        fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  static const ::fidl::internal::MethodEntry entries[] = {
      {
          ::fidl_test_service::kFirstProtocol_MethodOnFirst_Ordinal,
          ::fidl::WireRequest<
              ::fidl_test_service::FirstProtocol::MethodOnFirst>::Type,
          [](void* interface, void* bytes, ::fidl::Transaction* txn) {
            ::fidl::WireServer<::fidl_test_service::FirstProtocol>::
                MethodOnFirstCompleter::Sync completer(txn);
            reinterpret_cast<
                ::fidl::WireServer<::fidl_test_service::FirstProtocol>*>(
                interface)
                ->MethodOnFirst(
                    reinterpret_cast<::fidl::WireRequest<
                        ::fidl_test_service::FirstProtocol::MethodOnFirst>*>(
                        bytes),
                    completer);
          },
      },
  };
  return ::fidl::internal::TryDispatch(
      impl, msg, txn, entries,
      entries + sizeof(entries) / sizeof(::fidl::internal::MethodEntry));
}

::fidl::DispatchResult fidl::internal::
    WireServerDispatcher<::fidl_test_service::FirstProtocol>::Dispatch(
        ::fidl::WireServer<::fidl_test_service::FirstProtocol>* 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
fidl::WireServer<::fidl_test_service::FirstProtocol>::dispatch_message(
    fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  return ::fidl::internal::WireServerDispatcher<
      ::fidl_test_service::FirstProtocol>::Dispatch(this, msg, txn);
}

::fidl::DispatchResult
fidl::internal::WireDispatcher<::fidl_test_service::FirstProtocol>::TryDispatch(
    ::fidl::WireInterface<::fidl_test_service::FirstProtocol>* impl,
    fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  static const ::fidl::internal::MethodEntry entries[] = {
      {
          ::fidl_test_service::kFirstProtocol_MethodOnFirst_Ordinal,
          ::fidl::WireRequest<
              ::fidl_test_service::FirstProtocol::MethodOnFirst>::Type,
          [](void* interface, void* bytes, ::fidl::Transaction* txn) {
            ::fidl::WireServer<::fidl_test_service::FirstProtocol>::
                MethodOnFirstCompleter::Sync completer(txn);
            reinterpret_cast<
                ::fidl::WireInterface<::fidl_test_service::FirstProtocol>*>(
                interface)
                ->MethodOnFirst(completer);
          },
      },
  };
  return ::fidl::internal::TryDispatch(
      impl, msg, txn, entries,
      entries + sizeof(entries) / sizeof(::fidl::internal::MethodEntry));
}

::fidl::DispatchResult
fidl::internal::WireDispatcher<::fidl_test_service::FirstProtocol>::Dispatch(
    ::fidl::WireInterface<::fidl_test_service::FirstProtocol>* 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
fidl::WireInterface<::fidl_test_service::FirstProtocol>::dispatch_message(
    fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  return ::fidl::internal::WireDispatcher<
      ::fidl_test_service::FirstProtocol>::Dispatch(this, msg, txn);
}
#endif  // __Fuchsia__

void ::fidl::WireRequest<::fidl_test_service::FirstProtocol::MethodOnFirst>::
    _InitHeader(zx_txid_t _txid) {
  fidl_init_txn_header(
      &_hdr, _txid, ::fidl_test_service::kFirstProtocol_MethodOnFirst_Ordinal);
}

#ifdef __Fuchsia__

#endif  // __Fuchsia__
