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


#ifndef FLATBUFFERS_GENERATED_BASIC_FLATBUFFERS_GOLDENS_H_
#define FLATBUFFERS_GENERATED_BASIC_FLATBUFFERS_GOLDENS_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 == 25 &&
              FLATBUFFERS_VERSION_MINOR == 9 &&
              FLATBUFFERS_VERSION_REVISION == 23,
             "Non-compatible flatbuffers version included");

namespace flatbuffers {
namespace goldens {

struct Galaxy;
struct GalaxyBuilder;

struct Universe;
struct UniverseBuilder;

struct Galaxy FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef GalaxyBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_NUM_STARS = 4
  };
  int64_t num_stars() const {
    return GetField<int64_t>(VT_NUM_STARS, 0);
  }
  template <bool B = false>
  bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int64_t>(verifier, VT_NUM_STARS, 8) &&
           verifier.EndTable();
  }
};

struct GalaxyBuilder {
  typedef Galaxy Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_num_stars(int64_t num_stars) {
    fbb_.AddElement<int64_t>(Galaxy::VT_NUM_STARS, num_stars, 0);
  }
  explicit GalaxyBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<Galaxy> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<Galaxy>(end);
    return o;
  }
};

inline ::flatbuffers::Offset<Galaxy> CreateGalaxy(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    int64_t num_stars = 0) {
  GalaxyBuilder builder_(_fbb);
  builder_.add_num_stars(num_stars);
  return builder_.Finish();
}

struct Universe FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef UniverseBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_AGE = 4,
    VT_GALAXIES = 6
  };
  double age() const {
    return GetField<double>(VT_AGE, 0.0);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<flatbuffers::goldens::Galaxy>> *galaxies() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<flatbuffers::goldens::Galaxy>> *>(VT_GALAXIES);
  }
  template <bool B = false>
  bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<double>(verifier, VT_AGE, 8) &&
           VerifyOffset(verifier, VT_GALAXIES) &&
           verifier.VerifyVector(galaxies()) &&
           verifier.VerifyVectorOfTables(galaxies()) &&
           verifier.EndTable();
  }
};

struct UniverseBuilder {
  typedef Universe Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_age(double age) {
    fbb_.AddElement<double>(Universe::VT_AGE, age, 0.0);
  }
  void add_galaxies(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<flatbuffers::goldens::Galaxy>>> galaxies) {
    fbb_.AddOffset(Universe::VT_GALAXIES, galaxies);
  }
  explicit UniverseBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<Universe> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<Universe>(end);
    return o;
  }
};

inline ::flatbuffers::Offset<Universe> CreateUniverse(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    double age = 0.0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<flatbuffers::goldens::Galaxy>>> galaxies = 0) {
  UniverseBuilder builder_(_fbb);
  builder_.add_age(age);
  builder_.add_galaxies(galaxies);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<Universe> CreateUniverseDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    double age = 0.0,
    const std::vector<::flatbuffers::Offset<flatbuffers::goldens::Galaxy>> *galaxies = nullptr) {
  auto galaxies__ = galaxies ? _fbb.CreateVector<::flatbuffers::Offset<flatbuffers::goldens::Galaxy>>(*galaxies) : 0;
  return flatbuffers::goldens::CreateUniverse(
      _fbb,
      age,
      galaxies__);
}

inline const flatbuffers::goldens::Universe *GetUniverse(const void *buf) {
  return ::flatbuffers::GetRoot<flatbuffers::goldens::Universe>(buf);
}

inline const flatbuffers::goldens::Universe *GetSizePrefixedUniverse(const void *buf) {
  return ::flatbuffers::GetSizePrefixedRoot<flatbuffers::goldens::Universe>(buf);
}

template <bool B = false>
inline bool VerifyUniverseBuffer(
    ::flatbuffers::VerifierTemplate<B> &verifier) {
  return verifier.template VerifyBuffer<flatbuffers::goldens::Universe>(nullptr);
}

template <bool B = false>
inline bool VerifySizePrefixedUniverseBuffer(
    ::flatbuffers::VerifierTemplate<B> &verifier) {
  return verifier.template VerifySizePrefixedBuffer<flatbuffers::goldens::Universe>(nullptr);
}

inline void FinishUniverseBuffer(
    ::flatbuffers::FlatBufferBuilder &fbb,
    ::flatbuffers::Offset<flatbuffers::goldens::Universe> root) {
  fbb.Finish(root);
}

inline void FinishSizePrefixedUniverseBuffer(
    ::flatbuffers::FlatBufferBuilder &fbb,
    ::flatbuffers::Offset<flatbuffers::goldens::Universe> root) {
  fbb.FinishSizePrefixed(root);
}

}  // namespace goldens
}  // namespace flatbuffers

#endif  // FLATBUFFERS_GENERATED_BASIC_FLATBUFFERS_GOLDENS_H_
