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

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

#include <memory>

namespace llcpp {

namespace fidl {
namespace test {
namespace inheritance {

namespace {

[[maybe_unused]] constexpr uint64_t ksuper_foo_Ordinal = 4999045011615110827lu;
extern "C" const fidl_type_t fidl_test_inheritance_superfooRequestTable;
extern "C" const fidl_type_t fidl_test_inheritance_superfooResponseTable;

}  // namespace
super::ResultOf::foo::foo(zx_handle_t _client, const ::fidl::StringView& s) {
  fooRequest::OwnedEncodedMessage _request(zx_txid_t(0), s);
  _request.GetOutgoingMessage().Call<fooResponse>(
      _client, bytes_, fooResponse::PrimarySize + fooResponse::MaxOutOfLine);
  status_ = _request.status();
  error_ = _request.error();
}

super::ResultOf::foo::foo(zx_handle_t _client, const ::fidl::StringView& s,
                          zx_time_t _deadline) {
  fooRequest::OwnedEncodedMessage _request(zx_txid_t(0), s);
  _request.GetOutgoingMessage().Call<fooResponse>(
      _client, bytes_, fooResponse::PrimarySize + fooResponse::MaxOutOfLine,
      _deadline);
  status_ = _request.status();
  error_ = _request.error();
}

super::UnownedResultOf::foo::foo(zx_handle_t _client, uint8_t* _request_bytes,
                                 uint32_t _request_byte_capacity,
                                 const ::fidl::StringView& s,
                                 uint8_t* _response_bytes,
                                 uint32_t _response_byte_capacity)
    : bytes_(_response_bytes) {
  fooRequest::UnownedEncodedMessage _request(_request_bytes,
                                             _request_byte_capacity, 0, s);
  _request.GetOutgoingMessage().Call<fooResponse>(_client, _response_bytes,
                                                  _response_byte_capacity);
  status_ = _request.status();
  error_ = _request.error();
}

super::ResultOf::foo super::ClientImpl::foo_Sync(::fidl::StringView s) {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    return ResultOf::foo(_channel->handle(), s);
  }
  return super::ResultOf::foo(
      ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound));
}

super::UnownedResultOf::foo super::ClientImpl::foo_Sync(
    ::fidl::BufferSpan _request_buffer, ::fidl::StringView s,
    ::fidl::BufferSpan _response_buffer) {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    return UnownedResultOf::foo(
        _channel->handle(), _request_buffer.data, _request_buffer.capacity, s,
        _response_buffer.data, _response_buffer.capacity);
  }
  return super::UnownedResultOf::foo(
      ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound));
}

super::fooResponseContext::fooResponseContext()
    : ::fidl::internal::ResponseContext(fooResponse::Type, ksuper_foo_Ordinal) {
}

void super::fooResponseContext::OnReply(uint8_t* reply) {
  OnReply(reinterpret_cast<fooResponse*>(reply));
}

::fidl::Result super::ClientImpl::foo(
    ::fidl::StringView s, ::fit::callback<void(fooResponse* response)> _cb) {
  class ResponseContext final : public fooResponseContext {
   public:
    ResponseContext(::fit::callback<void(fooResponse* response)> cb)
        : cb_(std::move(cb)) {}

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

      delete this;
    }

    void OnError() override { delete this; }

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

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

::fidl::Result super::ClientImpl::foo(::fidl::BufferSpan _request_buffer,
                                      ::fidl::StringView s,
                                      fooResponseContext* _context) {
  ::fidl::internal::ClientBase::PrepareAsyncTxn(_context);

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

std::optional<::fidl::UnbindInfo> super::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 superDispatchfoo(void* interface, void* bytes, ::fidl::Transaction* txn) {
  auto message = reinterpret_cast<super::fooRequest*>(bytes);
  super::Interface::fooCompleter::Sync completer(txn);
  reinterpret_cast<super::Interface*>(interface)->foo(std::move(message->s),
                                                      completer);
}

}  // namespace methods

namespace entries {

::fidl::internal::MethodEntry super[] = {
    {ksuper_foo_Ordinal, super::fooRequest::Type, methods::superDispatchfoo},
};

}  // namespace entries

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

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

::fidl::Result super::Interface::fooCompleterBase::Reply(int64_t y) {
  fooResponse::OwnedEncodedMessage _response{y};
  return CompleterBase::SendReply(&_response.GetOutgoingMessage());
}

::fidl::Result super::Interface::fooCompleterBase::Reply(
    ::fidl::BufferSpan _buffer, int64_t y) {
  fooResponse::UnownedEncodedMessage _response(_buffer.data, _buffer.capacity,
                                               y);
  return CompleterBase::SendReply(&_response.GetOutgoingMessage());
}

void super::fooRequest::_InitHeader(zx_txid_t _txid) {
  fidl_init_txn_header(&_hdr, _txid, ksuper_foo_Ordinal);
}

void super::fooResponse::_InitHeader() {
  fidl_init_txn_header(&_hdr, 0, ksuper_foo_Ordinal);
}

namespace {

[[maybe_unused]] constexpr uint64_t ksub_foo_Ordinal = 4999045011615110827lu;
extern "C" const fidl_type_t fidl_test_inheritance_subfooRequestTable;
extern "C" const fidl_type_t fidl_test_inheritance_subfooResponseTable;

}  // namespace
sub::ResultOf::foo::foo(zx_handle_t _client, const ::fidl::StringView& s) {
  fooRequest::OwnedEncodedMessage _request(zx_txid_t(0), s);
  _request.GetOutgoingMessage().Call<fooResponse>(
      _client, bytes_, fooResponse::PrimarySize + fooResponse::MaxOutOfLine);
  status_ = _request.status();
  error_ = _request.error();
}

sub::ResultOf::foo::foo(zx_handle_t _client, const ::fidl::StringView& s,
                        zx_time_t _deadline) {
  fooRequest::OwnedEncodedMessage _request(zx_txid_t(0), s);
  _request.GetOutgoingMessage().Call<fooResponse>(
      _client, bytes_, fooResponse::PrimarySize + fooResponse::MaxOutOfLine,
      _deadline);
  status_ = _request.status();
  error_ = _request.error();
}

sub::UnownedResultOf::foo::foo(zx_handle_t _client, uint8_t* _request_bytes,
                               uint32_t _request_byte_capacity,
                               const ::fidl::StringView& s,
                               uint8_t* _response_bytes,
                               uint32_t _response_byte_capacity)
    : bytes_(_response_bytes) {
  fooRequest::UnownedEncodedMessage _request(_request_bytes,
                                             _request_byte_capacity, 0, s);
  _request.GetOutgoingMessage().Call<fooResponse>(_client, _response_bytes,
                                                  _response_byte_capacity);
  status_ = _request.status();
  error_ = _request.error();
}

sub::ResultOf::foo sub::ClientImpl::foo_Sync(::fidl::StringView s) {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    return ResultOf::foo(_channel->handle(), s);
  }
  return sub::ResultOf::foo(
      ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound));
}

sub::UnownedResultOf::foo sub::ClientImpl::foo_Sync(
    ::fidl::BufferSpan _request_buffer, ::fidl::StringView s,
    ::fidl::BufferSpan _response_buffer) {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    return UnownedResultOf::foo(
        _channel->handle(), _request_buffer.data, _request_buffer.capacity, s,
        _response_buffer.data, _response_buffer.capacity);
  }
  return sub::UnownedResultOf::foo(
      ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound));
}

sub::fooResponseContext::fooResponseContext()
    : ::fidl::internal::ResponseContext(fooResponse::Type, ksub_foo_Ordinal) {}

void sub::fooResponseContext::OnReply(uint8_t* reply) {
  OnReply(reinterpret_cast<fooResponse*>(reply));
}

::fidl::Result sub::ClientImpl::foo(
    ::fidl::StringView s, ::fit::callback<void(fooResponse* response)> _cb) {
  class ResponseContext final : public fooResponseContext {
   public:
    ResponseContext(::fit::callback<void(fooResponse* response)> cb)
        : cb_(std::move(cb)) {}

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

      delete this;
    }

    void OnError() override { delete this; }

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

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

::fidl::Result sub::ClientImpl::foo(::fidl::BufferSpan _request_buffer,
                                    ::fidl::StringView s,
                                    fooResponseContext* _context) {
  ::fidl::internal::ClientBase::PrepareAsyncTxn(_context);

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

std::optional<::fidl::UnbindInfo> sub::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 subDispatchfoo(void* interface, void* bytes, ::fidl::Transaction* txn) {
  auto message = reinterpret_cast<sub::fooRequest*>(bytes);
  sub::Interface::fooCompleter::Sync completer(txn);
  reinterpret_cast<sub::Interface*>(interface)->foo(std::move(message->s),
                                                    completer);
}

}  // namespace methods

namespace entries {

::fidl::internal::MethodEntry sub[] = {
    {ksub_foo_Ordinal, sub::fooRequest::Type, methods::subDispatchfoo},
};

}  // namespace entries

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

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

::fidl::Result sub::Interface::fooCompleterBase::Reply(int64_t y) {
  fooResponse::OwnedEncodedMessage _response{y};
  return CompleterBase::SendReply(&_response.GetOutgoingMessage());
}

::fidl::Result sub::Interface::fooCompleterBase::Reply(
    ::fidl::BufferSpan _buffer, int64_t y) {
  fooResponse::UnownedEncodedMessage _response(_buffer.data, _buffer.capacity,
                                               y);
  return CompleterBase::SendReply(&_response.GetOutgoingMessage());
}

void sub::fooRequest::_InitHeader(zx_txid_t _txid) {
  fidl_init_txn_header(&_hdr, _txid, ksub_foo_Ordinal);
}

void sub::fooResponse::_InitHeader() {
  fidl_init_txn_header(&_hdr, 0, ksub_foo_Ordinal);
}

}  // namespace inheritance
}  // namespace test
}  // namespace fidl
}  // namespace llcpp
