// automatically generated by the FlatBuffers compiler, do not modify


#ifndef FLATBUFFERS_GENERATED_NATIVETYPETEST_GEOMETRY_H_
#define FLATBUFFERS_GENERATED_NATIVETYPETEST_GEOMETRY_H_

#include "flatbuffers/flatbuffers.h"

// Ensure the included flatbuffers.h is the same version as when this file was
// generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 24 &&
              FLATBUFFERS_VERSION_MINOR == 3 &&
              FLATBUFFERS_VERSION_REVISION == 25,
             "Non-compatible flatbuffers version included");

#include "native_type_test_impl.h"

namespace Geometry {

struct Vector3D;

struct Vector3DAlt;

struct ApplicationData;
struct ApplicationDataBuilder;
struct ApplicationDataT;

inline const ::flatbuffers::TypeTable *Vector3DTypeTable();

inline const ::flatbuffers::TypeTable *Vector3DAltTypeTable();

inline const ::flatbuffers::TypeTable *ApplicationDataTypeTable();

FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3D FLATBUFFERS_FINAL_CLASS {
 private:
  float x_;
  float y_;
  float z_;

 public:
  static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
    return Vector3DTypeTable();
  }
  Vector3D()
      : x_(0),
        y_(0),
        z_(0) {
  }
  Vector3D(float _x, float _y, float _z)
      : x_(::flatbuffers::EndianScalar(_x)),
        y_(::flatbuffers::EndianScalar(_y)),
        z_(::flatbuffers::EndianScalar(_z)) {
  }
  float x() const {
    return ::flatbuffers::EndianScalar(x_);
  }
  void mutate_x(float _x) {
    ::flatbuffers::WriteScalar(&x_, _x);
  }
  float y() const {
    return ::flatbuffers::EndianScalar(y_);
  }
  void mutate_y(float _y) {
    ::flatbuffers::WriteScalar(&y_, _y);
  }
  float z() const {
    return ::flatbuffers::EndianScalar(z_);
  }
  void mutate_z(float _z) {
    ::flatbuffers::WriteScalar(&z_, _z);
  }
};
FLATBUFFERS_STRUCT_END(Vector3D, 12);

FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3DAlt FLATBUFFERS_FINAL_CLASS {
 private:
  float a_;
  float b_;
  float c_;

 public:
  static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
    return Vector3DAltTypeTable();
  }
  Vector3DAlt()
      : a_(0),
        b_(0),
        c_(0) {
  }
  Vector3DAlt(float _a, float _b, float _c)
      : a_(::flatbuffers::EndianScalar(_a)),
        b_(::flatbuffers::EndianScalar(_b)),
        c_(::flatbuffers::EndianScalar(_c)) {
  }
  float a() const {
    return ::flatbuffers::EndianScalar(a_);
  }
  void mutate_a(float _a) {
    ::flatbuffers::WriteScalar(&a_, _a);
  }
  float b() const {
    return ::flatbuffers::EndianScalar(b_);
  }
  void mutate_b(float _b) {
    ::flatbuffers::WriteScalar(&b_, _b);
  }
  float c() const {
    return ::flatbuffers::EndianScalar(c_);
  }
  void mutate_c(float _c) {
    ::flatbuffers::WriteScalar(&c_, _c);
  }
};
FLATBUFFERS_STRUCT_END(Vector3DAlt, 12);

struct ApplicationDataT : public ::flatbuffers::NativeTable {
  typedef ApplicationData TableType;
  std::vector<Native::Vector3D> vectors{};
  std::vector<Native::Vector3D> vectors_alt{};
};

struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef ApplicationDataT NativeTableType;
  typedef ApplicationDataBuilder Builder;
  static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
    return ApplicationDataTypeTable();
  }
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_VECTORS = 4,
    VT_VECTORS_ALT = 6
  };
  const ::flatbuffers::Vector<const Geometry::Vector3D *> *vectors() const {
    return GetPointer<const ::flatbuffers::Vector<const Geometry::Vector3D *> *>(VT_VECTORS);
  }
  ::flatbuffers::Vector<const Geometry::Vector3D *> *mutable_vectors() {
    return GetPointer<::flatbuffers::Vector<const Geometry::Vector3D *> *>(VT_VECTORS);
  }
  const ::flatbuffers::Vector<const Geometry::Vector3DAlt *> *vectors_alt() const {
    return GetPointer<const ::flatbuffers::Vector<const Geometry::Vector3DAlt *> *>(VT_VECTORS_ALT);
  }
  ::flatbuffers::Vector<const Geometry::Vector3DAlt *> *mutable_vectors_alt() {
    return GetPointer<::flatbuffers::Vector<const Geometry::Vector3DAlt *> *>(VT_VECTORS_ALT);
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffset(verifier, VT_VECTORS) &&
           verifier.VerifyVector(vectors()) &&
           VerifyOffset(verifier, VT_VECTORS_ALT) &&
           verifier.VerifyVector(vectors_alt()) &&
           verifier.EndTable();
  }
  ApplicationDataT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
  void UnPackTo(ApplicationDataT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
  static ::flatbuffers::Offset<ApplicationData> Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
};

struct ApplicationDataBuilder {
  typedef ApplicationData Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_vectors(::flatbuffers::Offset<::flatbuffers::Vector<const Geometry::Vector3D *>> vectors) {
    fbb_.AddOffset(ApplicationData::VT_VECTORS, vectors);
  }
  void add_vectors_alt(::flatbuffers::Offset<::flatbuffers::Vector<const Geometry::Vector3DAlt *>> vectors_alt) {
    fbb_.AddOffset(ApplicationData::VT_VECTORS_ALT, vectors_alt);
  }
  explicit ApplicationDataBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<ApplicationData> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<ApplicationData>(end);
    return o;
  }
};

inline ::flatbuffers::Offset<ApplicationData> CreateApplicationData(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    ::flatbuffers::Offset<::flatbuffers::Vector<const Geometry::Vector3D *>> vectors = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<const Geometry::Vector3DAlt *>> vectors_alt = 0) {
  ApplicationDataBuilder builder_(_fbb);
  builder_.add_vectors_alt(vectors_alt);
  builder_.add_vectors(vectors);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<ApplicationData> CreateApplicationDataDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    const std::vector<Geometry::Vector3D> *vectors = nullptr,
    const std::vector<Geometry::Vector3DAlt> *vectors_alt = nullptr) {
  auto vectors__ = vectors ? _fbb.CreateVectorOfStructs<Geometry::Vector3D>(*vectors) : 0;
  auto vectors_alt__ = vectors_alt ? _fbb.CreateVectorOfStructs<Geometry::Vector3DAlt>(*vectors_alt) : 0;
  return Geometry::CreateApplicationData(
      _fbb,
      vectors__,
      vectors_alt__);
}

::flatbuffers::Offset<ApplicationData> CreateApplicationData(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);

inline ApplicationDataT *ApplicationData::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
  auto _o = std::unique_ptr<ApplicationDataT>(new ApplicationDataT());
  UnPackTo(_o.get(), _resolver);
  return _o.release();
}

inline void ApplicationData::UnPackTo(ApplicationDataT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
  (void)_o;
  (void)_resolver;
  { auto _e = vectors(); if (_e) { _o->vectors.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vectors[_i] = ::flatbuffers::UnPack(*_e->Get(_i)); } } else { _o->vectors.resize(0); } }
  { auto _e = vectors_alt(); if (_e) { _o->vectors_alt.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vectors_alt[_i] = ::flatbuffers::UnPackVector3DAlt(*_e->Get(_i)); } } else { _o->vectors_alt.resize(0); } }
}

inline ::flatbuffers::Offset<ApplicationData> ApplicationData::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
  return CreateApplicationData(_fbb, _o, _rehasher);
}

inline ::flatbuffers::Offset<ApplicationData> CreateApplicationData(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
  (void)_rehasher;
  (void)_o;
  struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const ApplicationDataT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
  auto _vectors = _o->vectors.size() ? _fbb.CreateVectorOfNativeStructs<Geometry::Vector3D, Native::Vector3D>(_o->vectors) : 0;
  auto _vectors_alt = _o->vectors_alt.size() ? _fbb.CreateVectorOfNativeStructs<Geometry::Vector3DAlt, Native::Vector3D>(_o->vectors_alt, ::flatbuffers::PackVector3DAlt) : 0;
  return Geometry::CreateApplicationData(
      _fbb,
      _vectors,
      _vectors_alt);
}

inline const ::flatbuffers::TypeTable *Vector3DTypeTable() {
  static const ::flatbuffers::TypeCode type_codes[] = {
    { ::flatbuffers::ET_FLOAT, 0, -1 },
    { ::flatbuffers::ET_FLOAT, 0, -1 },
    { ::flatbuffers::ET_FLOAT, 0, -1 }
  };
  static const int64_t values[] = { 0, 4, 8, 12 };
  static const char * const names[] = {
    "x",
    "y",
    "z"
  };
  static const ::flatbuffers::TypeTable tt = {
    ::flatbuffers::ST_STRUCT, 3, type_codes, nullptr, nullptr, values, names
  };
  return &tt;
}

inline const ::flatbuffers::TypeTable *Vector3DAltTypeTable() {
  static const ::flatbuffers::TypeCode type_codes[] = {
    { ::flatbuffers::ET_FLOAT, 0, -1 },
    { ::flatbuffers::ET_FLOAT, 0, -1 },
    { ::flatbuffers::ET_FLOAT, 0, -1 }
  };
  static const int64_t values[] = { 0, 4, 8, 12 };
  static const char * const names[] = {
    "a",
    "b",
    "c"
  };
  static const ::flatbuffers::TypeTable tt = {
    ::flatbuffers::ST_STRUCT, 3, type_codes, nullptr, nullptr, values, names
  };
  return &tt;
}

inline const ::flatbuffers::TypeTable *ApplicationDataTypeTable() {
  static const ::flatbuffers::TypeCode type_codes[] = {
    { ::flatbuffers::ET_SEQUENCE, 1, 0 },
    { ::flatbuffers::ET_SEQUENCE, 1, 1 }
  };
  static const ::flatbuffers::TypeFunction type_refs[] = {
    Geometry::Vector3DTypeTable,
    Geometry::Vector3DAltTypeTable
  };
  static const char * const names[] = {
    "vectors",
    "vectors_alt"
  };
  static const ::flatbuffers::TypeTable tt = {
    ::flatbuffers::ST_TABLE, 2, type_codes, type_refs, nullptr, nullptr, names
  };
  return &tt;
}

inline const Geometry::ApplicationData *GetApplicationData(const void *buf) {
  return ::flatbuffers::GetRoot<Geometry::ApplicationData>(buf);
}

inline const Geometry::ApplicationData *GetSizePrefixedApplicationData(const void *buf) {
  return ::flatbuffers::GetSizePrefixedRoot<Geometry::ApplicationData>(buf);
}

inline ApplicationData *GetMutableApplicationData(void *buf) {
  return ::flatbuffers::GetMutableRoot<ApplicationData>(buf);
}

inline Geometry::ApplicationData *GetMutableSizePrefixedApplicationData(void *buf) {
  return ::flatbuffers::GetMutableSizePrefixedRoot<Geometry::ApplicationData>(buf);
}

inline bool VerifyApplicationDataBuffer(
    ::flatbuffers::Verifier &verifier) {
  return verifier.VerifyBuffer<Geometry::ApplicationData>(nullptr);
}

inline bool VerifySizePrefixedApplicationDataBuffer(
    ::flatbuffers::Verifier &verifier) {
  return verifier.VerifySizePrefixedBuffer<Geometry::ApplicationData>(nullptr);
}

inline void FinishApplicationDataBuffer(
    ::flatbuffers::FlatBufferBuilder &fbb,
    ::flatbuffers::Offset<Geometry::ApplicationData> root) {
  fbb.Finish(root);
}

inline void FinishSizePrefixedApplicationDataBuffer(
    ::flatbuffers::FlatBufferBuilder &fbb,
    ::flatbuffers::Offset<Geometry::ApplicationData> root) {
  fbb.FinishSizePrefixed(root);
}

inline std::unique_ptr<Geometry::ApplicationDataT> UnPackApplicationData(
    const void *buf,
    const ::flatbuffers::resolver_function_t *res = nullptr) {
  return std::unique_ptr<Geometry::ApplicationDataT>(GetApplicationData(buf)->UnPack(res));
}

inline std::unique_ptr<Geometry::ApplicationDataT> UnPackSizePrefixedApplicationData(
    const void *buf,
    const ::flatbuffers::resolver_function_t *res = nullptr) {
  return std::unique_ptr<Geometry::ApplicationDataT>(GetSizePrefixedApplicationData(buf)->UnPack(res));
}

}  // namespace Geometry

#endif  // FLATBUFFERS_GENERATED_NATIVETYPETEST_GEOMETRY_H_
