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

// fidl_experiment = output_index_json

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

#include <memory>

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

namespace test_service {

[[maybe_unused]]
constexpr uint64_t kFirstProtocol_MethodOnFirst_Ordinal = 6352548393671797041lu;

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

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

#endif  // __Fuchsia__

#ifdef __Fuchsia__
}  // namespace test_service

::fidl::WireUnownedResult<::test_service::FirstProtocol::MethodOnFirst>::WireUnownedResult(::fidl::UnownedClientEnd<::test_service::FirstProtocol> client_end, ::fidl::internal::AnyBufferAllocator& allocator, ::fidl::internal::TransactionalRequest<::test_service::FirstProtocol::MethodOnFirst>* request) {
  constexpr uint32_t buffer_size = ::fidl::SyncClientMethodBufferSizeInChannel<::test_service::FirstProtocol::MethodOnFirst>();
  ::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_service::FirstProtocol::MethodOnFirst>> request_message(
      request_bytes, request_byte_capacity, request);
  auto& outgoing = request_message.GetOutgoingMessage();
  outgoing.Write(client_end.handle());
  SetStatus(outgoing);
}
namespace test_service {

#endif  // __Fuchsia__

}  // namespace test_service

#ifdef __Fuchsia__

::fidl::OneWayStatus fidl::internal::WireWeakOnewayClientImpl<::test_service::FirstProtocol>::MethodOnFirst() {
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::internal::TransactionalRequest<::test_service::FirstProtocol::MethodOnFirst> _request_object{};
  ::fidl::internal::OwnedEncodedMessage<::fidl::internal::TransactionalRequest<::test_service::FirstProtocol::MethodOnFirst>, ::fidl::internal::ChannelTransport> _request_message(
      ::fidl::internal::AllowUnownedInputRef{}, &_request_object);
  return _client_base()->SendOneWay(_request_message.GetOutgoingMessage());
}
::fidl::OneWayStatus fidl::internal::WireWeakOnewayBufferClientImpl<::test_service::FirstProtocol>::MethodOnFirst() {
  constexpr uint32_t _buffer_size = ::fidl::AsyncClientMethodBufferSizeInChannel<::test_service::FirstProtocol::MethodOnFirst>();
  ::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_service::FirstProtocol::MethodOnFirst> _request{};
  ::fidl::internal::UnownedEncodedMessage<::fidl::internal::TransactionalRequest<::test_service::FirstProtocol::MethodOnFirst>> _request_message(
      _allocation->data, _buffer_size, &_request);
  return _client_base()->SendOneWay(_request_message.GetOutgoingMessage());
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

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

#endif  // __Fuchsia__

#ifdef __Fuchsia__

constexpr ::fidl::internal::MethodEntry fidl::internal::WireServerDispatcher<::test_service::FirstProtocol>::entries_[] = {
    {
        ::test_service::kFirstProtocol_MethodOnFirst_Ordinal,
        [](void* interface, ::fidl::EncodedMessage& msg, ::fidl::WireFormatMetadata metadata,
           internal::MessageStorageViewBase* storage_view, ::fidl::Transaction* txn) {
          ::fit::result decoded = ::fidl::internal::DecodeTransactionalMessageWithoutBody(
              msg, metadata);
          if (unlikely(!decoded.is_ok())) {
            return decoded.error_value();
          }
          ::fidl::internal::WireCompleter<::test_service::FirstProtocol::MethodOnFirst>::Sync completer(txn);
          reinterpret_cast<::fidl::WireServer<::test_service::FirstProtocol>*>(interface)->MethodOnFirst(
              completer);
          return ::fidl::Status::Ok();
        },
    },
};

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

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

#endif  // __Fuchsia__

#ifdef __Fuchsia__
void ::fidl::internal::TransactionalRequest<::test_service::FirstProtocol::MethodOnFirst>::_InitHeader() {
  ::fidl::InitTxnHeader(&header, 0, ::test_service::kFirstProtocol_MethodOnFirst_Ordinal, ::test_service::kFirstProtocol_MethodOnFirst_DynamicFlags);
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

#endif  // __Fuchsia__

namespace test_service {

[[maybe_unused]]
constexpr uint64_t kSecondProtocol_MethodOnSecond_Ordinal = 8121179205110225988lu;

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

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

#endif  // __Fuchsia__

#ifdef __Fuchsia__
}  // namespace test_service

::fidl::WireUnownedResult<::test_service::SecondProtocol::MethodOnSecond>::WireUnownedResult(::fidl::UnownedClientEnd<::test_service::SecondProtocol> client_end, ::fidl::internal::AnyBufferAllocator& allocator, ::fidl::internal::TransactionalRequest<::test_service::SecondProtocol::MethodOnSecond>* request) {
  constexpr uint32_t buffer_size = ::fidl::SyncClientMethodBufferSizeInChannel<::test_service::SecondProtocol::MethodOnSecond>();
  ::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_service::SecondProtocol::MethodOnSecond>> request_message(
      request_bytes, request_byte_capacity, request);
  auto& outgoing = request_message.GetOutgoingMessage();
  outgoing.Write(client_end.handle());
  SetStatus(outgoing);
}
namespace test_service {

#endif  // __Fuchsia__

}  // namespace test_service

#ifdef __Fuchsia__

::fidl::OneWayStatus fidl::internal::WireWeakOnewayClientImpl<::test_service::SecondProtocol>::MethodOnSecond() {
  FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT
  ::fidl::internal::TransactionalRequest<::test_service::SecondProtocol::MethodOnSecond> _request_object{};
  ::fidl::internal::OwnedEncodedMessage<::fidl::internal::TransactionalRequest<::test_service::SecondProtocol::MethodOnSecond>, ::fidl::internal::ChannelTransport> _request_message(
      ::fidl::internal::AllowUnownedInputRef{}, &_request_object);
  return _client_base()->SendOneWay(_request_message.GetOutgoingMessage());
}
::fidl::OneWayStatus fidl::internal::WireWeakOnewayBufferClientImpl<::test_service::SecondProtocol>::MethodOnSecond() {
  constexpr uint32_t _buffer_size = ::fidl::AsyncClientMethodBufferSizeInChannel<::test_service::SecondProtocol::MethodOnSecond>();
  ::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_service::SecondProtocol::MethodOnSecond> _request{};
  ::fidl::internal::UnownedEncodedMessage<::fidl::internal::TransactionalRequest<::test_service::SecondProtocol::MethodOnSecond>> _request_message(
      _allocation->data, _buffer_size, &_request);
  return _client_base()->SendOneWay(_request_message.GetOutgoingMessage());
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

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

#endif  // __Fuchsia__

#ifdef __Fuchsia__

constexpr ::fidl::internal::MethodEntry fidl::internal::WireServerDispatcher<::test_service::SecondProtocol>::entries_[] = {
    {
        ::test_service::kSecondProtocol_MethodOnSecond_Ordinal,
        [](void* interface, ::fidl::EncodedMessage& msg, ::fidl::WireFormatMetadata metadata,
           internal::MessageStorageViewBase* storage_view, ::fidl::Transaction* txn) {
          ::fit::result decoded = ::fidl::internal::DecodeTransactionalMessageWithoutBody(
              msg, metadata);
          if (unlikely(!decoded.is_ok())) {
            return decoded.error_value();
          }
          ::fidl::internal::WireCompleter<::test_service::SecondProtocol::MethodOnSecond>::Sync completer(txn);
          reinterpret_cast<::fidl::WireServer<::test_service::SecondProtocol>*>(interface)->MethodOnSecond(
              completer);
          return ::fidl::Status::Ok();
        },
    },
};

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

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

#endif  // __Fuchsia__

#ifdef __Fuchsia__
void ::fidl::internal::TransactionalRequest<::test_service::SecondProtocol::MethodOnSecond>::_InitHeader() {
  ::fidl::InitTxnHeader(&header, 0, ::test_service::kSecondProtocol_MethodOnSecond_Ordinal, ::test_service::kSecondProtocol_MethodOnSecond_DynamicFlags);
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

#endif  // __Fuchsia__

#pragma clang diagnostic pop
