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

// fidl_experiment = output_index_json

#include <fidl/test.anonymous/cpp/wire_types.h>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow"

auto ::test_anonymous::wire::Expression::Which() const -> ::test_anonymous::wire::Expression::Tag {
  ZX_ASSERT(!has_invalid_tag());
  switch (ordinal_) {
    case ::test_anonymous::wire::Expression::Ordinal::kValue:
    case ::test_anonymous::wire::Expression::Ordinal::kBinOp:
    case ::test_anonymous::wire::Expression::Ordinal::kFunctionApplication:
      return static_cast<::test_anonymous::wire::Expression::Tag>(ordinal_);
    default:
      return ::test_anonymous::wire::Expression::Tag::_do_not_handle_this__write_a_default_case_instead;
  }
}

void ::test_anonymous::wire::Expression::SizeAndOffsetAssertionHelper() {
  static_assert(sizeof(Expression) == sizeof(fidl_union_t));
  static_assert(offsetof(Expression, ordinal_) == offsetof(fidl_union_t, tag));
  static_assert(offsetof(Expression, envelope_) == offsetof(fidl_union_t, envelope));
}

auto ::test_anonymous::wire::UnionMember::Which() const -> ::test_anonymous::wire::UnionMember::Tag {
  ZX_ASSERT(!has_invalid_tag());
  switch (ordinal_) {
    case ::test_anonymous::wire::UnionMember::Ordinal::kUnionData:
      return static_cast<::test_anonymous::wire::UnionMember::Tag>(ordinal_);
    default:
      return ::test_anonymous::wire::UnionMember::Tag::_do_not_handle_this__write_a_default_case_instead;
  }
}

void ::test_anonymous::wire::UnionMember::SizeAndOffsetAssertionHelper() {
  static_assert(sizeof(UnionMember) == sizeof(fidl_union_t));
  static_assert(offsetof(UnionMember, ordinal_) == offsetof(fidl_union_t, tag));
  static_assert(offsetof(UnionMember, envelope_) == offsetof(fidl_union_t, envelope));
}

void ::test_anonymous::wire::SomeProtocolSomeMethodResult::SizeAndOffsetAssertionHelper() {
  static_assert(sizeof(SomeProtocolSomeMethodResult) == sizeof(fidl_union_t));
  static_assert(offsetof(SomeProtocolSomeMethodResult, ordinal_) == offsetof(fidl_union_t, tag));
  static_assert(offsetof(SomeProtocolSomeMethodResult, envelope_) == offsetof(fidl_union_t, envelope));
}

bool ::fidl::WireTableFrame<::test_anonymous::wire::FunctionApplication>::HasUnknownData() const {
  if (!reserved_1_.IsZeroEnvelope()) {
    return true;
  }
  return false;
}

uint64_t fidl::WireTableFrame<::test_anonymous::wire::FunctionApplication>::ComputeMaxOrdinal() const {
  uint64_t max_ordinal = 0;
  if (!func_.has_data()) {
    max_ordinal = 1;
  }
  if (!reserved_1_.IsZeroEnvelope()) {
    max_ordinal = 1;
  }
  if (!args_.has_data()) {
    max_ordinal = 3;
  }
  if (!flags_.has_data()) {
    max_ordinal = 4;
  }
  return max_ordinal;
}

bool ::test_anonymous::wire::FunctionApplication::HasUnknownData() const {
  if (max_ordinal_ > 4) {
    return true;
  }
  if (frame_ptr_ == nullptr) {
    return false;
  }
  return frame_ptr_->HasUnknownData();
}

bool ::fidl::WireTableFrame<::test_anonymous::wire::TableMember>::HasUnknownData() const {
  if (!reserved_0_.IsZeroEnvelope()) {
    return true;
  }
  return false;
}

uint64_t fidl::WireTableFrame<::test_anonymous::wire::TableMember>::ComputeMaxOrdinal() const {
  uint64_t max_ordinal = 0;
  if (!reserved_0_.IsZeroEnvelope()) {
    max_ordinal = 0;
  }
  if (!table_data_.has_data()) {
    max_ordinal = 2;
  }
  return max_ordinal;
}

bool ::test_anonymous::wire::TableMember::HasUnknownData() const {
  if (max_ordinal_ > 2) {
    return true;
  }
  if (frame_ptr_ == nullptr) {
    return false;
  }
  return frame_ptr_->HasUnknownData();
}

#pragma clang diagnostic pop
