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

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

#include <memory>

namespace llcpp {

namespace fidl {
namespace test {
namespace emptystruct {

namespace {

[[maybe_unused]] constexpr uint64_t kEmptyProtocol_Send_Ordinal =
    2183815705502904104lu;
extern "C" const fidl_type_t
    fidl_test_emptystruct_EmptyProtocolSendRequestTable;
extern "C" const fidl_type_t
    fidl_test_emptystruct_EmptyProtocolSendResponseTable;
[[maybe_unused]] constexpr uint64_t kEmptyProtocol_Receive_Ordinal =
    5025214662316626400lu;
extern "C" const fidl_type_t
    fidl_test_emptystruct_EmptyProtocolReceiveRequestTable;
extern "C" const fidl_type_t
    fidl_test_emptystruct_EmptyProtocolReceiveEventTable;
[[maybe_unused]] constexpr uint64_t kEmptyProtocol_SendAndReceive_Ordinal =
    6253929606062814577lu;
extern "C" const fidl_type_t
    fidl_test_emptystruct_EmptyProtocolSendAndReceiveRequestTable;
extern "C" const fidl_type_t
    fidl_test_emptystruct_EmptyProtocolSendAndReceiveResponseTable;

}  // namespace
EmptyProtocol::ResultOf::Send::Send(
    zx_handle_t _client, ::llcpp::fidl::test::emptystruct::Empty& e) {
  SendRequest::OwnedEncodedMessage _request(zx_txid_t(0), e);
  _request.GetOutgoingMessage().Write(_client);
  status_ = _request.status();
  error_ = _request.error();
}

EmptyProtocol::UnownedResultOf::Send::Send(
    zx_handle_t _client, uint8_t* _request_bytes,
    uint32_t _request_byte_capacity,
    ::llcpp::fidl::test::emptystruct::Empty& e) {
  SendRequest::UnownedEncodedMessage _request(_request_bytes,
                                              _request_byte_capacity, 0, e);
  _request.GetOutgoingMessage().Write(_client);
  status_ = _request.status();
  error_ = _request.error();
}

EmptyProtocol::ResultOf::SendAndReceive::SendAndReceive(
    zx_handle_t _client, ::llcpp::fidl::test::emptystruct::Empty& e) {
  SendAndReceiveRequest::OwnedEncodedMessage _request(zx_txid_t(0), e);
  _request.GetOutgoingMessage().Call<SendAndReceiveResponse>(
      _client, bytes_,
      SendAndReceiveResponse::PrimarySize +
          SendAndReceiveResponse::MaxOutOfLine);
  status_ = _request.status();
  error_ = _request.error();
}

EmptyProtocol::ResultOf::SendAndReceive::SendAndReceive(
    zx_handle_t _client, ::llcpp::fidl::test::emptystruct::Empty& e,
    zx_time_t _deadline) {
  SendAndReceiveRequest::OwnedEncodedMessage _request(zx_txid_t(0), e);
  _request.GetOutgoingMessage().Call<SendAndReceiveResponse>(
      _client, bytes_,
      SendAndReceiveResponse::PrimarySize +
          SendAndReceiveResponse::MaxOutOfLine,
      _deadline);
  status_ = _request.status();
  error_ = _request.error();
}

EmptyProtocol::UnownedResultOf::SendAndReceive::SendAndReceive(
    zx_handle_t _client, uint8_t* _request_bytes,
    uint32_t _request_byte_capacity, ::llcpp::fidl::test::emptystruct::Empty& e,
    uint8_t* _response_bytes, uint32_t _response_byte_capacity)
    : bytes_(_response_bytes) {
  SendAndReceiveRequest::UnownedEncodedMessage _request(
      _request_bytes, _request_byte_capacity, 0, e);
  _request.GetOutgoingMessage().Call<SendAndReceiveResponse>(
      _client, _response_bytes, _response_byte_capacity);
  status_ = _request.status();
  error_ = _request.error();
}

::fidl::Result EmptyProtocol::ClientImpl::Send(
    ::llcpp::fidl::test::emptystruct::Empty e) {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    auto _res = ResultOf::Send(_channel->handle(), e);
    return ::fidl::Result(_res.status(), _res.error());
  }
  return ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound);
}

::fidl::Result EmptyProtocol::ClientImpl::Send(
    ::fidl::BufferSpan _request_buffer,
    ::llcpp::fidl::test::emptystruct::Empty e) {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    auto _res = UnownedResultOf::Send(_channel->handle(), _request_buffer.data,
                                      _request_buffer.capacity, e);
    return ::fidl::Result(_res.status(), _res.error());
  }
  return ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound);
}

EmptyProtocol::ResultOf::SendAndReceive
EmptyProtocol::ClientImpl::SendAndReceive_Sync(
    ::llcpp::fidl::test::emptystruct::Empty e) {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    return ResultOf::SendAndReceive(_channel->handle(), e);
  }
  return EmptyProtocol::ResultOf::SendAndReceive(
      ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound));
}

EmptyProtocol::UnownedResultOf::SendAndReceive
EmptyProtocol::ClientImpl::SendAndReceive_Sync(
    ::fidl::BufferSpan _request_buffer,
    ::llcpp::fidl::test::emptystruct::Empty e,
    ::fidl::BufferSpan _response_buffer) {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    return UnownedResultOf::SendAndReceive(
        _channel->handle(), _request_buffer.data, _request_buffer.capacity, e,
        _response_buffer.data, _response_buffer.capacity);
  }
  return EmptyProtocol::UnownedResultOf::SendAndReceive(
      ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound));
}

EmptyProtocol::SendAndReceiveResponseContext::SendAndReceiveResponseContext()
    : ::fidl::internal::ResponseContext(SendAndReceiveResponse::Type,
                                        kEmptyProtocol_SendAndReceive_Ordinal) {
}

void EmptyProtocol::SendAndReceiveResponseContext::OnReply(uint8_t* reply) {
  OnReply(reinterpret_cast<SendAndReceiveResponse*>(reply));
}

::fidl::Result EmptyProtocol::ClientImpl::SendAndReceive(
    ::llcpp::fidl::test::emptystruct::Empty e,
    ::fit::callback<void(SendAndReceiveResponse* response)> _cb) {
  class ResponseContext final : public SendAndReceiveResponseContext {
   public:
    ResponseContext(::fit::callback<void(SendAndReceiveResponse* response)> cb)
        : cb_(std::move(cb)) {}

    void OnReply(SendAndReceiveResponse* response) override {
      cb_(response);

      delete this;
    }

    void OnError() override { delete this; }

   private:
    ::fit::callback<void(SendAndReceiveResponse* response)> cb_;
  };

  auto* _context = new ResponseContext(std::move(_cb));
  ::fidl::internal::ClientBase::PrepareAsyncTxn(_context);
  SendAndReceiveRequest::OwnedEncodedMessage _request(_context->Txid(), e);
  return _request.GetOutgoingMessage().Write(this, _context);
}

::fidl::Result EmptyProtocol::ClientImpl::SendAndReceive(
    ::fidl::BufferSpan _request_buffer,
    ::llcpp::fidl::test::emptystruct::Empty e,
    SendAndReceiveResponseContext* _context) {
  ::fidl::internal::ClientBase::PrepareAsyncTxn(_context);

  SendAndReceiveRequest::UnownedEncodedMessage _request(
      _request_buffer.data, _request_buffer.capacity, _context->Txid(), e);
  return _request.GetOutgoingMessage().Write(this, _context);
}

std::optional<::fidl::UnbindInfo> EmptyProtocol::ClientImpl::DispatchEvent(
    fidl_incoming_msg_t* msg) {
  fidl_message_header_t* hdr =
      reinterpret_cast<fidl_message_header_t*>(msg->bytes);
  switch (hdr->ordinal) {
    case kEmptyProtocol_Receive_Ordinal: {
      const char* error_message;
      zx_status_t status =
          fidl_decode_etc(ReceiveResponse::Type, msg->bytes, msg->num_bytes,
                          msg->handles, msg->num_handles, &error_message);
      if (status != ZX_OK) {
        return ::fidl::UnbindInfo{::fidl::UnbindInfo::kDecodeError, status};
      }
      if (!handlers_.receive) {
        return ::fidl::UnbindInfo{::fidl::UnbindInfo::kUnexpectedMessage,
                                  ZX_ERR_NOT_SUPPORTED};
      }
      handlers_.receive(reinterpret_cast<ReceiveResponse*>(msg->bytes));
      break;
    }
    default:
      FidlHandleInfoCloseMany(msg->handles, msg->num_handles);
      return ::fidl::UnbindInfo{::fidl::UnbindInfo::kUnexpectedMessage,
                                ZX_ERR_NOT_SUPPORTED};
  }
  return {};
}

::fidl::Result EmptyProtocol::EventHandler::HandleOneEvent(
    ::zx::unowned_channel client_end) {
  zx_status_t status =
      client_end->wait_one(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED,
                           ::zx::time::infinite(), nullptr);
  if (status != ZX_OK) {
    return ::fidl::Result(status, ::fidl::kErrorWaitOneFailed);
  }
  constexpr uint32_t kReadAllocSize = ([]() constexpr {
    uint32_t x = 0;
    if (::fidl::internal::ClampedMessageSize<
            ReceiveResponse, ::fidl::MessageDirection::kReceiving>() >= x) {
      x = ::fidl::internal::ClampedMessageSize<
          ReceiveResponse, ::fidl::MessageDirection::kReceiving>();
    }
    return x;
  })();
  constexpr uint32_t kHandleAllocSize = ([]() constexpr {
    uint32_t x = 0;
    if (ReceiveResponse::MaxNumHandles >= x) {
      x = ReceiveResponse::MaxNumHandles;
    }
    if (x > ZX_CHANNEL_MAX_MSG_HANDLES) {
      x = ZX_CHANNEL_MAX_MSG_HANDLES;
    }
    return x;
  })();
  ::fidl::internal::ByteStorage<kReadAllocSize> read_storage;
  uint8_t* read_bytes = read_storage.data();
  zx_handle_info_t read_handles[kHandleAllocSize];
  uint32_t actual_bytes;
  uint32_t actual_handles;
  status = client_end->read_etc(ZX_CHANNEL_READ_MAY_DISCARD, read_bytes,
                                read_handles, kReadAllocSize, kHandleAllocSize,
                                &actual_bytes, &actual_handles);
  if (status == ZX_ERR_BUFFER_TOO_SMALL) {
    // Message size is unexpectedly larger than calculated.
    // This can only be due to a newer version of the protocol defining a new
    // event, whose size exceeds the maximum of known events in the current
    // protocol.
    return ::fidl::Result(Unknown(), nullptr);
  }
  if (status != ZX_OK) {
    return ::fidl::Result(status, ::fidl::kErrorReadFailed);
  }
  if (actual_bytes < sizeof(fidl_message_header_t)) {
    FidlHandleInfoCloseMany(read_handles, actual_handles);
    return ::fidl::Result(ZX_ERR_INVALID_ARGS, ::fidl::kErrorInvalidHeader);
  }
  fidl_message_header_t* hdr =
      reinterpret_cast<fidl_message_header_t*>(read_bytes);
  status = fidl_validate_txn_header(hdr);
  if (status != ZX_OK) {
    FidlHandleInfoCloseMany(read_handles, actual_handles);
    return ::fidl::Result(status, ::fidl::kErrorInvalidHeader);
  }
  switch (hdr->ordinal) {
    case kEmptyProtocol_Receive_Ordinal: {
      const char* error_message;
      zx_status_t status =
          fidl_decode_etc(ReceiveResponse::Type, read_bytes, actual_bytes,
                          read_handles, actual_handles, &error_message);
      if (status != ZX_OK) {
        return ::fidl::Result(status, error_message);
      }
      Receive(reinterpret_cast<ReceiveResponse*>(read_bytes));
      return ::fidl::Result(ZX_OK, nullptr);
    }
    default: {
      FidlHandleInfoCloseMany(read_handles, actual_handles);
      return ::fidl::Result(Unknown(), nullptr);
    }
  }
}

namespace methods {

void EmptyProtocolDispatchSend(void* interface, void* bytes,
                               ::fidl::Transaction* txn) {
  auto message = reinterpret_cast<EmptyProtocol::SendRequest*>(bytes);
  EmptyProtocol::Interface::SendCompleter::Sync completer(txn);
  reinterpret_cast<EmptyProtocol::Interface*>(interface)->Send(
      std::move(message->e), completer);
}

void EmptyProtocolDispatchSendAndReceive(void* interface, void* bytes,
                                         ::fidl::Transaction* txn) {
  auto message = reinterpret_cast<EmptyProtocol::SendAndReceiveRequest*>(bytes);
  EmptyProtocol::Interface::SendAndReceiveCompleter::Sync completer(txn);
  reinterpret_cast<EmptyProtocol::Interface*>(interface)->SendAndReceive(
      std::move(message->e), completer);
}

}  // namespace methods

namespace entries {

::fidl::internal::MethodEntry EmptyProtocol[] = {
    {kEmptyProtocol_Send_Ordinal, EmptyProtocol::SendRequest::Type,
     methods::EmptyProtocolDispatchSend},
    {kEmptyProtocol_SendAndReceive_Ordinal,
     EmptyProtocol::SendAndReceiveRequest::Type,
     methods::EmptyProtocolDispatchSendAndReceive},
};

}  // namespace entries

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

::fidl::DispatchResult EmptyProtocol::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 EmptyProtocol::Interface::dispatch_message(
    fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  return EmptyProtocol::Dispatch(this, msg, txn);
}

::fidl::Result EmptyProtocol::Interface::SendAndReceiveCompleterBase::Reply(
    ::llcpp::fidl::test::emptystruct::Empty e) {
  SendAndReceiveResponse::OwnedEncodedMessage _response{e};
  return CompleterBase::SendReply(&_response.GetOutgoingMessage());
}

::fidl::Result EmptyProtocol::Interface::SendAndReceiveCompleterBase::Reply(
    ::fidl::BufferSpan _buffer, ::llcpp::fidl::test::emptystruct::Empty e) {
  SendAndReceiveResponse::UnownedEncodedMessage _response(_buffer.data,
                                                          _buffer.capacity, e);
  return CompleterBase::SendReply(&_response.GetOutgoingMessage());
}

void EmptyProtocol::SendRequest::_InitHeader(zx_txid_t _txid) {
  fidl_init_txn_header(&_hdr, _txid, kEmptyProtocol_Send_Ordinal);
}

void EmptyProtocol::ReceiveResponse::_InitHeader() {
  fidl_init_txn_header(&_hdr, 0, kEmptyProtocol_Receive_Ordinal);
}

void EmptyProtocol::SendAndReceiveRequest::_InitHeader(zx_txid_t _txid) {
  fidl_init_txn_header(&_hdr, _txid, kEmptyProtocol_SendAndReceive_Ordinal);
}

void EmptyProtocol::SendAndReceiveResponse::_InitHeader() {
  fidl_init_txn_header(&_hdr, 0, kEmptyProtocol_SendAndReceive_Ordinal);
}

zx_status_t EmptyProtocol::EventSender::Receive(
    ::llcpp::fidl::test::emptystruct::Empty e) const {
  ReceiveResponse::OwnedEncodedMessage _response{e};
  _response.Write(server_end_.get());
  return _response.status();
}

zx_status_t EmptyProtocol::EventSender::Receive(
    ::fidl::BufferSpan _buffer,
    ::llcpp::fidl::test::emptystruct::Empty e) const {
  ReceiveResponse::UnownedEncodedMessage _response(_buffer.data,
                                                   _buffer.capacity, e);
  _response.Write(server_end_.get());
  return _response.status();
}

}  // namespace emptystruct
}  // namespace test
}  // namespace fidl
}  // namespace llcpp
