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

#pragma once

#include "lib/fidl/cpp/internal/header.h"


namespace test {
namespace name {

class OlderSimpleTable;
class NewerSimpleTable;
class SimpleTable;

class OlderSimpleTable  {
 public:
  static const fidl_type_t* FidlType;
  
  const int64_t* x() const {
    return has_x_ ? &x_.value : nullptr;
  }
  bool has_x() const {
    return has_x_;
  }
  
  int64_t* mutable_x() {
    if (!has_x_) {
      has_x_ = true;
      Construct(&x_.value);
    }
    return &x_.value;
  }
  void set_x(int64_t value) {
    if (!has_x_) {
      has_x_ = true;
      Construct(&x_.value, std::move(value));
    } else {
      x_.value = std::move(value);
    }
  }
  void clear_x() {
    if (!has_x_) {
      return;
    }
    has_x_ = false;
    Destruct(&x_.value);
  }

  OlderSimpleTable();
  OlderSimpleTable(OlderSimpleTable&& other);
  ~OlderSimpleTable();
  OlderSimpleTable& operator=(OlderSimpleTable&& other);

  static inline ::std::unique_ptr<OlderSimpleTable> New() { return ::std::make_unique<OlderSimpleTable>(); }

  void Encode(::fidl::Encoder* encoder, size_t offset);
  static void Decode(::fidl::Decoder* decoder, OlderSimpleTable* value, size_t offset);
  zx_status_t Clone(OlderSimpleTable* result) const;

 private:
  template <class T, class... Args>
  void Construct(T* p, Args&&... args) {
    new (p) T(std::forward<Args>(args)...);
  }

  template <class T>
  void Destruct(T* p) {
    p->~T();
  }
  bool has_x_ : 1;
  union ValueUnion_x {
    ValueUnion_x() {}
    ~ValueUnion_x() {}

    int64_t value;
  };
  ValueUnion_x x_;
};

bool operator==(const OlderSimpleTable& lhs, const OlderSimpleTable& rhs);
inline bool operator!=(const OlderSimpleTable& lhs, const OlderSimpleTable& rhs) {
  return !(lhs == rhs);
}

using OlderSimpleTablePtr = ::std::unique_ptr<OlderSimpleTable>;

class NewerSimpleTable  {
 public:
  static const fidl_type_t* FidlType;
  
  const int64_t* x() const {
    return has_x_ ? &x_.value : nullptr;
  }
  bool has_x() const {
    return has_x_;
  }
  
  int64_t* mutable_x() {
    if (!has_x_) {
      has_x_ = true;
      Construct(&x_.value);
    }
    return &x_.value;
  }
  void set_x(int64_t value) {
    if (!has_x_) {
      has_x_ = true;
      Construct(&x_.value, std::move(value));
    } else {
      x_.value = std::move(value);
    }
  }
  void clear_x() {
    if (!has_x_) {
      return;
    }
    has_x_ = false;
    Destruct(&x_.value);
  }
  
  const int64_t* y() const {
    return has_y_ ? &y_.value : nullptr;
  }
  bool has_y() const {
    return has_y_;
  }
  
  int64_t* mutable_y() {
    if (!has_y_) {
      has_y_ = true;
      Construct(&y_.value);
    }
    return &y_.value;
  }
  void set_y(int64_t value) {
    if (!has_y_) {
      has_y_ = true;
      Construct(&y_.value, std::move(value));
    } else {
      y_.value = std::move(value);
    }
  }
  void clear_y() {
    if (!has_y_) {
      return;
    }
    has_y_ = false;
    Destruct(&y_.value);
  }
  
  const int64_t* z() const {
    return has_z_ ? &z_.value : nullptr;
  }
  bool has_z() const {
    return has_z_;
  }
  
  int64_t* mutable_z() {
    if (!has_z_) {
      has_z_ = true;
      Construct(&z_.value);
    }
    return &z_.value;
  }
  void set_z(int64_t value) {
    if (!has_z_) {
      has_z_ = true;
      Construct(&z_.value, std::move(value));
    } else {
      z_.value = std::move(value);
    }
  }
  void clear_z() {
    if (!has_z_) {
      return;
    }
    has_z_ = false;
    Destruct(&z_.value);
  }

  NewerSimpleTable();
  NewerSimpleTable(NewerSimpleTable&& other);
  ~NewerSimpleTable();
  NewerSimpleTable& operator=(NewerSimpleTable&& other);

  static inline ::std::unique_ptr<NewerSimpleTable> New() { return ::std::make_unique<NewerSimpleTable>(); }

  void Encode(::fidl::Encoder* encoder, size_t offset);
  static void Decode(::fidl::Decoder* decoder, NewerSimpleTable* value, size_t offset);
  zx_status_t Clone(NewerSimpleTable* result) const;

 private:
  template <class T, class... Args>
  void Construct(T* p, Args&&... args) {
    new (p) T(std::forward<Args>(args)...);
  }

  template <class T>
  void Destruct(T* p) {
    p->~T();
  }
  bool has_x_ : 1;
  bool has_y_ : 1;
  bool has_z_ : 1;
  union ValueUnion_x {
    ValueUnion_x() {}
    ~ValueUnion_x() {}

    int64_t value;
  };
  ValueUnion_x x_;
  union ValueUnion_y {
    ValueUnion_y() {}
    ~ValueUnion_y() {}

    int64_t value;
  };
  ValueUnion_y y_;
  union ValueUnion_z {
    ValueUnion_z() {}
    ~ValueUnion_z() {}

    int64_t value;
  };
  ValueUnion_z z_;
};

bool operator==(const NewerSimpleTable& lhs, const NewerSimpleTable& rhs);
inline bool operator!=(const NewerSimpleTable& lhs, const NewerSimpleTable& rhs) {
  return !(lhs == rhs);
}

using NewerSimpleTablePtr = ::std::unique_ptr<NewerSimpleTable>;

class SimpleTable  {
 public:
  static const fidl_type_t* FidlType;
  
  const int64_t* x() const {
    return has_x_ ? &x_.value : nullptr;
  }
  bool has_x() const {
    return has_x_;
  }
  
  int64_t* mutable_x() {
    if (!has_x_) {
      has_x_ = true;
      Construct(&x_.value);
    }
    return &x_.value;
  }
  void set_x(int64_t value) {
    if (!has_x_) {
      has_x_ = true;
      Construct(&x_.value, std::move(value));
    } else {
      x_.value = std::move(value);
    }
  }
  void clear_x() {
    if (!has_x_) {
      return;
    }
    has_x_ = false;
    Destruct(&x_.value);
  }
  
  const int64_t* y() const {
    return has_y_ ? &y_.value : nullptr;
  }
  bool has_y() const {
    return has_y_;
  }
  
  int64_t* mutable_y() {
    if (!has_y_) {
      has_y_ = true;
      Construct(&y_.value);
    }
    return &y_.value;
  }
  void set_y(int64_t value) {
    if (!has_y_) {
      has_y_ = true;
      Construct(&y_.value, std::move(value));
    } else {
      y_.value = std::move(value);
    }
  }
  void clear_y() {
    if (!has_y_) {
      return;
    }
    has_y_ = false;
    Destruct(&y_.value);
  }

  SimpleTable();
  SimpleTable(SimpleTable&& other);
  ~SimpleTable();
  SimpleTable& operator=(SimpleTable&& other);

  static inline ::std::unique_ptr<SimpleTable> New() { return ::std::make_unique<SimpleTable>(); }

  void Encode(::fidl::Encoder* encoder, size_t offset);
  static void Decode(::fidl::Decoder* decoder, SimpleTable* value, size_t offset);
  zx_status_t Clone(SimpleTable* result) const;

 private:
  template <class T, class... Args>
  void Construct(T* p, Args&&... args) {
    new (p) T(std::forward<Args>(args)...);
  }

  template <class T>
  void Destruct(T* p) {
    p->~T();
  }
  bool has_x_ : 1;
  bool has_y_ : 1;
  union ValueUnion_x {
    ValueUnion_x() {}
    ~ValueUnion_x() {}

    int64_t value;
  };
  ValueUnion_x x_;
  union ValueUnion_y {
    ValueUnion_y() {}
    ~ValueUnion_y() {}

    int64_t value;
  };
  ValueUnion_y y_;
};

bool operator==(const SimpleTable& lhs, const SimpleTable& rhs);
inline bool operator!=(const SimpleTable& lhs, const SimpleTable& rhs) {
  return !(lhs == rhs);
}

using SimpleTablePtr = ::std::unique_ptr<SimpleTable>;
}  // namespace name
}  // namespace test
namespace fidl {

template <>
struct CodingTraits<::test::name::OlderSimpleTable>
    : public EncodableCodingTraits<::test::name::OlderSimpleTable, 16> {};

inline zx_status_t Clone(const ::test::name::OlderSimpleTable& value,
                         ::test::name::OlderSimpleTable* result) {
  return value.Clone(result);
}
template <>
struct CodingTraits<::test::name::NewerSimpleTable>
    : public EncodableCodingTraits<::test::name::NewerSimpleTable, 16> {};

inline zx_status_t Clone(const ::test::name::NewerSimpleTable& value,
                         ::test::name::NewerSimpleTable* result) {
  return value.Clone(result);
}
template <>
struct CodingTraits<::test::name::SimpleTable>
    : public EncodableCodingTraits<::test::name::SimpleTable, 16> {};

inline zx_status_t Clone(const ::test::name::SimpleTable& value,
                         ::test::name::SimpleTable* result) {
  return value.Clone(result);
}}  // namespace fidl
