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

#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_BottomGetFooTopResponseTable;

}  // namespace _internal
Top::~Top() = default;

const fidl_type_t* ::test::transitivedependenciescompose::Top_RequestDecoder::GetType(uint64_t ordinal, bool* out_needs_response) {
  *out_needs_response = false;
  switch (ordinal) {
    case ::test::transitivedependenciescompose::internal::kTop_GetFoo_Ordinal:
      *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_BottomGetFooTopResponseTable;
      ;
    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_BottomGetFooTopResponseTable);
}

}  // 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_BottomGetFooTopResponseTable;
    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;
  const fidl_type_t* request_type = ::test::transitivedependenciescompose::Top_RequestDecoder::GetType(message.ordinal(), &needs_response);
  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: {
      return ZX_ERR_NOT_SUPPORTED;
    }
  }
  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_BottomGetFooTopResponseTable;
  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__
