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

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

#include <memory>

#ifdef __Fuchsia__
void ::fidl_test_nullable::wire::StructWithNullableRequest::_CloseHandles() {
  val.reset();
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__
void ::fidl_test_nullable::wire::StructWithNullableProtocol::_CloseHandles() {
  val.reset();
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__
void ::fidl_test_nullable::wire::StructWithNullableHandle::_CloseHandles() {
  val.reset();
}
#endif  // __Fuchsia__

namespace fidl_test_nullable {
[[maybe_unused]] constexpr uint64_t kSimpleProtocol_Add_Ordinal =
    1238508415331800925lu;

extern "C" const fidl_type_t fidl_test_nullable_SimpleProtocolAddRequestTable;

extern "C" const fidl_type_t fidl_test_nullable_SimpleProtocolAddResponseTable;
#ifdef __Fuchsia__
}  // namespace fidl_test_nullable
::fidl::WireResult<::fidl_test_nullable::SimpleProtocol::Add>::WireResult(
    ::fidl::UnownedClientEnd<::fidl_test_nullable::SimpleProtocol> _client,
    int32_t a, int32_t b) {
  ::fidl::OwnedEncodedMessage<
      ::fidl::WireRequest<::fidl_test_nullable::SimpleProtocol::Add>>
      _request(zx_txid_t(0), a, b);
  _request.GetOutgoingMessage()
      .Call<::fidl::WireResponse<::fidl_test_nullable::SimpleProtocol::Add>>(
          _client, bytes_.data(), bytes_.size());
  status_ = _request.status();
  error_ = _request.error();
}

::fidl::WireResult<::fidl_test_nullable::SimpleProtocol::Add>::WireResult(
    ::fidl::UnownedClientEnd<::fidl_test_nullable::SimpleProtocol> _client,
    int32_t a, int32_t b, zx_time_t _deadline) {
  ::fidl::OwnedEncodedMessage<
      ::fidl::WireRequest<::fidl_test_nullable::SimpleProtocol::Add>>
      _request(zx_txid_t(0), a, b);
  _request.GetOutgoingMessage()
      .Call<::fidl::WireResponse<::fidl_test_nullable::SimpleProtocol::Add>>(
          _client, bytes_.data(), bytes_.size(), _deadline);
  status_ = _request.status();
  error_ = _request.error();
}
namespace fidl_test_nullable {
#endif  // __Fuchsia__

#ifdef __Fuchsia__
}  // namespace fidl_test_nullable
::fidl::WireUnownedResult<::fidl_test_nullable::SimpleProtocol::Add>::
    WireUnownedResult(
        ::fidl::UnownedClientEnd<::fidl_test_nullable::SimpleProtocol> _client,
        uint8_t* _request_bytes, uint32_t _request_byte_capacity, int32_t a,
        int32_t b, uint8_t* _response_bytes, uint32_t _response_byte_capacity)
    : bytes_(_response_bytes) {
  ::fidl::UnownedEncodedMessage<
      ::fidl::WireRequest<::fidl_test_nullable::SimpleProtocol::Add>>
      _request(_request_bytes, _request_byte_capacity, 0, a, b);
  _request.GetOutgoingMessage()
      .Call<::fidl::WireResponse<::fidl_test_nullable::SimpleProtocol::Add>>(
          _client, _response_bytes, _response_byte_capacity);
  status_ = _request.status();
  error_ = _request.error();
}
namespace fidl_test_nullable {
#endif  // __Fuchsia__

}  // namespace fidl_test_nullable
#ifdef __Fuchsia__
::fidl::WireResult<::fidl_test_nullable::SimpleProtocol::Add>
fidl::internal::WireClientImpl<::fidl_test_nullable::SimpleProtocol>::Add_Sync(
    int32_t a, int32_t b) {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    return ::fidl::WireResult<::fidl_test_nullable::SimpleProtocol::Add>(
        ::fidl::UnownedClientEnd<::fidl_test_nullable::SimpleProtocol>(
            _channel->handle()),
        a, b);
  }
  return ::fidl::WireResult<::fidl_test_nullable::SimpleProtocol::Add>(
      ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound));
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__
::fidl::WireUnownedResult<::fidl_test_nullable::SimpleProtocol::Add>
fidl::internal::WireClientImpl<::fidl_test_nullable::SimpleProtocol>::Add_Sync(
    ::fidl::BufferSpan _request_buffer, int32_t a, int32_t b,
    ::fidl::BufferSpan _response_buffer) {
  if (auto _channel = ::fidl::internal::ClientBase::GetChannel()) {
    return ::fidl::WireUnownedResult<::fidl_test_nullable::SimpleProtocol::Add>(
        ::fidl::UnownedClientEnd<::fidl_test_nullable::SimpleProtocol>(
            _channel->handle()),
        _request_buffer.data, _request_buffer.capacity, a, b,
        _response_buffer.data, _response_buffer.capacity);
  }
  return ::fidl::WireUnownedResult<::fidl_test_nullable::SimpleProtocol::Add>(
      ::fidl::Result(ZX_ERR_CANCELED, ::fidl::kErrorChannelUnbound));
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__

::fidl::WireResponseContext<
    ::fidl_test_nullable::SimpleProtocol::Add>::WireResponseContext()
    : ::fidl::internal::ResponseContext(
          ::fidl::WireResponse<::fidl_test_nullable::SimpleProtocol::Add>::Type,
          ::fidl_test_nullable::kSimpleProtocol_Add_Ordinal) {}

void ::fidl::WireResponseContext<
    ::fidl_test_nullable::SimpleProtocol::Add>::OnReply(uint8_t* reply) {
  OnReply(reinterpret_cast<
          ::fidl::WireResponse<::fidl_test_nullable::SimpleProtocol::Add>*>(
      reply));
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__
::fidl::Result
fidl::internal::WireClientImpl<::fidl_test_nullable::SimpleProtocol>::Add(
    int32_t a, int32_t b,
    ::fit::callback<void(::fidl::WireResponse<
                         ::fidl_test_nullable::SimpleProtocol::Add>* response)>
        _cb) {
  class ResponseContext final : public ::fidl::WireResponseContext<
                                    ::fidl_test_nullable::SimpleProtocol::Add> {
   public:
    ResponseContext(::fit::callback<
                    void(::fidl::WireResponse<
                         ::fidl_test_nullable::SimpleProtocol::Add>* response)>
                        cb)
        : cb_(std::move(cb)) {}

    void OnReply(
        ::fidl::WireResponse<::fidl_test_nullable::SimpleProtocol::Add>*
            response) override {
      cb_(response);

      delete this;
    }

    void OnError() override { delete this; }

   private:
    ::fit::callback<void(::fidl::WireResponse<
                         ::fidl_test_nullable::SimpleProtocol::Add>* response)>
        cb_;
  };

  auto* _context = new ResponseContext(std::move(_cb));
  ::fidl::internal::ClientBase::PrepareAsyncTxn(_context);
  ::fidl::WireRequest<::fidl_test_nullable::SimpleProtocol::Add>::
      OwnedEncodedMessage _request(_context->Txid(), a, b);
  return _request.GetOutgoingMessage().Write(this, _context);
}

::fidl::Result
fidl::internal::WireClientImpl<::fidl_test_nullable::SimpleProtocol>::Add(
    ::fidl::BufferSpan _request_buffer, int32_t a, int32_t b,
    ::fidl::WireResponseContext<::fidl_test_nullable::SimpleProtocol::Add>*
        _context) {
  ::fidl::internal::ClientBase::PrepareAsyncTxn(_context);

  ::fidl::WireRequest<::fidl_test_nullable::SimpleProtocol::Add>::
      UnownedEncodedMessage _request(_request_buffer.data,
                                     _request_buffer.capacity, _context->Txid(),
                                     a, b);
  return _request.GetOutgoingMessage().Write(this, _context);
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__
std::optional<::fidl::UnbindInfo> fidl::internal::WireClientImpl<
    ::fidl_test_nullable::SimpleProtocol>::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_nullable::SimpleProtocol>::TryDispatch(
        ::fidl::WireServer<::fidl_test_nullable::SimpleProtocol>* impl,
        fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  static const ::fidl::internal::MethodEntry entries[] = {
      {
          ::fidl_test_nullable::kSimpleProtocol_Add_Ordinal,
          ::fidl::WireRequest<::fidl_test_nullable::SimpleProtocol::Add>::Type,
          [](void* interface, void* bytes, ::fidl::Transaction* txn) {
            ::fidl::WireServer<::fidl_test_nullable::SimpleProtocol>::
                AddCompleter::Sync completer(txn);
            reinterpret_cast<
                ::fidl::WireServer<::fidl_test_nullable::SimpleProtocol>*>(
                interface)
                ->Add(reinterpret_cast<::fidl::WireRequest<
                          ::fidl_test_nullable::SimpleProtocol::Add>*>(bytes),
                      completer);
          },
      },
  };
  return ::fidl::internal::TryDispatch(
      impl, msg, txn, entries,
      entries + sizeof(entries) / sizeof(::fidl::internal::MethodEntry));
}

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

::fidl::DispatchResult fidl::internal::
    WireDispatcher<::fidl_test_nullable::SimpleProtocol>::TryDispatch(
        ::fidl::WireInterface<::fidl_test_nullable::SimpleProtocol>* impl,
        fidl_incoming_msg_t* msg, ::fidl::Transaction* txn) {
  static const ::fidl::internal::MethodEntry entries[] = {
      {
          ::fidl_test_nullable::kSimpleProtocol_Add_Ordinal,
          ::fidl::WireRequest<::fidl_test_nullable::SimpleProtocol::Add>::Type,
          [](void* interface, void* bytes, ::fidl::Transaction* txn) {
            auto message = reinterpret_cast<::fidl::WireRequest<
                ::fidl_test_nullable::SimpleProtocol::Add>*>(bytes);
            ::fidl::WireServer<::fidl_test_nullable::SimpleProtocol>::
                AddCompleter::Sync completer(txn);
            reinterpret_cast<
                ::fidl::WireInterface<::fidl_test_nullable::SimpleProtocol>*>(
                interface)
                ->Add(std::move(message->a), std::move(message->b), completer);
          },
      },
  };
  return ::fidl::internal::TryDispatch(
      impl, msg, txn, entries,
      entries + sizeof(entries) / sizeof(::fidl::internal::MethodEntry));
}

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

#ifdef __Fuchsia__
::fidl::Result
fidl::WireServer<::fidl_test_nullable::SimpleProtocol>::AddCompleterBase::Reply(
    int32_t sum) {
  ::fidl::OwnedEncodedMessage<
      ::fidl::WireResponse<::fidl_test_nullable::SimpleProtocol::Add>>
      _response{sum};
  return ::fidl::WireServer<::fidl_test_nullable::SimpleProtocol>::
      AddCompleterBase::SendReply(&_response.GetOutgoingMessage());
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__
::fidl::Result
fidl::WireServer<::fidl_test_nullable::SimpleProtocol>::AddCompleterBase::Reply(
    ::fidl::BufferSpan _backing_buffer, int32_t sum) {
  ::fidl::WireResponse<::fidl_test_nullable::SimpleProtocol::Add>::
      UnownedEncodedMessage _response(_backing_buffer.data,
                                      _backing_buffer.capacity, sum);
  return CompleterBase::SendReply(&_response.GetOutgoingMessage());
}
#endif  // __Fuchsia__

void ::fidl::WireRequest<
    ::fidl_test_nullable::SimpleProtocol::Add>::_InitHeader(zx_txid_t _txid) {
  fidl_init_txn_header(&_hdr, _txid,
                       ::fidl_test_nullable::kSimpleProtocol_Add_Ordinal);
}

void ::fidl::WireResponse<
    ::fidl_test_nullable::SimpleProtocol::Add>::_InitHeader() {
  fidl_init_txn_header(&_hdr, 0,
                       ::fidl_test_nullable::kSimpleProtocol_Add_Ordinal);
}

#ifdef __Fuchsia__

#endif  // __Fuchsia__

void ::fidl_test_nullable::wire::SimpleUnion::SizeAndOffsetAssertionHelper() {
  static_assert(sizeof(SimpleUnion) == sizeof(fidl_xunion_t));
  static_assert(offsetof(SimpleUnion, ordinal_) ==
                offsetof(fidl_xunion_t, tag));
  static_assert(offsetof(SimpleUnion, envelope_) ==
                offsetof(fidl_xunion_t, envelope));
}
