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

#pragma once

#include <fidl/test.driveroneway/cpp/common_types.h>
#include <fidl/test.driveroneway/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_driveroneway {
class Payload;

class OneWaySendRequest;

extern "C" const fidl_type_t test_driveroneway_PayloadTable;

class Payload {
 private:
  struct Storage_;

 public:
  Payload(Storage_ storage) noexcept : storage_(std::move(storage)) {}
  Payload(uint32_t value) noexcept : storage_({.value = std::move(value)}) {}

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

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

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

  uint32_t value() const { return storage_.value; }

  uint32_t& value() { return storage_.value; }

  Payload(::fidl::internal::DefaultConstructPossiblyInvalidObjectTag)
      : Payload(Storage_{
            .value = {},
        }) {}

 private:
  struct Storage_ final {
    uint32_t value = {};
  };

  Storage_ storage_;
  Storage_ CloneStorage_() const;

  friend struct ::fidl::internal::NaturalStructCodingTraits<
      ::test_driveroneway::Payload, 4>;
  friend struct ::fidl::internal::MemberVisitor<::test_driveroneway::Payload>;
  static constexpr auto kMembers = std::make_tuple(
      ::fidl::internal::NaturalStructMember<
          Storage_, uint32_t, fidl::internal::NaturalCodingConstraintEmpty>{
          &Storage_::value, 0});
  static constexpr auto kPadding = std::make_tuple();
};

extern "C" const fidl_type_t test_driveroneway_OneWaySendRequestTable;

class OneWaySendRequest {
 private:
  struct Storage_;

 public:
  OneWaySendRequest(Storage_ storage) noexcept : storage_(std::move(storage)) {}
  OneWaySendRequest(::test_driveroneway::Payload payload) noexcept
      : storage_({.payload = std::move(payload)}) {}

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

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

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

  const ::test_driveroneway::Payload& payload() const {
    return storage_.payload;
  }

  ::test_driveroneway::Payload& payload() { return storage_.payload; }

  OneWaySendRequest(::fidl::internal::DefaultConstructPossiblyInvalidObjectTag)
      : OneWaySendRequest(Storage_{
            .payload =
                ::fidl::internal::DefaultConstructPossiblyInvalidObjectTag{},
        }) {}

 private:
  struct Storage_ final {
    ::test_driveroneway::Payload payload;
  };

  Storage_ storage_;
  Storage_ CloneStorage_() const;

  friend struct ::fidl::internal::NaturalStructCodingTraits<
      ::test_driveroneway::OneWaySendRequest, 4>;
  friend struct ::fidl::internal::MemberVisitor<
      ::test_driveroneway::OneWaySendRequest>;
  static constexpr auto kMembers = std::make_tuple(
      ::fidl::internal::NaturalStructMember<
          Storage_, ::test_driveroneway::Payload,
          fidl::internal::NaturalCodingConstraintEmpty>{&Storage_::payload, 0});
  static constexpr auto kPadding = std::make_tuple();
};

}  // namespace test_driveroneway
namespace fidl {

extern "C" const fidl_type_t test_driveroneway_PayloadTable;

template <>
struct IsFidlType<::test_driveroneway::Payload> : public std::true_type {};

template <>
struct ::fidl::internal::TypeTraits<::test_driveroneway::Payload> final {
 public:
  static constexpr const fidl_type_t* kCodingTable =
      &test_driveroneway_PayloadTable;
};

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

extern "C" const fidl_type_t test_driveroneway_OneWaySendRequestTable;

template <>
struct IsFidlType<::test_driveroneway::OneWaySendRequest>
    : public std::true_type {};

template <>
struct ::fidl::internal::TypeTraits<::test_driveroneway::OneWaySendRequest>
    final {
 public:
  static constexpr const fidl_type_t* kCodingTable =
      &test_driveroneway_OneWaySendRequestTable;
};

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

}  // namespace fidl
