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

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

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

//
// Domain objects definitions (i.e. "natural types" in unified bindings)
//
namespace fidl {
namespace test {
namespace doccomments {
extern "C" const fidl_type_t fidl_test_doccomments_TableTable;
const fidl_type_t* Table::FidlType = &fidl_test_doccomments_TableTable;

Table::Table() {}

Table::Table(Table&& other) {
  field_presence_ = other.field_presence_;
  if (field_presence_.IsSet<0>()) {
    Construct(&Field_value_.value, std::move(other.Field_value_.value));
  }
  _unknown_data = std::move(other._unknown_data);
}

Table::~Table() {
  if (field_presence_.IsSet<0>()) {
    Destruct(&Field_value_.value);
  }
}

Table& Table::operator=(Table&& other) {
  if (other.field_presence_.IsSet<0>()) {
    if (field_presence_.IsSet<0>()) {
      Field_value_.value = std::move(other.Field_value_.value);
    } else {
      field_presence_.Set<0>();
      Construct(&Field_value_.value, std::move(other.Field_value_.value));
    }
  } else if (field_presence_.IsSet<0>()) {
    field_presence_.Clear<0>();
    Destruct(&Field_value_.value);
  }
  _unknown_data = std::move(other._unknown_data);
  return *this;
}

bool Table::IsEmpty() const {
  return field_presence_.IsEmpty() && _unknown_data.size() == 0;
}

void Table::Encode(
    ::fidl::Encoder* _encoder, size_t _offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  size_t max_ordinal = MaxOrdinal();
  ::fidl::EncodeVectorPointer(_encoder, max_ordinal, _offset);
  if (max_ordinal == 0) return;
  size_t base = _encoder->Alloc(max_ordinal * sizeof(fidl_envelope_t));
  auto next_unknown = _unknown_data.begin();
  if (field_presence_.IsSet<0>()) {
    // Encode unknown fields that have an ordinal that should appear before this
    // field.
    while (next_unknown != _unknown_data.end() && next_unknown->first < 1) {
      size_t envelope_base =
          base + (next_unknown->first - 1) * sizeof(fidl_envelope_t);
      ::fidl::EncodeUnknownBytes(_encoder, &next_unknown->second,
                                 envelope_base);
      std::advance(next_unknown, 1);
    }

    const size_t length_before = _encoder->CurrentLength();
    const size_t handles_before = _encoder->CurrentHandleCount();
    ::fidl::Encode(
        _encoder, &Field_value_.value,
        _encoder->Alloc(
            ::fidl::EncodingInlineSize<int32_t, ::fidl::Encoder>(_encoder)));
    size_t envelope_base = base + (1 - 1) * sizeof(fidl_envelope_t);
    uint64_t num_bytes_then_num_handles =
        (_encoder->CurrentLength() - length_before) |
        ((_encoder->CurrentHandleCount() - handles_before) << 32);
    ::fidl::Encode(_encoder, &num_bytes_then_num_handles, envelope_base);
    *_encoder->GetPtr<uintptr_t>(envelope_base +
                                 offsetof(fidl_envelope_t, presence)) =
        FIDL_ALLOC_PRESENT;
  }
  // Encode any remaining unknown fields (i.e. ones that have an ordinal outside
  // the range of known ordinals)
  for (auto curr = next_unknown; curr != _unknown_data.end(); ++curr) {
    size_t envelope_base = base + (curr->first - 1) * sizeof(fidl_envelope_t);
    ::fidl::EncodeUnknownBytes(_encoder, &curr->second, envelope_base);
  }
}

void Table::Decode(::fidl::Decoder* _decoder, Table* _value, size_t _offset) {
  fidl_vector_t* encoded = _decoder->GetPtr<fidl_vector_t>(_offset);
  size_t base;
  size_t count;
  if (!encoded->data) {
    goto clear_all;
  }

  base = _decoder->GetOffset(encoded->data);
  count = encoded->count;
  if (count >= 1) {
    size_t envelope_base = base + (1 - 1) * sizeof(fidl_envelope_t);
    uint64_t presence;
    ::fidl::Decode(_decoder, &presence,
                   envelope_base + offsetof(fidl_envelope_t, presence));
    if (presence != 0) {
      ::fidl::Decode(_decoder, _value->mutable_Field(),
                     _decoder->GetOffset(presence));
    } else {
      _value->clear_Field();
    }
  } else {
    goto done_1;
  }

  if (count > 1) {
    for (uint64_t ordinal = 1; ordinal <= count; ordinal++) {
      if (IsOrdinalKnown(ordinal)) continue;

      size_t envelope_base = base + (ordinal - 1) * sizeof(fidl_envelope_t);
      fidl_envelope_t* envelope =
          _decoder->GetPtr<fidl_envelope_t>(envelope_base);
      if (envelope->presence != 0) {
        auto result = _value->_unknown_data.emplace(
            std::piecewise_construct, std::forward_as_tuple(ordinal),
            std::forward_as_tuple());
        auto iter = result.first;
        iter->second.resize(envelope->num_bytes);
        ::fidl::DecodeUnknownBytesContents(_decoder, &iter->second,
                                           _decoder->GetOffset(envelope->data));
      }
    }
  }

  return;

  // Clear unset values.
clear_all:
done_1:
  _value->clear_Field();
  return;
}

zx_status_t Table::Clone(Table* result) const {
  if (field_presence_.IsSet<0>()) {
    zx_status_t _status =
        ::fidl::Clone(Field_value_.value, result->mutable_Field());
    if (_status != ZX_OK) return _status;
  } else {
    result->clear_Field();
  }
  return ::fidl::Clone(_unknown_data, &result->_unknown_data);
}

extern "C" const fidl_type_t fidl_test_doccomments_StructTable;
const fidl_type_t* Struct::FidlType = &fidl_test_doccomments_StructTable;

void Struct::Encode(
    ::fidl::Encoder* _encoder, size_t _offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<Struct>::value) {
    memcpy(_encoder->template GetPtr<Struct>(_offset), this, sizeof(Struct));
  } else {
    ::fidl::Encode(_encoder, &Field, _offset + 0);
  }
}

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

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

extern "C" const fidl_type_t fidl_test_doccomments_StrictUnionTable;
const fidl_type_t* StrictUnion::FidlType =
    &fidl_test_doccomments_StrictUnionTable;

StrictUnion::StrictUnion() {}

StrictUnion::~StrictUnion() { Destroy(); }

StrictUnion::StrictUnion(StrictUnion&& other) : tag_(other.tag_) {
  switch (tag_) {
    case ::fidl::test::doccomments::StrictUnion::Tag::kField:
      Field_ = std::move(other.Field_);
      break;
    case static_cast<fidl_xunion_tag_t>(
        ::fidl::test::doccomments::StrictUnion::Tag::Invalid):
      break;
  }
}

StrictUnion& StrictUnion::operator=(StrictUnion&& other) {
  if (this != &other) {
    Destroy();
    tag_ = other.tag_;
    switch (tag_) {
      case ::fidl::test::doccomments::StrictUnion::Tag::kField:
        Field_ = std::move(other.Field_);
        break;
      case static_cast<fidl_xunion_tag_t>(
          ::fidl::test::doccomments::StrictUnion::Tag::Invalid):
        break;
    }
  }
  return *this;
}

StrictUnion StrictUnion::WithField(int32_t&& val) {
  StrictUnion result;
  result.set_Field(std::move(val));
  return result;
}

void StrictUnion::Encode(
    ::fidl::Encoder* encoder, size_t offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  const size_t length_before = encoder->CurrentLength();
  const size_t handles_before = encoder->CurrentHandleCount();

  size_t envelope_offset = 0;

  switch (Which()) {
    case ::fidl::test::doccomments::StrictUnion::Tag::kField: {
      envelope_offset = encoder->Alloc(
          ::fidl::EncodingInlineSize<int32_t, ::fidl::Encoder>(encoder));
      ::fidl::Encode(encoder, &Field_, envelope_offset);
      break;
    }
    default:
      break;
  }

  fidl_xunion_t* xunion = encoder->GetPtr<fidl_xunion_t>(offset);
  assert(xunion->envelope.presence == FIDL_ALLOC_ABSENT);

  if (envelope_offset) {
    xunion->tag = tag_;
    xunion->envelope.num_bytes =
        static_cast<uint32_t>(encoder->CurrentLength() - length_before);
    xunion->envelope.num_handles =
        static_cast<uint32_t>(encoder->CurrentHandleCount() - handles_before);
    xunion->envelope.presence = FIDL_ALLOC_PRESENT;
  }
}

void StrictUnion::Decode(::fidl::Decoder* decoder, StrictUnion* value,
                         size_t offset) {
  fidl_xunion_t* xunion = decoder->GetPtr<fidl_xunion_t>(offset);

  if (!xunion->envelope.data) {
    value->EnsureStorageInitialized(static_cast<fidl_xunion_tag_t>(
        ::fidl::test::doccomments::StrictUnion::Tag::Invalid));
    return;
  }

  value->EnsureStorageInitialized(xunion->tag);

  const size_t envelope_offset = decoder->GetOffset(xunion->envelope.data);

  switch (value->tag_) {
    case ::fidl::test::doccomments::StrictUnion::Tag::kField:
      ::fidl::Decode(decoder, &value->Field_, envelope_offset);
      break;
    default:
      break;
  }
}

zx_status_t StrictUnion::Clone(StrictUnion* result) const {
  result->Destroy();
  result->tag_ = tag_;
  switch (tag_) {
    case ::fidl::test::doccomments::StrictUnion::Tag::Invalid:
      return ZX_OK;
    case ::fidl::test::doccomments::StrictUnion::Tag::kField:
      return ::fidl::Clone(Field_, &result->Field_);
    default:
      return ZX_OK;
  }
}

StrictUnion& StrictUnion::set_Field(int32_t value) {
  EnsureStorageInitialized(::fidl::test::doccomments::StrictUnion::Tag::kField);
  Field_ = std::move(value);
  return *this;
}

void StrictUnion::Destroy() {
  switch (tag_) {
    case ::fidl::test::doccomments::StrictUnion::Tag::kField:
      break;

    default:
      break;
  }
  tag_ = static_cast<fidl_xunion_tag_t>(
      ::fidl::test::doccomments::StrictUnion::Tag::Invalid);
}

void StrictUnion::EnsureStorageInitialized(::fidl_xunion_tag_t tag) {
  if (tag_ != tag) {
    Destroy();
    tag_ = tag;
    switch (tag_) {
      case static_cast<fidl_xunion_tag_t>(
          ::fidl::test::doccomments::StrictUnion::Tag::Invalid):
        break;
      case ::fidl::test::doccomments::StrictUnion::Tag::kField:
        new (&Field_) int32_t();
        break;
      default:
        break;
    }
  }
}

#if (__cplusplus < 201703)
constexpr const ::fidl::test::doccomments::MyFlexibleEnum MyFlexibleEnum::FOO =
    ::fidl::test::doccomments::MyFlexibleEnum(1u);
constexpr const ::fidl::test::doccomments::MyFlexibleEnum MyFlexibleEnum::BAR =
    ::fidl::test::doccomments::MyFlexibleEnum(2u);
#endif  // (__cplusplus < 201703)

#if (__cplusplus < 201703)
constexpr const ::fidl::test::doccomments::MyFlexibleBits
    MyFlexibleBits::MY_FIRST_BIT =
        ::fidl::test::doccomments::MyFlexibleBits(1u);
constexpr const ::fidl::test::doccomments::MyFlexibleBits
    MyFlexibleBits::MY_OTHER_BIT =
        ::fidl::test::doccomments::MyFlexibleBits(2u);
constexpr const ::fidl::test::doccomments::MyFlexibleBits
    MyFlexibleBits::kMask = ::fidl::test::doccomments::MyFlexibleBits(3u);

#endif  // (__cplusplus < 201703)

extern "C" const fidl_type_t fidl_test_doccomments_FlexibleUnionTable;
const fidl_type_t* FlexibleUnion::FidlType =
    &fidl_test_doccomments_FlexibleUnionTable;

FlexibleUnion::FlexibleUnion() {}

FlexibleUnion::~FlexibleUnion() { Destroy(); }

FlexibleUnion::FlexibleUnion(FlexibleUnion&& other) : tag_(other.tag_) {
  switch (tag_) {
    case ::fidl::test::doccomments::FlexibleUnion::Tag::kField:
      Field_ = std::move(other.Field_);
      break;
    case static_cast<fidl_xunion_tag_t>(
        ::fidl::test::doccomments::FlexibleUnion::Tag::Invalid):
      break;
    default:
      new (&unknown_data_) decltype(unknown_data_);
      unknown_data_ = std::move(other.unknown_data_);
      break;
  }
}

FlexibleUnion& FlexibleUnion::operator=(FlexibleUnion&& other) {
  if (this != &other) {
    Destroy();
    tag_ = other.tag_;
    switch (tag_) {
      case ::fidl::test::doccomments::FlexibleUnion::Tag::kField:
        Field_ = std::move(other.Field_);
        break;
      case static_cast<fidl_xunion_tag_t>(
          ::fidl::test::doccomments::FlexibleUnion::Tag::Invalid):
        break;
      default:
        new (&unknown_data_) decltype(unknown_data_);
        unknown_data_ = std::move(other.unknown_data_);
        break;
    }
  }
  return *this;
}

FlexibleUnion FlexibleUnion::WithField(int32_t&& val) {
  FlexibleUnion result;
  result.set_Field(std::move(val));
  return result;
}

void FlexibleUnion::Encode(
    ::fidl::Encoder* encoder, size_t offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  const size_t length_before = encoder->CurrentLength();
  const size_t handles_before = encoder->CurrentHandleCount();

  size_t envelope_offset = 0;

  switch (Which()) {
    case ::fidl::test::doccomments::FlexibleUnion::Tag::kField: {
      envelope_offset = encoder->Alloc(
          ::fidl::EncodingInlineSize<int32_t, ::fidl::Encoder>(encoder));
      ::fidl::Encode(encoder, &Field_, envelope_offset);
      break;
    }
    case ::fidl::test::doccomments::FlexibleUnion::Tag::kUnknown:
      envelope_offset = encoder->Alloc(unknown_data_.size());
      ::fidl::EncodeUnknownBytesContents(encoder, &unknown_data_,
                                         envelope_offset);
      break;
    default:
      break;
  }

  fidl_xunion_t* xunion = encoder->GetPtr<fidl_xunion_t>(offset);
  assert(xunion->envelope.presence == FIDL_ALLOC_ABSENT);

  if (envelope_offset) {
    xunion->tag = tag_;
    xunion->envelope.num_bytes =
        static_cast<uint32_t>(encoder->CurrentLength() - length_before);
    xunion->envelope.num_handles =
        static_cast<uint32_t>(encoder->CurrentHandleCount() - handles_before);
    xunion->envelope.presence = FIDL_ALLOC_PRESENT;
  }
}

void FlexibleUnion::Decode(::fidl::Decoder* decoder, FlexibleUnion* value,
                           size_t offset) {
  fidl_xunion_t* xunion = decoder->GetPtr<fidl_xunion_t>(offset);

  if (!xunion->envelope.data) {
    value->EnsureStorageInitialized(static_cast<fidl_xunion_tag_t>(
        ::fidl::test::doccomments::FlexibleUnion::Tag::Invalid));
    return;
  }

  value->EnsureStorageInitialized(xunion->tag);

  const size_t envelope_offset = decoder->GetOffset(xunion->envelope.data);

  switch (value->tag_) {
    case ::fidl::test::doccomments::FlexibleUnion::Tag::kField:
      ::fidl::Decode(decoder, &value->Field_, envelope_offset);
      break;
    default:

      value->unknown_data_.resize(xunion->envelope.num_bytes);
      ::fidl::DecodeUnknownBytesContents(decoder, &value->unknown_data_,
                                         envelope_offset);
      break;
  }
}

zx_status_t FlexibleUnion::Clone(FlexibleUnion* result) const {
  result->Destroy();
  result->tag_ = tag_;
  switch (tag_) {
    case ::fidl::test::doccomments::FlexibleUnion::Tag::Invalid:
      return ZX_OK;
    case ::fidl::test::doccomments::FlexibleUnion::Tag::kField:
      return ::fidl::Clone(Field_, &result->Field_);
    default:
      new (&result->unknown_data_) decltype(unknown_data_);
      return ::fidl::Clone(unknown_data_, &result->unknown_data_);
      return ZX_OK;
  }
}

FlexibleUnion& FlexibleUnion::set_Field(int32_t value) {
  EnsureStorageInitialized(
      ::fidl::test::doccomments::FlexibleUnion::Tag::kField);
  Field_ = std::move(value);
  return *this;
}
FlexibleUnion& FlexibleUnion::SetUnknownData(fidl_xunion_tag_t ordinal,
                                             std::vector<uint8_t> bytes) {
  EnsureStorageInitialized(ordinal);
  unknown_data_ = std::move(bytes);
  return *this;
}

void FlexibleUnion::Destroy() {
  switch (tag_) {
    case ::fidl::test::doccomments::FlexibleUnion::Tag::kField:
      break;

    case static_cast<fidl_xunion_tag_t>(
        ::fidl::test::doccomments::FlexibleUnion::Tag::Invalid):
      break;
    default:
      unknown_data_.~decltype(unknown_data_)();
      break;
  }
  tag_ = static_cast<fidl_xunion_tag_t>(
      ::fidl::test::doccomments::FlexibleUnion::Tag::Invalid);
}

void FlexibleUnion::EnsureStorageInitialized(::fidl_xunion_tag_t tag) {
  if (tag_ != tag) {
    Destroy();
    tag_ = tag;
    switch (tag_) {
      case static_cast<fidl_xunion_tag_t>(
          ::fidl::test::doccomments::FlexibleUnion::Tag::Invalid):
        break;
      case ::fidl::test::doccomments::FlexibleUnion::Tag::kField:
        new (&Field_) int32_t();
        break;
      default:
        new (&unknown_data_) decltype(unknown_data_);
        break;
    }
  }
}

//
// Proxies and stubs definitions
//
#ifdef __Fuchsia__

namespace _internal {
extern "C" const fidl_type_t fidl_test_doccomments_InterfaceMethodRequestTable;

extern "C" const fidl_type_t fidl_test_doccomments_InterfaceOnEventEventTable;

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

const fidl_type_t* ::fidl::test::doccomments::Interface_RequestDecoder::GetType(
    uint64_t ordinal, bool* out_needs_response) {
  switch (ordinal) {
    case ::fidl::test::doccomments::internal::kInterface_Method_Ordinal:
      *out_needs_response = false;
      return &::fidl::test::doccomments::_internal::
          fidl_test_doccomments_InterfaceMethodRequestTable;
    default:
      *out_needs_response = false;
      return nullptr;
  }
}

const fidl_type_t* Interface_ResponseDecoder::GetType(uint64_t ordinal) {
  switch (ordinal) {
    case ::fidl::test::doccomments::internal::kInterface_OnEvent_Ordinal:
      return &::fidl::test::doccomments::_internal::
          fidl_test_doccomments_InterfaceOnEventEventTable;
    default:
      return nullptr;
  }
}

Interface_EventSender::~Interface_EventSender() = default;

Interface_Sync::~Interface_Sync() = default;

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

Interface_Proxy::~Interface_Proxy() = default;

zx_status_t Interface_Proxy::Dispatch_(::fidl::HLCPPIncomingMessage message) {
  zx_status_t status = ZX_OK;
  switch (message.ordinal()) {
    case ::fidl::test::doccomments::internal::kInterface_OnEvent_Ordinal: {
      if (!OnEvent) {
        status = ZX_OK;
        break;
      }
      const char* error_msg = nullptr;
      status =
          message.Decode(&::fidl::test::doccomments::_internal::
                             fidl_test_doccomments_InterfaceOnEventEventTable,
                         &error_msg);
      if (status != ZX_OK) {
        FIDL_REPORT_DECODING_ERROR(
            message,
            &::fidl::test::doccomments::_internal::
                fidl_test_doccomments_InterfaceOnEventEventTable,
            error_msg);
        break;
      }
      OnEvent();
      break;
    }
    default: {
      status = ZX_ERR_NOT_SUPPORTED;
      break;
    }
  }
  return status;
}

void Interface_Proxy::Method() {
  ::fidl::Encoder _encoder(
      ::fidl::test::doccomments::internal::kInterface_Method_Ordinal);
  controller_->Send(
      &::fidl::test::doccomments::_internal::
          fidl_test_doccomments_InterfaceMethodRequestTable,
      ::fidl::test::doccomments::Interface_RequestEncoder::Method(&_encoder),
      nullptr);
}

Interface_Stub::Interface_Stub(
    ::fidl::test::doccomments::Interface_Stub::Interface_clazz* impl)
    : impl_(impl) {
  (void)impl_;
}

Interface_Stub::~Interface_Stub() = default;

namespace {}  // namespace

zx_status_t Interface_Stub::Dispatch_(
    ::fidl::HLCPPIncomingMessage message,
    ::fidl::internal::PendingResponse response) {
  bool needs_response;
  const fidl_type_t* request_type =
      ::fidl::test::doccomments::Interface_RequestDecoder::GetType(
          message.ordinal(), &needs_response);
  if (request_type == nullptr) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  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;
  }
  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;
  }
  uint64_t ordinal = message.ordinal();
  switch (ordinal) {
    case ::fidl::test::doccomments::internal::kInterface_Method_Ordinal: {
      impl_->Method();
      break;
    }
    default: {
      status = ZX_ERR_NOT_SUPPORTED;
      break;
    }
  }
  return status;
}
void Interface_Stub::OnEvent() {
  ::fidl::Encoder _encoder(
      ::fidl::test::doccomments::internal::kInterface_OnEvent_Ordinal);
  sender_()->Send(
      &::fidl::test::doccomments::_internal::
          fidl_test_doccomments_InterfaceOnEventEventTable,
      ::fidl::test::doccomments::Interface_ResponseEncoder::OnEvent(&_encoder));
}

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

Interface_SyncProxy::~Interface_SyncProxy() = default;

zx_status_t Interface_SyncProxy::Method() {
  ::fidl::Encoder _encoder(
      ::fidl::test::doccomments::internal::kInterface_Method_Ordinal);
  return proxy_.Send(
      &::fidl::test::doccomments::_internal::
          fidl_test_doccomments_InterfaceMethodRequestTable,
      ::fidl::test::doccomments::Interface_RequestEncoder::Method(&_encoder));
}
#endif  // __Fuchsia__

}  // namespace doccomments
}  // namespace test
}  // namespace fidl
