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

#include <fidl/test.nullable/cpp/wire_messaging.h>

#include <memory>

namespace test_nullable {
[[maybe_unused]] constexpr uint64_t kSimpleProtocol_Add_Ordinal =
    9142761280038437494lu;

[[maybe_unused]] constexpr ::fidl::MessageDynamicFlags
    kSimpleProtocol_Add_DynamicFlags =
        ::fidl::MessageDynamicFlags::kStrictMethod;

extern "C" const fidl_type_t test_nullable_SimpleProtocolAddRequestTable;

extern "C" const fidl_type_t test_nullable_SimpleProtocolAddTopResponseTable;
#ifdef __Fuchsia__
}  // namespace test_nullable
::fidl::WireResult<::test_nullable::SimpleProtocol::Add>::WireResult(
    ::fidl::UnownedClientEnd<::test_nullable::SimpleProtocol> client,
    ::fidl::internal::TransactionalRequest<
        ::test_nullable::SimpleProtocol::Add>* request) {
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::unstable::OwnedEncodedMessage<
      ::fidl::internal::TransactionalRequest<
          ::test_nullable::SimpleProtocol::Add>,
      ::fidl::internal::ChannelTransport>
      request_message(::fidl::internal::AllowUnownedInputRef{}, request);
  auto& outgoing = request_message.GetOutgoingMessage();
  outgoing.Call<::fidl::internal::TransactionalResponse<
      ::test_nullable::SimpleProtocol::Add>>(
      client.handle(), bytes_.data(), static_cast<uint32_t>(bytes_.size()));
  SetStatus(outgoing);
}

::fidl::WireResult<::test_nullable::SimpleProtocol::Add>::WireResult(
    ::fidl::UnownedClientEnd<::test_nullable::SimpleProtocol> client,
    ::fidl::internal::TransactionalRequest<
        ::test_nullable::SimpleProtocol::Add>* request,
    zx_time_t deadline) {
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::unstable::OwnedEncodedMessage<
      ::fidl::internal::TransactionalRequest<
          ::test_nullable::SimpleProtocol::Add>,
      ::fidl::internal::ChannelTransport>
      request_message(::fidl::internal::AllowUnownedInputRef{}, request);
  auto& outgoing = request_message.GetOutgoingMessage();
  outgoing.Call<::fidl::internal::TransactionalResponse<
      ::test_nullable::SimpleProtocol::Add>>(
      client.handle(), bytes_.data(), static_cast<uint32_t>(bytes_.size()),
      fidl::CallOptions{.deadline = deadline});
  SetStatus(outgoing);
}
namespace test_nullable {
#endif  // __Fuchsia__

#ifdef __Fuchsia__
}  // namespace test_nullable
::fidl::WireUnownedResult<::test_nullable::SimpleProtocol::Add>::
    WireUnownedResult(
        ::fidl::UnownedClientEnd<::test_nullable::SimpleProtocol> client_end,
        ::fidl::internal::AnyBufferAllocator& allocator,
        ::fidl::internal::TransactionalRequest<
            ::test_nullable::SimpleProtocol::Add>* request) {
  constexpr uint32_t buffer_size = ::fidl::SyncClientMethodBufferSizeInChannel<
      ::test_nullable::SimpleProtocol::Add>();
  ::fitx::result<::fidl::Error, ::fidl::BufferSpan> allocation =
      allocator.TryAllocate(buffer_size);
  if (!allocation.is_ok()) {
    ::fidl::Status::operator=(allocation.error_value());
    return;
  }
  uint8_t* buffer = allocation->data;
  constexpr uint32_t request_byte_capacity =
      ::fidl::MaxSizeInChannel<::fidl::internal::TransactionalRequest<
                                   ::test_nullable::SimpleProtocol::Add>,
                               ::fidl::MessageDirection::kSending>();
  uint8_t* request_bytes = buffer;
  static_assert(buffer_size > request_byte_capacity);
  uint32_t response_byte_capacity = buffer_size - request_byte_capacity;
  uint8_t* response_bytes = &buffer[request_byte_capacity];

  ::fidl::unstable::UnownedEncodedMessage<
      ::fidl::internal::TransactionalRequest<
          ::test_nullable::SimpleProtocol::Add>>
      request_message(request_bytes, request_byte_capacity, request);
  auto& outgoing = request_message.GetOutgoingMessage();
  outgoing.Call<::fidl::internal::TransactionalResponse<
      ::test_nullable::SimpleProtocol::Add>>(
      client_end.handle(), response_bytes, response_byte_capacity);
  bytes_ = response_bytes;
  ::fidl::Status::operator=(outgoing);
}
namespace test_nullable {
#endif  // __Fuchsia__

}  // namespace test_nullable
#ifdef __Fuchsia__

::fidl::internal::WireThenable<::test_nullable::SimpleProtocol::Add>
fidl::internal::WireWeakAsyncClientImpl<::test_nullable::SimpleProtocol>::Add(
    int32_t a, int32_t b) {
  ::fidl::internal::TransactionalRequest<::test_nullable::SimpleProtocol::Add>
      _request{a, b};
  return ::fidl::internal::WireThenable<::test_nullable::SimpleProtocol::Add>{
      _client_base(), ::fidl::WriteOptions{},
      ::fidl::internal::AllowUnownedInputRef{}, &_request};
}
::fidl::internal::WireBufferThenable<::test_nullable::SimpleProtocol::Add>
fidl::internal::WireWeakAsyncBufferClientImpl<
    ::test_nullable::SimpleProtocol>::Add(int32_t a, int32_t b) {
  constexpr uint32_t _buffer_size =
      ::fidl::AsyncClientMethodBufferSizeInChannel<
          ::test_nullable::SimpleProtocol::Add>();
  ::fidl::internal::TransactionalRequest<::test_nullable::SimpleProtocol::Add>
      _request{a, b};
  return ::fidl::internal::WireBufferThenable<
      ::test_nullable::SimpleProtocol::Add>{
      _client_base(), ::fidl::WriteOptions{}, _allocator(), _buffer_size,
      &_request};
}

::fidl::WireResult<::test_nullable::SimpleProtocol::Add>
fidl::internal::WireWeakSyncClientImpl<::test_nullable::SimpleProtocol>::Add(
    int32_t a, int32_t b) {
  return _client_base()->MakeSyncCallWith(
      [&](std::shared_ptr<::fidl::internal::AnyTransport> _transport) {
        ::fidl::internal::TransactionalRequest<
            ::test_nullable::SimpleProtocol::Add>
            _request{a, b};
        return ::fidl::WireResult<::test_nullable::SimpleProtocol::Add>(
            ::fidl::UnownedClientEnd<::test_nullable::SimpleProtocol>(
                _transport->get<::fidl::internal::ChannelTransport>()),
            &_request);
      });
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__

::fidl::Status
fidl::WireSyncEventHandler<::test_nullable::SimpleProtocol>::HandleOneEvent(
    ::fidl::UnownedClientEnd<::test_nullable::SimpleProtocol> client_end) {
  zx_status_t status = client_end.channel()->wait_one(
      ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, ::zx::time::infinite(),
      nullptr);
  if (status != ZX_OK) {
    return ::fidl::Status::TransportError(
        status, ::fidl::internal::kErrorWaitOneFailed);
  }
  constexpr uint32_t kHandleAllocSize = ([]() constexpr {
    uint32_t x = 0;
    if (x > ZX_CHANNEL_MAX_MSG_HANDLES) {
      x = ZX_CHANNEL_MAX_MSG_HANDLES;
    }
    return x;
  })();
  static_assert(kHandleAllocSize <= ZX_CHANNEL_MAX_MSG_HANDLES);
  ::fidl::internal::InlineMessageBuffer<24> read_storage;
  std::array<zx_handle_t, kHandleAllocSize> read_handles;
  // TODO(fxbug.dev/85734) Remove this channel-specific allocation.
  std::array<fidl_channel_handle_metadata_t, kHandleAllocSize>
      read_handle_metadata;
  ::fidl::IncomingMessage msg = ::fidl::MessageRead(
      zx::unowned_channel(client_end.handle()), read_storage.view(),
      read_handles.data(), read_handle_metadata.data(), kHandleAllocSize,
      ReadOptions{.discardable = true});
  if (msg.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::Status::UnexpectedMessage(
        ZX_ERR_BUFFER_TOO_SMALL,
        ::fidl::internal::kErrorSyncEventBufferTooSmall);
  }
  if (!msg.ok()) {
    return msg;
  }
  fidl_message_header_t* hdr = msg.header();
  switch (hdr->ordinal) {
    default: {
      return ::fidl::Status::UnknownOrdinal();
    }
  }
}

std::optional<::fidl::UnbindInfo> fidl::internal::
    WireEventDispatcher<::test_nullable::SimpleProtocol>::DispatchEvent(
        ::fidl::IncomingMessage& msg,
        ::fidl::internal::IncomingTransportContext transport_context) {
  switch (msg.header()->ordinal) {
    default:
      break;
  }
  return ::fidl::UnbindInfo::UnknownOrdinal();
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__

constexpr ::fidl::internal::MethodEntry fidl::internal::WireServerDispatcher<
    ::test_nullable::SimpleProtocol>::entries_[] = {
    {
        ::test_nullable::kSimpleProtocol_Add_Ordinal,
        [](void* interface, ::fidl::IncomingMessage&& msg,
           internal::IncomingTransportContext transport_context,
           ::fidl::Transaction* txn) {
          ::fidl::unstable::DecodedMessage<
              ::fidl::internal::TransactionalRequest<
                  ::test_nullable::SimpleProtocol::Add>>
              decoded{std::move(msg)};
          if (unlikely(!decoded.ok())) {
            return decoded.status();
          }
          auto* primary = &decoded.PrimaryObject()->body;
          ::fidl::internal::WireCompleter<
              ::test_nullable::SimpleProtocol::Add>::Sync completer(txn);
          reinterpret_cast<
              ::fidl::WireServer<::test_nullable::SimpleProtocol>*>(interface)
              ->Add(primary, completer);
          return ZX_OK;
        },
    },
};

const ::fidl::internal::MethodEntry* fidl::internal::WireServerDispatcher<
    ::test_nullable::SimpleProtocol>::entries_end_ = &entries_[1];

::fidl::DispatchResult fidl::internal::
    WireServerDispatcher<::test_nullable::SimpleProtocol>::TryDispatch(
        ::fidl::WireServer<::test_nullable::SimpleProtocol>* impl,
        ::fidl::IncomingMessage& msg,
        internal::IncomingTransportContext transport_context,
        ::fidl::Transaction* txn) {
  return ::fidl::internal::TryDispatch(impl, msg, std::move(transport_context),
                                       txn, entries_, entries_end_);
}

void fidl::internal::WireServerDispatcher<::test_nullable::SimpleProtocol>::
    Dispatch(::fidl::WireServer<::test_nullable::SimpleProtocol>* impl,
             ::fidl::IncomingMessage&& msg,
             internal::IncomingTransportContext transport_context,
             ::fidl::Transaction* txn) {
  ::fidl::internal::Dispatch(impl, msg, std::move(transport_context), txn,
                             entries_, entries_end_);
}
void fidl::WireServer<::test_nullable::SimpleProtocol>::dispatch_message(
    ::fidl::IncomingMessage&& msg, ::fidl::Transaction* txn,
    ::fidl::internal::IncomingTransportContext transport_context) {
  ::fidl::internal::WireServerDispatcher<
      ::test_nullable::SimpleProtocol>::Dispatch(this, std::move(msg),
                                                 std::move(transport_context),
                                                 txn);
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__
void fidl::internal::WireCompleterImpl<
    ::test_nullable::SimpleProtocol::Add>::Reply(int32_t sum) {
  ::fidl::internal::TransactionalResponse<::test_nullable::SimpleProtocol::Add>
      _response{sum};
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::unstable::OwnedEncodedMessage<
      ::fidl::internal::TransactionalResponse<
          ::test_nullable::SimpleProtocol::Add>,
      ::fidl::internal::ChannelTransport>
      _response_message{::fidl::internal::AllowUnownedInputRef{}, &_response};
  return _core()->SendReply(&_response_message.GetOutgoingMessage(),
                            ::fidl::internal::OutgoingTransportContext());
}

void fidl::internal::WireBufferCompleterImpl<
    ::test_nullable::SimpleProtocol::Add>::Reply(int32_t sum) {
  ::fidl::internal::TransactionalResponse<::test_nullable::SimpleProtocol::Add>
      _response{sum};
  constexpr uint32_t _buffer_size = ::fidl::ServerReplyBufferSizeInChannel<
      ::test_nullable::SimpleProtocol::Add>();
  ::fitx::result<::fidl::Error, ::fidl::BufferSpan> _allocation =
      _allocator().TryAllocate(_buffer_size);
  if (!_allocation.is_ok()) {
    ::fidl::OutgoingMessage _failure{_allocation.error_value()};
    return _core()->SendReply(&_failure,
                              ::fidl::internal::OutgoingTransportContext());
  }
  ::fidl::unstable::UnownedEncodedMessage<
      ::fidl::internal::TransactionalResponse<
          ::test_nullable::SimpleProtocol::Add>,
      ::fidl::internal::ChannelTransport>
      _response_message(_allocation->data, _buffer_size, &_response);
  return _core()->SendReply(&_response_message.GetOutgoingMessage(),
                            ::fidl::internal::OutgoingTransportContext());
}
#endif  // __Fuchsia__

void ::fidl::internal::TransactionalRequest<
    ::test_nullable::SimpleProtocol::Add>::_InitHeader() {
  ::fidl::InitTxnHeader(&header, 0,
                        ::test_nullable::kSimpleProtocol_Add_Ordinal,
                        ::test_nullable::kSimpleProtocol_Add_DynamicFlags);
}

void ::fidl::internal::TransactionalResponse<
    ::test_nullable::SimpleProtocol::Add>::_InitHeader() {
  ::fidl::InitTxnHeader(&header, 0,
                        ::test_nullable::kSimpleProtocol_Add_Ordinal,
                        ::test_nullable::kSimpleProtocol_Add_DynamicFlags);
}

#ifdef __Fuchsia__

#endif  // __Fuchsia__
