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

#include <fidl/test.error/cpp/natural_messaging.h>

namespace test_error {
[[maybe_unused]] constexpr inline uint64_t kExample_foo_Ordinal = 1107623248440401476lu;

[[maybe_unused]] constexpr inline ::fidl::MessageDynamicFlags kExample_foo_DynamicFlags = ::fidl::MessageDynamicFlags::kStrictMethod;

#ifdef __Fuchsia__
}  // namespace test_error
::fidl::internal::NaturalThenable<::test_error::Example::Foo>
fidl::internal::NaturalClientImpl<::test_error::Example>::Foo(::fidl::Request<::test_error::Example::Foo> request) const {
  return ::fidl::internal::NaturalThenable<::test_error::Example::Foo>(
      &client_base(), {}, &::fidl::internal::ChannelTransport::VTable, ::test_error::kExample_foo_Ordinal, ::test_error::kExample_foo_DynamicFlags,
      [request = std::move(request)](NaturalMessageEncoder& encoder) mutable {
        encoder.EncodeBody(
            ::fidl::internal::NaturalMessageConverter<::fidl::Request<::test_error::Example::Foo>>::IntoDomainObject(std::move(request)));
        return ZX_OK;
      },
      [](
          ::fidl::internal::ThenableBase* base,
          ::fidl::internal::NaturalMessageEncoder& encoder,
          ::fidl::internal::ResponseContext* response_context) {
        ::fidl::OutgoingMessage msg = encoder.GetMessage();
        return base->SendTwoWay(msg, response_context);
      });
}

namespace test_error {
#endif  // __Fuchsia__

}  // namespace test_error
#ifdef __Fuchsia__

::fidl::Result<::test_error::Example::Foo>
fidl::internal::NaturalSyncClientImpl<::test_error::Example>::Foo(::fidl::Request<::test_error::Example::Foo> request) {
  ::fidl::internal::NaturalMessageEncoder encoder{
      &::fidl::internal::ChannelTransport::VTable, ::test_error::kExample_foo_Ordinal, ::test_error::kExample_foo_DynamicFlags};
  encoder.EncodeBody(
      ::fidl::internal::NaturalMessageConverter<::fidl::Request<::test_error::Example::Foo>>::IntoDomainObject(std::move(request)));
  ::fidl::OutgoingMessage msg = encoder.GetMessage();
  ::fidl::internal::IncomingMessageStorage<::fidl::internal::TransactionalResponse<::test_error::Example::Foo>> response_storage;
  return ::fidl::internal::DecodeResponseAndFoldError<::test_error::Example::Foo>(
      msg.Call(_client_end().handle(), response_storage.view()), nullptr);
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

::fidl::Status fidl::SyncEventHandler<::test_error::Example>::HandleOneEvent(
    ::fidl::UnownedClientEnd<::test_error::Example> client_end) {
  ::fidl::internal::IncomingEventsStorage<::test_error::Example> event_storage;
  fidl::internal::NaturalEventDispatcher<::test_error::Example> dispatcher{this};
  return HandleOneEventImpl_(client_end.channel(), event_storage.view(), dispatcher);
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__

#endif  // __Fuchsia__

void fidl::internal::NaturalCompleterBase<::test_error::Example::Foo>::Reply(::fidl::Response<::test_error::Example::Foo>&& response) {
  ::fidl::internal::NaturalMessageEncoder _encoder{
      &::fidl::internal::ChannelTransport::VTable, ::test_error::kExample_foo_Ordinal, ::test_error::kExample_foo_DynamicFlags};
  _encoder.EncodeBody(
      ::fidl::internal::NaturalMessageConverter<::fidl::Response<::test_error::Example::Foo>>::IntoDomainObject(std::move(response)));
  ::fidl::OutgoingMessage _encoded_message = _encoder.GetMessage();
  SendReply(&_encoded_message, ::fidl::internal::OutgoingTransportContext{});
}

#ifdef __Fuchsia__

constexpr ::fidl::internal::MethodEntry fidl::internal::NaturalServerDispatcher<::test_error::Example>::entries_[] = {
    {
        ::test_error::kExample_foo_Ordinal,
        [](void* interface, ::fidl::IncomingMessage&& msg,
           internal::MessageStorageViewBase* storage_view, ::fidl::Transaction* txn) {
          ::fitx::result decoded = ::fidl::internal::DecodeTransactionalMessage<::test_error::ExampleFooRequest>(std::move(msg));
          if (decoded.is_error()) {
            return decoded.error_value();
          }
          ::fidl::Request<::test_error::Example::Foo> request = ::fidl::internal::NaturalMessageConverter<::fidl::Request<::test_error::Example::Foo>>::FromDomainObject(std::move(decoded.value()));
          ::fidl::internal::NaturalCompleter<::test_error::Example::Foo>::Sync completer(txn);
          static_cast<::fidl::Server<::test_error::Example>*>(interface)->Foo(
              request, completer);
          return ::fidl::Status::Ok();
        },
    },
};

const ::fidl::internal::MethodEntry* fidl::internal::NaturalServerDispatcher<::test_error::Example>::entries_end_ =
    &entries_[1];

void fidl::internal::NaturalServerDispatcher<::test_error::Example>::Dispatch(::fidl::Server<::test_error::Example>* impl, ::fidl::IncomingMessage&& msg,
                                                                              internal::MessageStorageViewBase* storage_view, ::fidl::Transaction* txn) {
  ::fidl::internal::Dispatch(impl, msg, storage_view, txn, entries_, entries_end_);
}
void fidl::Server<::test_error::Example>::dispatch_message(
    ::fidl::IncomingMessage&& msg, ::fidl::Transaction* txn,
    ::fidl::internal::MessageStorageViewBase* storage_view) {
  ::fidl::internal::NaturalServerDispatcher<::test_error::Example>::Dispatch(this, std::move(msg), storage_view, txn);
}
#endif  // __Fuchsia__
