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

// fidl_experiment = output_index_json

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

#include <memory>

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

namespace test_placementofattributes {

[[maybe_unused]]
constexpr uint64_t kExampleProtocol_Method_Ordinal = 6023439637367187273lu;

[[maybe_unused]]
constexpr ::fidl::MessageDynamicFlags kExampleProtocol_Method_DynamicFlags = ::fidl::MessageDynamicFlags::kStrictMethod;
#ifdef __Fuchsia__
}  // namespace test_placementofattributes

::fidl::WireResult<::test_placementofattributes::ExampleProtocol::Method>::WireResult(
    ::fidl::UnownedClientEnd<::test_placementofattributes::ExampleProtocol> client,
    ::fidl::internal::TransactionalRequest<::test_placementofattributes::ExampleProtocol::Method>* request) {
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::internal::OwnedEncodedMessage<::fidl::internal::TransactionalRequest<::test_placementofattributes::ExampleProtocol::Method>, ::fidl::internal::ChannelTransport> request_message(
      ::fidl::internal::AllowUnownedInputRef{}, request);
  auto& outgoing = request_message.GetOutgoingMessage();
  outgoing.Write(client.handle());
  SetStatus(outgoing);
}
namespace test_placementofattributes {

#endif  // __Fuchsia__

#ifdef __Fuchsia__
}  // namespace test_placementofattributes

::fidl::WireUnownedResult<::test_placementofattributes::ExampleProtocol::Method>::WireUnownedResult(::fidl::UnownedClientEnd<::test_placementofattributes::ExampleProtocol> client_end, ::fidl::internal::AnyBufferAllocator& allocator, ::fidl::internal::TransactionalRequest<::test_placementofattributes::ExampleProtocol::Method>* request) {
  constexpr uint32_t buffer_size = ::fidl::SyncClientMethodBufferSizeInChannel<::test_placementofattributes::ExampleProtocol::Method>();
  ::fit::result<::fidl::Error, ::fidl::BufferSpan> allocation = allocator.TryAllocate(buffer_size);
  if (!allocation.is_ok()) {
    SetStatus(allocation.error_value());
    return;
  }
  uint8_t* buffer = allocation->data;
  uint32_t request_byte_capacity = buffer_size;
  uint8_t* request_bytes = buffer;

  ::fidl::internal::UnownedEncodedMessage<::fidl::internal::TransactionalRequest<::test_placementofattributes::ExampleProtocol::Method>> request_message(
      request_bytes, request_byte_capacity, request);
  auto& outgoing = request_message.GetOutgoingMessage();
  outgoing.Write(client_end.handle());
  SetStatus(outgoing);
}
namespace test_placementofattributes {

#endif  // __Fuchsia__

}  // namespace test_placementofattributes

#ifdef __Fuchsia__

::fidl::OneWayStatus fidl::internal::WireWeakOnewayClientImpl<::test_placementofattributes::ExampleProtocol>::Method(const ::test_exampleusing::wire::Empty& arg) {
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::internal::TransactionalRequest<::test_placementofattributes::ExampleProtocol::Method> _request_object{arg};
  ::fidl::internal::OwnedEncodedMessage<::fidl::internal::TransactionalRequest<::test_placementofattributes::ExampleProtocol::Method>, ::fidl::internal::ChannelTransport> _request_message(
      ::fidl::internal::AllowUnownedInputRef{}, &_request_object);
  return _client_base()->SendOneWay(_request_message.GetOutgoingMessage());
}
::fidl::OneWayStatus fidl::internal::WireWeakOnewayBufferClientImpl<::test_placementofattributes::ExampleProtocol>::Method(const ::test_exampleusing::wire::Empty& arg) {
  constexpr uint32_t _buffer_size = ::fidl::AsyncClientMethodBufferSizeInChannel<::test_placementofattributes::ExampleProtocol::Method>();
  ::fit::result<::fidl::Error, ::fidl::BufferSpan> _allocation =
      _allocator().TryAllocate(_buffer_size);
  if (!_allocation.is_ok()) {
    return ::fidl::OneWayStatus{_allocation.error_value()};
  }

  ::fidl::internal::TransactionalRequest<::test_placementofattributes::ExampleProtocol::Method> _request{arg};
  ::fidl::internal::UnownedEncodedMessage<::fidl::internal::TransactionalRequest<::test_placementofattributes::ExampleProtocol::Method>> _request_message(
      _allocation->data, _buffer_size, &_request);
  return _client_base()->SendOneWay(_request_message.GetOutgoingMessage());
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

::fidl::Status fidl::WireSyncEventHandler<::test_placementofattributes::ExampleProtocol>::HandleOneEvent(
    ::fidl::UnownedClientEnd<::test_placementofattributes::ExampleProtocol> client_end) {
  ::fidl::internal::IncomingEventsStorage<::test_placementofattributes::ExampleProtocol> event_storage;
  fidl::internal::WireEventDispatcher<::test_placementofattributes::ExampleProtocol> dispatcher{this};
  return HandleOneEventImpl_(client_end.channel(), event_storage.view(), dispatcher);
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

constexpr ::fidl::internal::MethodEntry fidl::internal::WireServerDispatcher<::test_placementofattributes::ExampleProtocol>::entries_[] = {
    {
        ::test_placementofattributes::kExampleProtocol_Method_Ordinal,
        [](void* interface, ::fidl::EncodedMessage& msg, ::fidl::WireFormatMetadata metadata,
           internal::MessageStorageViewBase* storage_view, ::fidl::Transaction* txn) {
          ::fit::result decoded = ::fidl::StandaloneInplaceDecode<::test_placementofattributes::wire::ExampleProtocolMethodRequest>(
              std::move(msg), metadata);
          if (unlikely(!decoded.is_ok())) {
            return decoded.error_value();
          }
          ::fidl::internal::WireCompleter<::test_placementofattributes::ExampleProtocol::Method>::Sync completer(txn);
          reinterpret_cast<::fidl::WireServer<::test_placementofattributes::ExampleProtocol>*>(interface)->Method(
              decoded.value().pointer(),
              completer);
          return ::fidl::Status::Ok();
        },
    },
};

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

::fidl::DispatchResult fidl::internal::WireServerDispatcher<::test_placementofattributes::ExampleProtocol>::TryDispatch(
    ::fidl::WireServer<::test_placementofattributes::ExampleProtocol>* 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_placementofattributes::ExampleProtocol>::Dispatch(::fidl::WireServer<::test_placementofattributes::ExampleProtocol>* 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 fidl::WireServer<::test_placementofattributes::ExampleProtocol>::dispatch_message(
    ::fidl::IncomingHeaderAndMessage&& msg, ::fidl::Transaction* txn,
    ::fidl::internal::MessageStorageViewBase* storage_view) {
  ::fidl::internal::WireServerDispatcher<::test_placementofattributes::ExampleProtocol>::Dispatch(this, std::move(msg), storage_view, txn);
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__
void ::fidl::internal::TransactionalRequest<::test_placementofattributes::ExampleProtocol::Method>::_InitHeader() {
  ::fidl::InitTxnHeader(&header, 0, ::test_placementofattributes::kExampleProtocol_Method_Ordinal, ::test_placementofattributes::kExampleProtocol_Method_DynamicFlags);
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

#endif  // __Fuchsia__

#pragma clang diagnostic pop
