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

// fidl_experiment = output_index_json

#include <test/transitivedependenciescompose/cpp/fidl.h>

#include "lib/fidl/cpp/internal/implementation.h"

//
// Domain objects definitions
//

//
// Proxies and stubs definitions
//

#ifdef __Fuchsia__

namespace test {
namespace transitivedependenciescompose {
namespace _internal {
__LOCAL extern "C" const fidl_type_t test_bottom_BottomGetFooResponseTable;

}  // namespace _internal

Top::~Top() = default;

const fidl_type_t* ::test::transitivedependenciescompose::Top_RequestDecoder::GetType(uint64_t ordinal, bool* out_needs_response, bool* out_is_known) {
  *out_needs_response = false;
  *out_is_known = false;
  switch (ordinal) {
    case ::test::transitivedependenciescompose::internal::kTop_GetFoo_Ordinal:
      *out_is_known = true;
      *out_needs_response = true;
      return nullptr;
      ;
    default:
      return nullptr;
  }
}

const fidl_type_t* Top_ResponseDecoder::GetType(uint64_t ordinal) {
  switch (ordinal) {
    case ::test::transitivedependenciescompose::internal::kTop_GetFoo_Ordinal:
      return &::test::transitivedependenciescompose::_internal::test_bottom_BottomGetFooResponseTable;
      ;
    default:
      return nullptr;
  }
}

Top_EventSender::~Top_EventSender() = default;

Top_Sync::~Top_Sync() = default;

Top_Proxy::Top_Proxy(::fidl::internal::ProxyController* controller)
    : controller_(controller) {
  (void)controller_;
}

Top_Proxy::~Top_Proxy() = default;

zx_status_t Top_Proxy::Dispatch_(::fidl::HLCPPIncomingMessage message) {
  zx_status_t status = ZX_OK;
  switch (message.ordinal()) {
    default: {
      status = ZX_ERR_NOT_SUPPORTED;
      break;
    }
  }
  return status;
}

namespace {

::std::unique_ptr<::fidl::internal::SingleUseMessageHandler>
Top_GetFoo_ResponseHandler(Top::GetFooCallback&& callback) {
  ZX_DEBUG_ASSERT_MSG(callback,
                      "Callback must not be empty for Top::GetFoo\n");
  return ::std::make_unique<::fidl::internal::SingleUseMessageHandler>(
      [callback_ = std::move(callback)](::fidl::HLCPPIncomingMessage&& message) {
        ::fidl::Decoder decoder(std::move(message));
        callback_(::fidl::DecodeAs<::test::bottom::Foo>(&decoder, 0 + sizeof(fidl_message_header_t)));
        return ZX_OK;
      },
      &::test::transitivedependenciescompose::_internal::test_bottom_BottomGetFooResponseTable);
}

}  // namespace
void Top_Proxy::GetFoo(GetFooCallback callback) {
  ::fidl::MessageEncoder _encoder(::test::transitivedependenciescompose::internal::kTop_GetFoo_Ordinal, ::test::transitivedependenciescompose::internal::kTop_GetFoo_DynamicFlags);
  const fidl_type_t* req_type = nullptr;
  controller_->Send(req_type, ::test::transitivedependenciescompose::Top_RequestEncoder::GetFoo(&_encoder), Top_GetFoo_ResponseHandler(std::move(callback)));
}

Top_Stub::Top_Stub(::test::transitivedependenciescompose::Top_Stub::Top_clazz* impl) : impl_(impl) {
  (void)impl_;
}

Top_Stub::~Top_Stub() = default;

namespace {

class Top_GetFoo_Responder final {
 public:
  Top_GetFoo_Responder(::fidl::internal::PendingResponse response)
      : response_(std::move(response)) {}

  void operator()(::test::bottom::Foo foo) {
    ::fidl::MessageEncoder _encoder(::test::transitivedependenciescompose::internal::kTop_GetFoo_Ordinal, ::test::transitivedependenciescompose::internal::kTop_GetFoo_DynamicFlags);
    const fidl_type_t* resp_type = &::test::transitivedependenciescompose::_internal::test_bottom_BottomGetFooResponseTable;
    response_.Send(resp_type, ::test::transitivedependenciescompose::Top_ResponseEncoder::GetFoo(&_encoder, &foo));
  }

 private:
  ::fidl::internal::PendingResponse response_;
};

}  // namespace

zx_status_t Top_Stub::Dispatch_(
    ::fidl::HLCPPIncomingMessage message,
    ::fidl::internal::PendingResponse response) {
  bool needs_response;
  bool is_known;
  const fidl_type_t* request_type = ::test::transitivedependenciescompose::Top_RequestDecoder::GetType(message.ordinal(), &needs_response, &is_known);

  if (!is_known) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  if (!message.has_only_header()) {
    if (request_type == nullptr) {
      return ZX_ERR_NOT_SUPPORTED;
    }
    const char* error_msg = nullptr;
    zx_status_t status = message.Decode(request_type, &error_msg);
    if (status != ZX_OK) {
      FIDL_REPORT_DECODING_ERROR(message, request_type, error_msg);
      return status;
    }
  }

  if (response.needs_response() != needs_response) {
    if (needs_response) {
      FIDL_REPORT_DECODING_ERROR(message, request_type, "Message needing a response with no txid");
    } else {
      FIDL_REPORT_DECODING_ERROR(message, request_type, "Message not needing a response with a txid");
    }
    return ZX_ERR_INVALID_ARGS;
  }

  uint64_t ordinal = message.ordinal();
  switch (ordinal) {
    case ::test::transitivedependenciescompose::internal::kTop_GetFoo_Ordinal: {
      impl_->GetFoo(Top_GetFoo_Responder(std::move(response)));
      break;
    }
    default: {
      // Unknown ordinals are handled at the beginning of dispatching, so this
      // should be unreachable.
      ZX_PANIC("Unreachable: unknown ordinals handled earlier.");
    }
  }
  return ZX_OK;
}

Top_SyncProxy::Top_SyncProxy(::zx::channel channel)
    : proxy_(::std::move(channel)) {}

Top_SyncProxy::~Top_SyncProxy() = default;

zx_status_t Top_SyncProxy::GetFoo(::test::bottom::Foo* out_foo) {
  ::fidl::MessageEncoder _encoder(::test::transitivedependenciescompose::internal::kTop_GetFoo_Ordinal, ::test::transitivedependenciescompose::internal::kTop_GetFoo_DynamicFlags);
  ::fidl::IncomingMessageBuffer buffer_;
  ::fidl::HLCPPIncomingMessage response_ = buffer_.CreateEmptyIncomingMessage();
  const fidl_type_t* req_type = nullptr;
  const fidl_type_t* resp_type = &::test::transitivedependenciescompose::_internal::test_bottom_BottomGetFooResponseTable;
  zx_status_t status_ = proxy_.Call(req_type, resp_type, ::test::transitivedependenciescompose::Top_RequestEncoder::GetFoo(&_encoder), &response_);
  if (status_ != ZX_OK)
    return status_;
  ::fidl::Decoder decoder_(std::move(response_));
  *out_foo = ::fidl::DecodeAs<::test::bottom::Foo>(&decoder_, 0 + sizeof(fidl_message_header_t));
  return ZX_OK;
}
}  // namespace transitivedependenciescompose
}  // namespace test

#endif  // __Fuchsia__
