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

// fidl_experiment = output_index_json

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

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

//
// Domain objects definitions
//
namespace test {
namespace inheritancewithrecursivedecl {

#ifdef __Fuchsia__

extern "C" const fidl_type_t test_inheritancewithrecursivedecl_ParentFirstRequestTable;
const fidl_type_t* ParentFirstRequest::FidlType = &test_inheritancewithrecursivedecl_ParentFirstRequestTable;

void ParentFirstRequest::Encode(::fidl::Encoder* _encoder, size_t _offset,
                                cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<ParentFirstRequest>::value) {
    memcpy(_encoder->template GetPtr<ParentFirstRequest>(_offset), this, sizeof(ParentFirstRequest));
  } else {
    ::fidl::Encode(_encoder, &request, _offset + 0, ::fidl::HandleInformation{
                                                        .object_type = ZX_OBJ_TYPE_CHANNEL,
                                                        .rights = ZX_DEFAULT_CHANNEL_RIGHTS,
                                                    });
  }
}

void ParentFirstRequest::Decode(::fidl::Decoder* _decoder, ParentFirstRequest* _value, size_t _offset) {
  if (::fidl::IsMemcpyCompatible<ParentFirstRequest>::value) {
    memcpy(_value, _decoder->template GetPtr<ParentFirstRequest>(_offset), sizeof(ParentFirstRequest));
  } else {
    ::fidl::Decode(_decoder, &_value->request, _offset + 0);
  }
}

zx_status_t ParentFirstRequest::Clone(ParentFirstRequest* _result) const {
  zx_status_t _status = ::fidl::Clone(request, &_result->request);
  if (_status != ZX_OK)
    return _status;
  return ZX_OK;
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

extern "C" const fidl_type_t test_inheritancewithrecursivedecl_ChildSecondRequestTable;
const fidl_type_t* ChildSecondRequest::FidlType = &test_inheritancewithrecursivedecl_ChildSecondRequestTable;

void ChildSecondRequest::Encode(::fidl::Encoder* _encoder, size_t _offset,
                                cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<ChildSecondRequest>::value) {
    memcpy(_encoder->template GetPtr<ChildSecondRequest>(_offset), this, sizeof(ChildSecondRequest));
  } else {
    ::fidl::Encode(_encoder, &request, _offset + 0, ::fidl::HandleInformation{
                                                        .object_type = ZX_OBJ_TYPE_CHANNEL,
                                                        .rights = ZX_DEFAULT_CHANNEL_RIGHTS,
                                                    });
  }
}

void ChildSecondRequest::Decode(::fidl::Decoder* _decoder, ChildSecondRequest* _value, size_t _offset) {
  if (::fidl::IsMemcpyCompatible<ChildSecondRequest>::value) {
    memcpy(_value, _decoder->template GetPtr<ChildSecondRequest>(_offset), sizeof(ChildSecondRequest));
  } else {
    ::fidl::Decode(_decoder, &_value->request, _offset + 0);
  }
}

zx_status_t ChildSecondRequest::Clone(ChildSecondRequest* _result) const {
  zx_status_t _status = ::fidl::Clone(request, &_result->request);
  if (_status != ZX_OK)
    return _status;
  return ZX_OK;
}

#endif  // __Fuchsia__

//
// Proxies and stubs definitions
//

#ifdef __Fuchsia__

namespace _internal {
__LOCAL extern "C" const fidl_type_t test_inheritancewithrecursivedecl_ParentFirstRequestTable;

}  // namespace _internal

Parent::~Parent() = default;

const fidl_type_t* ::test::inheritancewithrecursivedecl::Parent_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::inheritancewithrecursivedecl::internal::kParent_First_Ordinal:
      *out_is_known = true;
      return &::test::inheritancewithrecursivedecl::_internal::test_inheritancewithrecursivedecl_ParentFirstRequestTable;
      ;
    default:
      return nullptr;
  }
}

const fidl_type_t* Parent_ResponseDecoder::GetType(uint64_t ordinal) {
  switch (ordinal) {
    default:
      return nullptr;
  }
}

Parent_EventSender::~Parent_EventSender() = default;

Parent_Sync::~Parent_Sync() = default;

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

Parent_Proxy::~Parent_Proxy() = default;

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

void Parent_Proxy::First(::fidl::InterfaceRequest<::test::inheritancewithrecursivedecl::Parent> request) {
  ::fidl::MessageEncoder _encoder(::test::inheritancewithrecursivedecl::internal::kParent_First_Ordinal, ::test::inheritancewithrecursivedecl::internal::kParent_First_DynamicFlags);
  const fidl_type_t* req_type = &::test::inheritancewithrecursivedecl::_internal::test_inheritancewithrecursivedecl_ParentFirstRequestTable;
  controller_->Send(req_type, ::test::inheritancewithrecursivedecl::Parent_RequestEncoder::First(&_encoder, &request), nullptr);
}

Parent_Stub::Parent_Stub(::test::inheritancewithrecursivedecl::Parent_Stub::Parent_clazz* impl) : impl_(impl) {
  (void)impl_;
}

Parent_Stub::~Parent_Stub() = default;

namespace {

}  // namespace

zx_status_t Parent_Stub::Dispatch_(
    ::fidl::HLCPPIncomingMessage message,
    ::fidl::internal::PendingResponse response) {
  bool needs_response;
  bool is_known;
  const fidl_type_t* request_type = ::test::inheritancewithrecursivedecl::Parent_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::inheritancewithrecursivedecl::internal::kParent_First_Ordinal: {
      ::fidl::Decoder decoder(std::move(message));
      impl_->First(::fidl::DecodeAs<::fidl::InterfaceRequest<::test::inheritancewithrecursivedecl::Parent>>(&decoder, 0 + sizeof(fidl_message_header_t)));
      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;
}

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

Parent_SyncProxy::~Parent_SyncProxy() = default;

zx_status_t Parent_SyncProxy::First(::fidl::InterfaceRequest<::test::inheritancewithrecursivedecl::Parent> request) {
  ::fidl::MessageEncoder _encoder(::test::inheritancewithrecursivedecl::internal::kParent_First_Ordinal, ::test::inheritancewithrecursivedecl::internal::kParent_First_DynamicFlags);
  const fidl_type_t* req_type = &::test::inheritancewithrecursivedecl::_internal::test_inheritancewithrecursivedecl_ParentFirstRequestTable;
  return proxy_.Send(req_type, ::test::inheritancewithrecursivedecl::Parent_RequestEncoder::First(&_encoder, &request));
}

#endif  // __Fuchsia__

#ifdef __Fuchsia__

namespace _internal {
__LOCAL extern "C" const fidl_type_t test_inheritancewithrecursivedecl_ChildSecondRequestTable;

}  // namespace _internal

Child::~Child() = default;

const fidl_type_t* ::test::inheritancewithrecursivedecl::Child_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::inheritancewithrecursivedecl::internal::kChild_First_Ordinal:
      *out_is_known = true;
      return &::test::inheritancewithrecursivedecl::_internal::test_inheritancewithrecursivedecl_ParentFirstRequestTable;
      ;
    case ::test::inheritancewithrecursivedecl::internal::kChild_Second_Ordinal:
      *out_is_known = true;
      return &::test::inheritancewithrecursivedecl::_internal::test_inheritancewithrecursivedecl_ChildSecondRequestTable;
      ;
    default:
      return nullptr;
  }
}

const fidl_type_t* Child_ResponseDecoder::GetType(uint64_t ordinal) {
  switch (ordinal) {
    default:
      return nullptr;
  }
}

Child_EventSender::~Child_EventSender() = default;

Child_Sync::~Child_Sync() = default;

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

Child_Proxy::~Child_Proxy() = default;

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

void Child_Proxy::First(::fidl::InterfaceRequest<::test::inheritancewithrecursivedecl::Parent> request) {
  ::fidl::MessageEncoder _encoder(::test::inheritancewithrecursivedecl::internal::kChild_First_Ordinal, ::test::inheritancewithrecursivedecl::internal::kChild_First_DynamicFlags);
  const fidl_type_t* req_type = &::test::inheritancewithrecursivedecl::_internal::test_inheritancewithrecursivedecl_ParentFirstRequestTable;
  controller_->Send(req_type, ::test::inheritancewithrecursivedecl::Child_RequestEncoder::First(&_encoder, &request), nullptr);
}
void Child_Proxy::Second(::fidl::InterfaceRequest<::test::inheritancewithrecursivedecl::Parent> request) {
  ::fidl::MessageEncoder _encoder(::test::inheritancewithrecursivedecl::internal::kChild_Second_Ordinal, ::test::inheritancewithrecursivedecl::internal::kChild_Second_DynamicFlags);
  const fidl_type_t* req_type = &::test::inheritancewithrecursivedecl::_internal::test_inheritancewithrecursivedecl_ChildSecondRequestTable;
  controller_->Send(req_type, ::test::inheritancewithrecursivedecl::Child_RequestEncoder::Second(&_encoder, &request), nullptr);
}

Child_Stub::Child_Stub(::test::inheritancewithrecursivedecl::Child_Stub::Child_clazz* impl) : impl_(impl) {
  (void)impl_;
}

Child_Stub::~Child_Stub() = default;

namespace {

}  // namespace

zx_status_t Child_Stub::Dispatch_(
    ::fidl::HLCPPIncomingMessage message,
    ::fidl::internal::PendingResponse response) {
  bool needs_response;
  bool is_known;
  const fidl_type_t* request_type = ::test::inheritancewithrecursivedecl::Child_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::inheritancewithrecursivedecl::internal::kChild_First_Ordinal: {
      ::fidl::Decoder decoder(std::move(message));
      impl_->First(::fidl::DecodeAs<::fidl::InterfaceRequest<::test::inheritancewithrecursivedecl::Parent>>(&decoder, 0 + sizeof(fidl_message_header_t)));
      break;
    }
    case ::test::inheritancewithrecursivedecl::internal::kChild_Second_Ordinal: {
      ::fidl::Decoder decoder(std::move(message));
      impl_->Second(::fidl::DecodeAs<::fidl::InterfaceRequest<::test::inheritancewithrecursivedecl::Parent>>(&decoder, 0 + sizeof(fidl_message_header_t)));
      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;
}

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

Child_SyncProxy::~Child_SyncProxy() = default;

zx_status_t Child_SyncProxy::First(::fidl::InterfaceRequest<::test::inheritancewithrecursivedecl::Parent> request) {
  ::fidl::MessageEncoder _encoder(::test::inheritancewithrecursivedecl::internal::kChild_First_Ordinal, ::test::inheritancewithrecursivedecl::internal::kChild_First_DynamicFlags);
  const fidl_type_t* req_type = &::test::inheritancewithrecursivedecl::_internal::test_inheritancewithrecursivedecl_ParentFirstRequestTable;
  return proxy_.Send(req_type, ::test::inheritancewithrecursivedecl::Child_RequestEncoder::First(&_encoder, &request));
}

zx_status_t Child_SyncProxy::Second(::fidl::InterfaceRequest<::test::inheritancewithrecursivedecl::Parent> request) {
  ::fidl::MessageEncoder _encoder(::test::inheritancewithrecursivedecl::internal::kChild_Second_Ordinal, ::test::inheritancewithrecursivedecl::internal::kChild_Second_DynamicFlags);
  const fidl_type_t* req_type = &::test::inheritancewithrecursivedecl::_internal::test_inheritancewithrecursivedecl_ChildSecondRequestTable;
  return proxy_.Send(req_type, ::test::inheritancewithrecursivedecl::Child_RequestEncoder::Second(&_encoder, &request));
}

#endif  // __Fuchsia__

}  // namespace inheritancewithrecursivedecl
}  // namespace test
