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

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

namespace fidl {
namespace internal {

::test_doccomments::Struct WireNaturalConversionTraits<::test_doccomments::wire::Struct, ::test_doccomments::Struct>::ToNatural(::test_doccomments::wire::Struct src) {
  return ::test_doccomments::Struct(WireNaturalConversionTraits<int32_t, int32_t>::ToNatural(std::move(src.field)));
}
::test_doccomments::wire::Struct WireNaturalConversionTraits<::test_doccomments::wire::Struct, ::test_doccomments::Struct>::ToWire(fidl::AnyArena& arena, ::test_doccomments::Struct src) {
  return ::test_doccomments::wire::Struct{
      .field = WireNaturalConversionTraits<int32_t, int32_t>::ToWire(arena, std::move(src.field())),
  };
}

::test_doccomments::Table WireNaturalConversionTraits<::test_doccomments::wire::Table, ::test_doccomments::Table>::ToNatural(::test_doccomments::wire::Table src) {
  ::test_doccomments::Table dst;
  if (src.has_Field()) {
    dst.field() =
        WireNaturalConversionTraits<int32_t, int32_t>::ToNatural(std::move(src.field()));
  }

  return dst;
}
::test_doccomments::wire::Table WireNaturalConversionTraits<::test_doccomments::wire::Table, ::test_doccomments::Table>::ToWire(fidl::AnyArena& arena, ::test_doccomments::Table src) {
  auto builder = ::test_doccomments::wire::Table::Builder(arena);
  if (src.field().has_value()) {
    builder.field(
        WireNaturalConversionTraits<int32_t, int32_t>::ToWire(arena, std::move(src.field().value())));
  }
  return builder.Build();
}

::test_doccomments::StrictUnion WireNaturalConversionTraits<::test_doccomments::wire::StrictUnion, ::test_doccomments::StrictUnion>::ToNatural(::test_doccomments::wire::StrictUnion src) {
  switch (src.Which()) {
    case ::test_doccomments::wire::StrictUnion::Tag::kField:
      return ::test_doccomments::StrictUnion::WithField(
          WireNaturalConversionTraits<int32_t, int32_t>::ToNatural(std::move(src.field())));
    default:
      ZX_PANIC("unknown union tag in strict union");
  }
}
::test_doccomments::wire::StrictUnion WireNaturalConversionTraits<::test_doccomments::wire::StrictUnion, ::test_doccomments::StrictUnion>::ToWire(fidl::AnyArena& arena, ::test_doccomments::StrictUnion src) {
  switch (src.Which()) {
    case ::test_doccomments::StrictUnion::Tag::kField:
      return ::test_doccomments::wire::StrictUnion::WithField(
          WireNaturalConversionTraits<int32_t, int32_t>::ToWire(arena, std::move(src.field().value())));
  }
}

std::unique_ptr<::test_doccomments::StrictUnion> WireNaturalConversionTraits<::test_doccomments::wire::StrictUnion, std::unique_ptr<::test_doccomments::StrictUnion>>::ToNatural(::test_doccomments::wire::StrictUnion src) {
  if (src.has_invalid_tag()) {
    return nullptr;
  }
  return std::make_unique<::test_doccomments::StrictUnion>(WireNaturalConversionTraits<::test_doccomments::wire::StrictUnion, ::test_doccomments::StrictUnion>::ToNatural(std::move(src)));
}
::test_doccomments::wire::StrictUnion WireNaturalConversionTraits<::test_doccomments::wire::StrictUnion, std::unique_ptr<::test_doccomments::StrictUnion>>::ToWire(fidl::AnyArena& arena, std::unique_ptr<::test_doccomments::StrictUnion> src) {
  if (!src) {
    return ::test_doccomments::wire::StrictUnion();
  }
  return WireNaturalConversionTraits<::test_doccomments::wire::StrictUnion, ::test_doccomments::StrictUnion>::ToWire(arena, std::move(*src));
}

::test_doccomments::FlexibleUnion WireNaturalConversionTraits<::test_doccomments::wire::FlexibleUnion, ::test_doccomments::FlexibleUnion>::ToNatural(::test_doccomments::wire::FlexibleUnion src) {
  switch (src.Which()) {
    case ::test_doccomments::wire::FlexibleUnion::Tag::kField:
      return ::test_doccomments::FlexibleUnion::WithField(
          WireNaturalConversionTraits<int32_t, int32_t>::ToNatural(std::move(src.field())));
    default:
      return ::test_doccomments::FlexibleUnion();
  }
}
::test_doccomments::wire::FlexibleUnion WireNaturalConversionTraits<::test_doccomments::wire::FlexibleUnion, ::test_doccomments::FlexibleUnion>::ToWire(fidl::AnyArena& arena, ::test_doccomments::FlexibleUnion src) {
  switch (src.Which()) {
    case ::test_doccomments::FlexibleUnion::Tag::kField:
      return ::test_doccomments::wire::FlexibleUnion::WithField(
          WireNaturalConversionTraits<int32_t, int32_t>::ToWire(arena, std::move(src.field().value())));
    default:
      return ::test_doccomments::wire::FlexibleUnion();
  }
}

std::unique_ptr<::test_doccomments::FlexibleUnion> WireNaturalConversionTraits<::test_doccomments::wire::FlexibleUnion, std::unique_ptr<::test_doccomments::FlexibleUnion>>::ToNatural(::test_doccomments::wire::FlexibleUnion src) {
  if (src.has_invalid_tag()) {
    return nullptr;
  }
  return std::make_unique<::test_doccomments::FlexibleUnion>(WireNaturalConversionTraits<::test_doccomments::wire::FlexibleUnion, ::test_doccomments::FlexibleUnion>::ToNatural(std::move(src)));
}
::test_doccomments::wire::FlexibleUnion WireNaturalConversionTraits<::test_doccomments::wire::FlexibleUnion, std::unique_ptr<::test_doccomments::FlexibleUnion>>::ToWire(fidl::AnyArena& arena, std::unique_ptr<::test_doccomments::FlexibleUnion> src) {
  if (!src) {
    return ::test_doccomments::wire::FlexibleUnion();
  }
  return WireNaturalConversionTraits<::test_doccomments::wire::FlexibleUnion, ::test_doccomments::FlexibleUnion>::ToWire(arena, std::move(*src));
}

#ifdef __Fuchsia__

::fidl::Request<::test_doccomments::Interface::Method> WireNaturalConversionTraits<::fidl::WireRequest<::test_doccomments::Interface::Method>, ::fidl::Request<::test_doccomments::Interface::Method>>::ToNatural(::fidl::WireRequest<::test_doccomments::Interface::Method> src) {
  return ::fidl::Request<::test_doccomments::Interface::Method>();
}
::fidl::WireRequest<::test_doccomments::Interface::Method> WireNaturalConversionTraits<::fidl::WireRequest<::test_doccomments::Interface::Method>, ::fidl::Request<::test_doccomments::Interface::Method>>::ToWire(fidl::AnyArena& arena, ::fidl::Request<::test_doccomments::Interface::Method> src) {
  return ::fidl::WireRequest<::test_doccomments::Interface::Method>();
}

::fidl::Event<::test_doccomments::Interface::OnEvent> WireNaturalConversionTraits<::fidl::WireEvent<::test_doccomments::Interface::OnEvent>, ::fidl::Event<::test_doccomments::Interface::OnEvent>>::ToNatural(::fidl::WireEvent<::test_doccomments::Interface::OnEvent> src) {
  return ::fidl::Event<::test_doccomments::Interface::OnEvent>();
}
::fidl::WireEvent<::test_doccomments::Interface::OnEvent> WireNaturalConversionTraits<::fidl::WireEvent<::test_doccomments::Interface::OnEvent>, ::fidl::Event<::test_doccomments::Interface::OnEvent>>::ToWire(fidl::AnyArena& arena, ::fidl::Event<::test_doccomments::Interface::OnEvent> src) {
  return ::fidl::WireEvent<::test_doccomments::Interface::OnEvent>();
}
#endif  // __Fuchsia__
}  // namespace internal
}  // namespace fidl
