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

#pragma once

#include <fidl/test.error/cpp/common_types.h>
#include <fidl/test.error/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_error {
class ExampleFooResponse;

class ExampleFooTopResponse;

class ExampleFooRequest;

class ExampleFooResult;

extern "C" const fidl_type_t test_error_Example_foo_ResponseTable;

class ExampleFooResponse {
 private:
  struct Storage_;

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

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

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

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

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

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

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

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

  Storage_ storage_;
  Storage_ CloneStorage_() const;

  friend struct ::fidl::internal::NaturalStructCodingTraits<
      ::test_error::ExampleFooResponse, 8>;
  friend struct ::fidl::internal::MemberVisitor<
      ::test_error::ExampleFooResponse>;
  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_error_Example_foo_ResultTable;

class ExampleFooResult {
 private:
  using Storage_ =
      std::variant<std::monostate, ::test_error::ExampleFooResponse, uint32_t>;

 public:
  // TODO: share union tag types between wire & natural.
  enum class Tag : fidl_union_tag_t {
    kResponse = 1,  // 0x1
    kErr = 2,       // 0x2
  };

  ExampleFooResult(ExampleFooResult&& other) noexcept
      : ExampleFooResult(
            ::fidl::internal::DefaultConstructPossiblyInvalidObjectTag{}) {
    *storage_ = std::move(*other.storage_);
  }
  ExampleFooResult& operator=(ExampleFooResult&& other) noexcept {
    if (this != &other) {
      *storage_ = std::move(*other.storage_);
    }
    return *this;
  }
  ExampleFooResult(const ExampleFooResult& other) noexcept
      : ExampleFooResult(other.CloneStorage_()) {}
  ExampleFooResult& operator=(const ExampleFooResult& other) noexcept {
    if (this != &other) {
      storage_ = other.CloneStorage_();
    }
    return *this;
  }

  bool operator==(const ExampleFooResult& other) const noexcept {
    return *storage_ == *other.storage_;
  }
  bool operator!=(const ExampleFooResult& other) const noexcept {
    return *storage_ != *other.storage_;
  }

  constexpr ::test_error::ExampleFooResult::Tag Which() const {
    return ExampleFooResult::IndexToTag(storage_->index()).value();
  }
  static ExampleFooResult WithResponse(::test_error::ExampleFooResponse val) {
    return ExampleFooResult(
        std::make_shared<Storage_>(std::in_place_index_t<1>{}, std::move(val)));
  }

  const ::fidl::internal::UnionMemberView<1, Storage_> response() const {
    return ::fidl::internal::UnionMemberView<1, Storage_>(storage_);
  }
  ::fidl::internal::UnionMemberView<1, Storage_> response() {
    return ::fidl::internal::UnionMemberView<1, Storage_>(storage_);
  }
  static ExampleFooResult WithErr(uint32_t val) {
    return ExampleFooResult(
        std::make_shared<Storage_>(std::in_place_index_t<2>{}, std::move(val)));
  }

  const ::fidl::internal::UnionMemberView<2, Storage_> err() const {
    return ::fidl::internal::UnionMemberView<2, Storage_>(storage_);
  }
  ::fidl::internal::UnionMemberView<2, Storage_> err() {
    return ::fidl::internal::UnionMemberView<2, Storage_>(storage_);
  }

  ExampleFooResult(::fidl::internal::DefaultConstructPossiblyInvalidObjectTag)
      : storage_(std::make_shared<Storage_>()) {}

 private:
  std::shared_ptr<Storage_> storage_;
  std::shared_ptr<Storage_> CloneStorage_() const;
  friend struct ::fidl::internal::NaturalUnionCodingTraits<
      ::test_error::ExampleFooResult>;
  static constexpr auto kMembers =
      std::make_tuple(::fidl::internal::NaturalUnionMember<
                          ::fidl::internal::NaturalCodingConstraintEmpty>(),
                      ::fidl::internal::NaturalUnionMember<
                          fidl::internal::NaturalCodingConstraintEmpty>(),
                      ::fidl::internal::NaturalUnionMember<
                          fidl::internal::NaturalCodingConstraintEmpty>());

  explicit ExampleFooResult(std::shared_ptr<Storage_> storage)
      : storage_(std::move(storage)) {}

  static constexpr size_t TagToIndex(::fidl::internal::NaturalDecoder* decoder,
                                     ::test_error::ExampleFooResult::Tag tag) {
    switch (tag) {
      case ::test_error::ExampleFooResult::Tag::kResponse:
        return 1;
      case ::test_error::ExampleFooResult::Tag::kErr:
        return 2;
      default: {
        decoder->SetError(::fidl::internal::kCodingErrorUnknownUnionTag);
        return 0;
      }
    }
  }

  static constexpr std::optional<::test_error::ExampleFooResult::Tag>
  IndexToTag(size_t index) {
    switch (index) {
      case 1:
        return ::test_error::ExampleFooResult::Tag::kResponse;
      case 2:
        return ::test_error::ExampleFooResult::Tag::kErr;
      default:
        return std::nullopt;
    }
  }
};

extern "C" const fidl_type_t test_error_ExampleFooTopResponseTable;

class ExampleFooTopResponse {
 private:
  struct Storage_;

 public:
  ExampleFooTopResponse(Storage_ storage) noexcept
      : storage_(std::move(storage)) {}
  ExampleFooTopResponse(::test_error::ExampleFooResult result) noexcept
      : storage_({.result = std::move(result)}) {}

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

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

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

  const ::test_error::ExampleFooResult& result() const {
    return storage_.result;
  }

  ::test_error::ExampleFooResult& result() { return storage_.result; }

  ExampleFooTopResponse(
      ::fidl::internal::DefaultConstructPossiblyInvalidObjectTag)
      : ExampleFooTopResponse(Storage_{
            .result =
                ::fidl::internal::DefaultConstructPossiblyInvalidObjectTag{},
        }) {}

 private:
  struct Storage_ final {
    ::test_error::ExampleFooResult result;
  };

  Storage_ storage_;
  Storage_ CloneStorage_() const;

  friend struct ::fidl::internal::NaturalStructCodingTraits<
      ::test_error::ExampleFooTopResponse, 16>;
  friend struct ::fidl::internal::MemberVisitor<
      ::test_error::ExampleFooTopResponse>;
  static constexpr auto kMembers = std::make_tuple(
      ::fidl::internal::NaturalStructMember<
          Storage_, ::test_error::ExampleFooResult,
          fidl::internal::NaturalCodingConstraintEmpty>{&Storage_::result, 0});
  static constexpr auto kPadding = std::make_tuple();
};

extern "C" const fidl_type_t test_error_ExampleFooRequestTable;

class ExampleFooRequest {
 private:
  struct Storage_;

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

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

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

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

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

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

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

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

  Storage_ storage_;
  Storage_ CloneStorage_() const;

  friend struct ::fidl::internal::NaturalStructCodingTraits<
      ::test_error::ExampleFooRequest, 16>;
  friend struct ::fidl::internal::MemberVisitor<
      ::test_error::ExampleFooRequest>;
  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_error
namespace fidl {

extern "C" const fidl_type_t test_error_Example_foo_ResponseTable;

template <>
struct IsFidlType<::test_error::ExampleFooResponse> : public std::true_type {};

template <>
struct ::fidl::internal::TypeTraits<::test_error::ExampleFooResponse> final {
 public:
  static constexpr const fidl_type_t* kCodingTable =
      &test_error_Example_foo_ResponseTable;
};

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

extern "C" const fidl_type_t test_error_ExampleFooTopResponseTable;

template <>
struct IsFidlType<::test_error::ExampleFooTopResponse> : public std::true_type {
};

template <>
struct ::fidl::internal::TypeTraits<::test_error::ExampleFooTopResponse> final {
 public:
  static constexpr const fidl_type_t* kCodingTable =
      &test_error_ExampleFooTopResponseTable;
};

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

extern "C" const fidl_type_t test_error_ExampleFooRequestTable;

template <>
struct IsFidlType<::test_error::ExampleFooRequest> : public std::true_type {};

template <>
struct ::fidl::internal::TypeTraits<::test_error::ExampleFooRequest> final {
 public:
  static constexpr const fidl_type_t* kCodingTable =
      &test_error_ExampleFooRequestTable;
};

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

extern "C" const fidl_type_t test_error_Example_foo_ResultTable;

template <>
struct IsFidlType<::test_error::ExampleFooResult> : public std::true_type {};
template <>
struct IsUnion<::test_error::ExampleFooResult> : public std::true_type {};

template <>
struct ::fidl::internal::TypeTraits<::test_error::ExampleFooResult> final {
 public:
  static constexpr const fidl_type_t* kCodingTable =
      &test_error_Example_foo_ResultTable;
};

template <>
struct internal::NaturalCodingTraits<
    ::test_error::ExampleFooResult,
    ::fidl::internal::NaturalCodingConstraintEmpty>
    final : public ::fidl::internal::NaturalUnionCodingTraits<
                ::test_error::ExampleFooResult> {};

}  // namespace fidl
