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

#pragma once

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

#include <cinttypes>
#include <string>

#ifdef __Fuchsia__

#include <lib/zx/channel.h>

#endif  // __Fuchsia__

namespace test_inheritance {
class SuperFooTopResponse;

class SuperFooRequest;

extern "C" const fidl_type_t test_inheritance_SuperFooTopResponseTable;

class SuperFooTopResponse {
 private:
  struct Storage_;

 public:
  SuperFooTopResponse(Storage_ storage) noexcept
      : storage_(std::move(storage)) {}
  SuperFooTopResponse(int64_t y) noexcept : storage_({.y = std::move(y)}) {}

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

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

  bool operator==(const SuperFooTopResponse& other) const noexcept {
    return ::fidl::internal::NaturalStructCodingTraits<
        ::test_inheritance::SuperFooTopResponse, 8>::Equal(this, &other);
  }
  bool operator!=(const SuperFooTopResponse& other) const noexcept {
    return !::fidl::internal::NaturalStructCodingTraits<
        ::test_inheritance::SuperFooTopResponse, 8>::Equal(this, &other);
  }

  int64_t y() const { return storage_.y; }

  int64_t& y() { return storage_.y; }

  SuperFooTopResponse(
      ::fidl::internal::DefaultConstructPossiblyInvalidObjectTag)
      : SuperFooTopResponse(Storage_{
            .y = {},
        }) {}

 private:
  struct Storage_ final {
    int64_t y = {};
  };

  Storage_ storage_;
  Storage_ CloneStorage_() const;

  friend struct ::fidl::internal::NaturalStructCodingTraits<
      ::test_inheritance::SuperFooTopResponse, 8>;
  friend struct ::fidl::internal::MemberVisitor<
      ::test_inheritance::SuperFooTopResponse>;
  static constexpr auto kMembers = std::make_tuple(
      ::fidl::internal::NaturalStructMember<
          Storage_, int64_t, fidl::internal::NaturalCodingConstraintEmpty>{
          &Storage_::y, 0});
  static constexpr auto kPadding = std::make_tuple();
};

extern "C" const fidl_type_t test_inheritance_SuperFooRequestTable;

class SuperFooRequest {
 private:
  struct Storage_;

 public:
  SuperFooRequest(Storage_ storage) noexcept : storage_(std::move(storage)) {}
  SuperFooRequest(::std::string s) noexcept : storage_({.s = std::move(s)}) {}

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

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

  bool operator==(const SuperFooRequest& other) const noexcept {
    return ::fidl::internal::NaturalStructCodingTraits<
        ::test_inheritance::SuperFooRequest, 16>::Equal(this, &other);
  }
  bool operator!=(const SuperFooRequest& other) const noexcept {
    return !::fidl::internal::NaturalStructCodingTraits<
        ::test_inheritance::SuperFooRequest, 16>::Equal(this, &other);
  }

  const ::std::string& s() const { return storage_.s; }

  ::std::string& s() { return storage_.s; }

  SuperFooRequest(::fidl::internal::DefaultConstructPossiblyInvalidObjectTag)
      : SuperFooRequest(Storage_{
            .s = {},
        }) {}

 private:
  struct Storage_ final {
    ::std::string s;
  };

  Storage_ storage_;
  Storage_ CloneStorage_() const;

  friend struct ::fidl::internal::NaturalStructCodingTraits<
      ::test_inheritance::SuperFooRequest, 16>;
  friend struct ::fidl::internal::MemberVisitor<
      ::test_inheritance::SuperFooRequest>;
  static constexpr auto kMembers = std::make_tuple(
      ::fidl::internal::NaturalStructMember<
          Storage_, ::std::string,
          fidl::internal::NaturalCodingConstraintString<>>{&Storage_::s, 0});
  static constexpr auto kPadding = std::make_tuple();
};

}  // namespace test_inheritance
namespace fidl {

extern "C" const fidl_type_t test_inheritance_SuperFooTopResponseTable;

template <>
struct IsFidlType<::test_inheritance::SuperFooTopResponse>
    : public std::true_type {};

template <>
struct ::fidl::internal::TypeTraits<::test_inheritance::SuperFooTopResponse>
    final {
 public:
  static constexpr const fidl_type_t* kCodingTable =
      &test_inheritance_SuperFooTopResponseTable;
};

template <>
struct internal::NaturalCodingTraits<
    ::test_inheritance::SuperFooTopResponse,
    ::fidl::internal::NaturalCodingConstraintEmpty>
    final : public ::fidl::internal::NaturalStructCodingTraits<
                ::test_inheritance::SuperFooTopResponse, 8> {};

extern "C" const fidl_type_t test_inheritance_SuperFooRequestTable;

template <>
struct IsFidlType<::test_inheritance::SuperFooRequest> : public std::true_type {
};

template <>
struct ::fidl::internal::TypeTraits<::test_inheritance::SuperFooRequest> final {
 public:
  static constexpr const fidl_type_t* kCodingTable =
      &test_inheritance_SuperFooRequestTable;
};

template <>
struct internal::NaturalCodingTraits<
    ::test_inheritance::SuperFooRequest,
    ::fidl::internal::NaturalCodingConstraintEmpty>
    final : public ::fidl::internal::NaturalStructCodingTraits<
                ::test_inheritance::SuperFooRequest, 16> {};

}  // namespace fidl
