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

#pragma once

#include <fidl/test.transitivedependencies/cpp/common_types.h>
#include <fidl/test.transitivedependencies/cpp/markers.h>
#include <lib/fidl/cpp/natural_coding_traits.h>
#include <lib/fidl/cpp/natural_types.h>

#include <cinttypes>
#include <string>

#ifdef __Fuchsia__

#endif  // __Fuchsia__

#include <fidl/test.middle/cpp/natural_types.h>

namespace test_transitivedependencies {
class Baz;

extern "C" const fidl_type_t test_transitivedependencies_BazTable;

class Baz {
 private:
  struct Storage_;

 public:
  Baz(Storage_ storage) noexcept : storage_(std::move(storage)) {}
  Baz(::test_middle::Bar g) noexcept : storage_({.g = std::move(g)}) {}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdefaulted-function-deleted"
  // Default constructs a |Baz| only if all of its members are default
  // constructible.
  Baz() = default;
#pragma clang diagnostic pop

  Baz(Baz&&) noexcept = default;
  Baz& operator=(Baz&&) noexcept = default;
  Baz(const Baz& other) noexcept : Baz(other.CloneStorage_()) {}
  Baz& operator=(const Baz& other) noexcept {
    storage_ = other.CloneStorage_();
    return *this;
  }

  bool operator==(const Baz& other) const noexcept {
    return ::fidl::internal::NaturalStructCodingTraits<
        ::test_transitivedependencies::Baz, 4>::Equal(this, &other);
  }
  bool operator!=(const Baz& other) const noexcept {
    return !::fidl::internal::NaturalStructCodingTraits<
        ::test_transitivedependencies::Baz, 4>::Equal(this, &other);
  }

  const ::test_middle::Bar& g() const { return storage_.g; }

  ::test_middle::Bar& g() { return storage_.g; }

  Baz(::fidl::internal::DefaultConstructPossiblyInvalidObjectTag)
      : Baz(Storage_{
            .g = ::fidl::internal::DefaultConstructPossiblyInvalidObjectTag{},
        }) {}

 private:
  struct Storage_ final {
    ::test_middle::Bar g;
  };

  Storage_ storage_;
  Storage_ CloneStorage_() const;

  friend struct ::fidl::internal::NaturalStructCodingTraits<
      ::test_transitivedependencies::Baz, 4>;
  friend struct ::fidl::internal::MemberVisitor<
      ::test_transitivedependencies::Baz>;
  static constexpr auto kMembers = std::make_tuple(
      ::fidl::internal::NaturalStructMember<
          Storage_, ::test_middle::Bar,
          fidl::internal::NaturalCodingConstraintEmpty>{&Storage_::g, 0});
  static constexpr auto kPadding = std::make_tuple();
};

}  // namespace test_transitivedependencies
namespace fidl {

extern "C" const fidl_type_t test_transitivedependencies_BazTable;

template <>
struct IsFidlType<::test_transitivedependencies::Baz> : public std::true_type {
};

template <>
struct ::fidl::internal::TypeTraits<::test_transitivedependencies::Baz> final {
 public:
  static constexpr const fidl_type_t* kCodingTable =
      &test_transitivedependencies_BazTable;
};

template <>
struct internal::NaturalCodingTraits<
    ::test_transitivedependencies::Baz,
    ::fidl::internal::NaturalCodingConstraintEmpty>
    final : public ::fidl::internal::NaturalStructCodingTraits<
                ::test_transitivedependencies::Baz, 4> {};

}  // namespace fidl
