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

// fidl_experiment = output_index_json

#include <fidl/test.driveroneway/cpp/driver/wire_messaging.h>
#include <lib/fidl_driver/cpp/unknown_interactions.h>

#include <memory>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow"

namespace test_driveroneway {

[[maybe_unused]]
constexpr uint64_t kOneWay_Send_Ordinal = 7942965975761529343lu;

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

#ifdef __Fuchsia__
}  // namespace test_driveroneway

::fdf::WireUnownedResult<::test_driveroneway::OneWay::Send>::WireUnownedResult(::fdf::UnownedClientEnd<::test_driveroneway::OneWay> client_end, const ::fdf::Arena& arena, ::fidl::internal::TransactionalRequest<::test_driveroneway::OneWay::Send>* request) {
  constexpr uint32_t buffer_size =
      ::fidl::MaxSizeInChannel<::fidl::internal::TransactionalRequest<::test_driveroneway::OneWay::Send>, ::fidl::MessageDirection::kSending>();
  uint8_t* buffer = static_cast<uint8_t*>(arena.Allocate(buffer_size));

  ::fidl::internal::UnownedEncodedMessage<::fidl::internal::TransactionalRequest<::test_driveroneway::OneWay::Send>, fidl::internal::DriverTransport> request_message(
      buffer, buffer_size, request);
  auto& outgoing = request_message.GetOutgoingMessage();
  ::fidl::WriteOptions write_options = {
      .outgoing_transport_context =
          ::fidl::internal::OutgoingTransportContext::Create<fidl::internal::DriverTransport>(
              arena.get()),
  };
  outgoing.Write(client_end.handle(), std::move(write_options));
  SetStatus(outgoing);
}
namespace test_driveroneway {

#endif  // __Fuchsia__

#ifdef __Fuchsia__
}  // namespace test_driveroneway

::fidl::OneWayStatus fidl::internal::WireWeakOnewayClientImpl<::test_driveroneway::OneWay>::Send(const ::test_driveroneway::wire::Payload& payload) {
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::internal::TransactionalRequest<::test_driveroneway::OneWay::Send> _request_object{payload};

  constexpr uint32_t _buffer_size = ::fidl::AsyncClientMethodBufferSizeInChannel<::test_driveroneway::OneWay::Send>();
  uint8_t* _buffer = static_cast<uint8_t*>(arena_.Allocate(_buffer_size));

  ::fidl::internal::UnownedEncodedMessage<::fidl::internal::TransactionalRequest<::test_driveroneway::OneWay::Send>, ::fidl::internal::DriverTransport> _request_message(
      _buffer, _buffer_size, &_request_object);
  fidl::WriteOptions _options = {};
  _options.outgoing_transport_context =
      ::fidl::internal::OutgoingTransportContext::Create<::fidl::internal::DriverTransport>(
          arena_.get());
  return _client_base()->SendOneWay(_request_message.GetOutgoingMessage(), std::move(_options));
}
::fidl::OneWayStatus fidl::internal::WireWeakOnewayBufferClientImpl<::test_driveroneway::OneWay>::Send(const ::test_driveroneway::wire::Payload& payload) {
  constexpr uint32_t _buffer_size = ::fidl::AsyncClientMethodBufferSizeInChannel<::test_driveroneway::OneWay::Send>();
  uint8_t* _buffer = static_cast<uint8_t*>(_arena().Allocate(_buffer_size));

  ::fidl::internal::TransactionalRequest<::test_driveroneway::OneWay::Send> _request{payload};
  ::fidl::internal::UnownedEncodedMessage<::fidl::internal::TransactionalRequest<::test_driveroneway::OneWay::Send>, ::fidl::internal::DriverTransport> _request_message(
      _buffer, _buffer_size, &_request);
  fidl::WriteOptions _options = {};
  _options.outgoing_transport_context =
      ::fidl::internal::OutgoingTransportContext::Create<::fidl::internal::DriverTransport>(
          _arena().get());
  return _client_base()->SendOneWay(_request_message.GetOutgoingMessage(), std::move(_options));
}
namespace test_driveroneway {

#endif  // __Fuchsia__

}  // namespace test_driveroneway

#ifdef __Fuchsia__

#endif  // __Fuchsia__

#ifdef __Fuchsia__

constexpr ::fidl::internal::MethodEntry fidl::internal::WireServerDispatcher<::test_driveroneway::OneWay>::entries_[] = {
    {
        ::test_driveroneway::kOneWay_Send_Ordinal,
        [](void* interface, ::fidl::EncodedMessage& msg, ::fidl::WireFormatMetadata metadata,
           internal::MessageStorageViewBase* storage_view, ::fidl::Transaction* txn) {
          fdf::Arena arena(::fidl::internal::TakeDriverArenaFromStorage(storage_view));
          ::fit::result decoded = ::fidl::StandaloneInplaceDecode<::test_driveroneway::wire::OneWaySendRequest>(
              std::move(msg), metadata);
          if (unlikely(!decoded.is_ok())) {
            return decoded.error_value();
          }
          ::fidl::internal::WireCompleter<::test_driveroneway::OneWay::Send>::Sync completer(txn);
          reinterpret_cast<::fdf::WireServer<::test_driveroneway::OneWay>*>(interface)->Send(
              decoded.value().pointer(),
              arena,
              completer);
          return ::fidl::Status::Ok();
        },
    },
};

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

::fidl::DispatchResult fidl::internal::WireServerDispatcher<::test_driveroneway::OneWay>::TryDispatch(
    ::fdf::WireServer<::test_driveroneway::OneWay>* impl, ::fidl::IncomingHeaderAndMessage& msg,
    internal::MessageStorageViewBase* storage_view, ::fidl::Transaction* txn) {
  return ::fidl::internal::TryDispatch(
      impl, msg, storage_view, txn, entries_, entries_end_);
}

void fidl::internal::WireServerDispatcher<::test_driveroneway::OneWay>::Dispatch(::fdf::WireServer<::test_driveroneway::OneWay>* impl, ::fidl::IncomingHeaderAndMessage&& msg,
                                                                                 internal::MessageStorageViewBase* storage_view, ::fidl::Transaction* txn) {
  ::fidl::internal::Dispatch(impl, msg, storage_view, txn, entries_, entries_end_,
                             &unknown_method_handler_entry_);
}

void fdf::WireServer<::test_driveroneway::OneWay>::dispatch_message(
    ::fidl::IncomingHeaderAndMessage&& msg, ::fidl::Transaction* txn,
    ::fidl::internal::MessageStorageViewBase* storage_view) {
  ::fidl::internal::WireServerDispatcher<::test_driveroneway::OneWay>::Dispatch(this, std::move(msg), storage_view, txn);
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__
void ::fidl::internal::TransactionalRequest<::test_driveroneway::OneWay::Send>::_InitHeader() {
  ::fidl::InitTxnHeader(&header, 0, ::test_driveroneway::kOneWay_Send_Ordinal, ::test_driveroneway::kOneWay_Send_DynamicFlags);
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

#endif  // __Fuchsia__

#pragma clang diagnostic pop
