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


#ifndef FLATBUFFERS_GENERATED_TENSOR_ORG_APACHE_ARROW_FLATBUF_H_
#define FLATBUFFERS_GENERATED_TENSOR_ORG_APACHE_ARROW_FLATBUF_H_

#include "flatbuffers/flatbuffers.h"

#include "Schema_generated.h"

namespace org {
namespace apache {
namespace arrow {
namespace flatbuf {

struct TensorDim;

struct Tensor;

struct SparseTensorIndexCOO;

struct SparseMatrixIndexCSR;

struct SparseTensor;

enum SparseTensorIndex {
  SparseTensorIndex_NONE = 0,
  SparseTensorIndex_SparseTensorIndexCOO = 1,
  SparseTensorIndex_SparseMatrixIndexCSR = 2,
  SparseTensorIndex_MIN = SparseTensorIndex_NONE,
  SparseTensorIndex_MAX = SparseTensorIndex_SparseMatrixIndexCSR
};

inline const SparseTensorIndex (&EnumValuesSparseTensorIndex())[3] {
  static const SparseTensorIndex values[] = {
    SparseTensorIndex_NONE,
    SparseTensorIndex_SparseTensorIndexCOO,
    SparseTensorIndex_SparseMatrixIndexCSR
  };
  return values;
}

inline const char * const *EnumNamesSparseTensorIndex() {
  static const char * const names[] = {
    "NONE",
    "SparseTensorIndexCOO",
    "SparseMatrixIndexCSR",
    nullptr
  };
  return names;
}

inline const char *EnumNameSparseTensorIndex(SparseTensorIndex e) {
  const size_t index = static_cast<int>(e);
  return EnumNamesSparseTensorIndex()[index];
}

template<typename T> struct SparseTensorIndexTraits {
  static const SparseTensorIndex enum_value = SparseTensorIndex_NONE;
};

template<> struct SparseTensorIndexTraits<SparseTensorIndexCOO> {
  static const SparseTensorIndex enum_value = SparseTensorIndex_SparseTensorIndexCOO;
};

template<> struct SparseTensorIndexTraits<SparseMatrixIndexCSR> {
  static const SparseTensorIndex enum_value = SparseTensorIndex_SparseMatrixIndexCSR;
};

bool VerifySparseTensorIndex(flatbuffers::Verifier &verifier, const void *obj, SparseTensorIndex type);
bool VerifySparseTensorIndexVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);

/// ----------------------------------------------------------------------
/// Data structures for dense tensors
/// Shape data for a single axis in a tensor
struct TensorDim FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_SIZE = 4,
    VT_NAME = 6
  };
  /// Length of dimension
  int64_t size() const {
    return GetField<int64_t>(VT_SIZE, 0);
  }
  /// Name of the dimension, optional
  const flatbuffers::String *name() const {
    return GetPointer<const flatbuffers::String *>(VT_NAME);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int64_t>(verifier, VT_SIZE) &&
           VerifyOffset(verifier, VT_NAME) &&
           verifier.VerifyString(name()) &&
           verifier.EndTable();
  }
};

struct TensorDimBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_size(int64_t size) {
    fbb_.AddElement<int64_t>(TensorDim::VT_SIZE, size, 0);
  }
  void add_name(flatbuffers::Offset<flatbuffers::String> name) {
    fbb_.AddOffset(TensorDim::VT_NAME, name);
  }
  explicit TensorDimBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  TensorDimBuilder &operator=(const TensorDimBuilder &);
  flatbuffers::Offset<TensorDim> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<TensorDim>(end);
    return o;
  }
};

inline flatbuffers::Offset<TensorDim> CreateTensorDim(
    flatbuffers::FlatBufferBuilder &_fbb,
    int64_t size = 0,
    flatbuffers::Offset<flatbuffers::String> name = 0) {
  TensorDimBuilder builder_(_fbb);
  builder_.add_size(size);
  builder_.add_name(name);
  return builder_.Finish();
}

inline flatbuffers::Offset<TensorDim> CreateTensorDimDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    int64_t size = 0,
    const char *name = nullptr) {
  return org::apache::arrow::flatbuf::CreateTensorDim(
      _fbb,
      size,
      name ? _fbb.CreateString(name) : 0);
}

struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_TYPE_TYPE = 4,
    VT_TYPE = 6,
    VT_SHAPE = 8,
    VT_STRIDES = 10,
    VT_DATA = 12
  };
  Type type_type() const {
    return static_cast<Type>(GetField<uint8_t>(VT_TYPE_TYPE, 0));
  }
  /// The type of data contained in a value cell. Currently only fixed-width
  /// value types are supported, no strings or nested types
  const void *type() const {
    return GetPointer<const void *>(VT_TYPE);
  }
  template<typename T> const T *type_as() const;
  const Null *type_as_Null() const {
    return type_type() == Type_Null ? static_cast<const Null *>(type()) : nullptr;
  }
  const Int *type_as_Int() const {
    return type_type() == Type_Int ? static_cast<const Int *>(type()) : nullptr;
  }
  const FloatingPoint *type_as_FloatingPoint() const {
    return type_type() == Type_FloatingPoint ? static_cast<const FloatingPoint *>(type()) : nullptr;
  }
  const Binary *type_as_Binary() const {
    return type_type() == Type_Binary ? static_cast<const Binary *>(type()) : nullptr;
  }
  const Utf8 *type_as_Utf8() const {
    return type_type() == Type_Utf8 ? static_cast<const Utf8 *>(type()) : nullptr;
  }
  const Bool *type_as_Bool() const {
    return type_type() == Type_Bool ? static_cast<const Bool *>(type()) : nullptr;
  }
  const Decimal *type_as_Decimal() const {
    return type_type() == Type_Decimal ? static_cast<const Decimal *>(type()) : nullptr;
  }
  const Date *type_as_Date() const {
    return type_type() == Type_Date ? static_cast<const Date *>(type()) : nullptr;
  }
  const Time *type_as_Time() const {
    return type_type() == Type_Time ? static_cast<const Time *>(type()) : nullptr;
  }
  const Timestamp *type_as_Timestamp() const {
    return type_type() == Type_Timestamp ? static_cast<const Timestamp *>(type()) : nullptr;
  }
  const Interval *type_as_Interval() const {
    return type_type() == Type_Interval ? static_cast<const Interval *>(type()) : nullptr;
  }
  const List *type_as_List() const {
    return type_type() == Type_List ? static_cast<const List *>(type()) : nullptr;
  }
  const Struct_ *type_as_Struct_() const {
    return type_type() == Type_Struct_ ? static_cast<const Struct_ *>(type()) : nullptr;
  }
  const Union *type_as_Union() const {
    return type_type() == Type_Union ? static_cast<const Union *>(type()) : nullptr;
  }
  const FixedSizeBinary *type_as_FixedSizeBinary() const {
    return type_type() == Type_FixedSizeBinary ? static_cast<const FixedSizeBinary *>(type()) : nullptr;
  }
  const FixedSizeList *type_as_FixedSizeList() const {
    return type_type() == Type_FixedSizeList ? static_cast<const FixedSizeList *>(type()) : nullptr;
  }
  const Map *type_as_Map() const {
    return type_type() == Type_Map ? static_cast<const Map *>(type()) : nullptr;
  }
  /// The dimensions of the tensor, optionally named
  const flatbuffers::Vector<flatbuffers::Offset<TensorDim>> *shape() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<TensorDim>> *>(VT_SHAPE);
  }
  /// Non-negative byte offsets to advance one value cell along each dimension
  const flatbuffers::Vector<int64_t> *strides() const {
    return GetPointer<const flatbuffers::Vector<int64_t> *>(VT_STRIDES);
  }
  /// The location and size of the tensor's data
  const Buffer *data() const {
    return GetStruct<const Buffer *>(VT_DATA);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint8_t>(verifier, VT_TYPE_TYPE) &&
           VerifyOffset(verifier, VT_TYPE) &&
           VerifyType(verifier, type(), type_type()) &&
           VerifyOffset(verifier, VT_SHAPE) &&
           verifier.VerifyVector(shape()) &&
           verifier.VerifyVectorOfTables(shape()) &&
           VerifyOffset(verifier, VT_STRIDES) &&
           verifier.VerifyVector(strides()) &&
           VerifyField<Buffer>(verifier, VT_DATA) &&
           verifier.EndTable();
  }
};

template<> inline const Null *Tensor::type_as<Null>() const {
  return type_as_Null();
}

template<> inline const Int *Tensor::type_as<Int>() const {
  return type_as_Int();
}

template<> inline const FloatingPoint *Tensor::type_as<FloatingPoint>() const {
  return type_as_FloatingPoint();
}

template<> inline const Binary *Tensor::type_as<Binary>() const {
  return type_as_Binary();
}

template<> inline const Utf8 *Tensor::type_as<Utf8>() const {
  return type_as_Utf8();
}

template<> inline const Bool *Tensor::type_as<Bool>() const {
  return type_as_Bool();
}

template<> inline const Decimal *Tensor::type_as<Decimal>() const {
  return type_as_Decimal();
}

template<> inline const Date *Tensor::type_as<Date>() const {
  return type_as_Date();
}

template<> inline const Time *Tensor::type_as<Time>() const {
  return type_as_Time();
}

template<> inline const Timestamp *Tensor::type_as<Timestamp>() const {
  return type_as_Timestamp();
}

template<> inline const Interval *Tensor::type_as<Interval>() const {
  return type_as_Interval();
}

template<> inline const List *Tensor::type_as<List>() const {
  return type_as_List();
}

template<> inline const Struct_ *Tensor::type_as<Struct_>() const {
  return type_as_Struct_();
}

template<> inline const Union *Tensor::type_as<Union>() const {
  return type_as_Union();
}

template<> inline const FixedSizeBinary *Tensor::type_as<FixedSizeBinary>() const {
  return type_as_FixedSizeBinary();
}

template<> inline const FixedSizeList *Tensor::type_as<FixedSizeList>() const {
  return type_as_FixedSizeList();
}

template<> inline const Map *Tensor::type_as<Map>() const {
  return type_as_Map();
}

struct TensorBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_type_type(Type type_type) {
    fbb_.AddElement<uint8_t>(Tensor::VT_TYPE_TYPE, static_cast<uint8_t>(type_type), 0);
  }
  void add_type(flatbuffers::Offset<void> type) {
    fbb_.AddOffset(Tensor::VT_TYPE, type);
  }
  void add_shape(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<TensorDim>>> shape) {
    fbb_.AddOffset(Tensor::VT_SHAPE, shape);
  }
  void add_strides(flatbuffers::Offset<flatbuffers::Vector<int64_t>> strides) {
    fbb_.AddOffset(Tensor::VT_STRIDES, strides);
  }
  void add_data(const Buffer *data) {
    fbb_.AddStruct(Tensor::VT_DATA, data);
  }
  explicit TensorBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  TensorBuilder &operator=(const TensorBuilder &);
  flatbuffers::Offset<Tensor> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Tensor>(end);
    return o;
  }
};

inline flatbuffers::Offset<Tensor> CreateTensor(
    flatbuffers::FlatBufferBuilder &_fbb,
    Type type_type = Type_NONE,
    flatbuffers::Offset<void> type = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<TensorDim>>> shape = 0,
    flatbuffers::Offset<flatbuffers::Vector<int64_t>> strides = 0,
    const Buffer *data = 0) {
  TensorBuilder builder_(_fbb);
  builder_.add_data(data);
  builder_.add_strides(strides);
  builder_.add_shape(shape);
  builder_.add_type(type);
  builder_.add_type_type(type_type);
  return builder_.Finish();
}

inline flatbuffers::Offset<Tensor> CreateTensorDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    Type type_type = Type_NONE,
    flatbuffers::Offset<void> type = 0,
    const std::vector<flatbuffers::Offset<TensorDim>> *shape = nullptr,
    const std::vector<int64_t> *strides = nullptr,
    const Buffer *data = 0) {
  return org::apache::arrow::flatbuf::CreateTensor(
      _fbb,
      type_type,
      type,
      shape ? _fbb.CreateVector<flatbuffers::Offset<TensorDim>>(*shape) : 0,
      strides ? _fbb.CreateVector<int64_t>(*strides) : 0,
      data);
}

/// ----------------------------------------------------------------------
/// EXPERIMENTAL: Data structures for sparse tensors
/// Coodinate format of sparse tensor index.
struct SparseTensorIndexCOO FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_INDICESBUFFER = 4
  };
  /// COO's index list are represented as a NxM matrix,
  /// where N is the number of non-zero values,
  /// and M is the number of dimensions of a sparse tensor.
  /// indicesBuffer stores the location and size of this index matrix.
  /// The type of index value is long, so the stride for the index matrix is unnecessary.
  ///
  /// For example, let X be a 2x3x4x5 tensor, and it has the following 6 non-zero values:
  ///
  ///   X[0, 1, 2, 0] := 1
  ///   X[1, 1, 2, 3] := 2
  ///   X[0, 2, 1, 0] := 3
  ///   X[0, 1, 3, 0] := 4
  ///   X[0, 1, 2, 1] := 5
  ///   X[1, 2, 0, 4] := 6
  ///
  /// In COO format, the index matrix of X is the following 4x6 matrix:
  ///
  ///   [[0, 0, 0, 0, 1, 1],
  ///    [1, 1, 1, 2, 1, 2],
  ///    [2, 2, 3, 1, 2, 0],
  ///    [0, 1, 0, 0, 3, 4]]
  ///
  /// Note that the indices are sorted in lexcographical order.
  const Buffer *indicesBuffer() const {
    return GetStruct<const Buffer *>(VT_INDICESBUFFER);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<Buffer>(verifier, VT_INDICESBUFFER) &&
           verifier.EndTable();
  }
};

struct SparseTensorIndexCOOBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_indicesBuffer(const Buffer *indicesBuffer) {
    fbb_.AddStruct(SparseTensorIndexCOO::VT_INDICESBUFFER, indicesBuffer);
  }
  explicit SparseTensorIndexCOOBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  SparseTensorIndexCOOBuilder &operator=(const SparseTensorIndexCOOBuilder &);
  flatbuffers::Offset<SparseTensorIndexCOO> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<SparseTensorIndexCOO>(end);
    return o;
  }
};

inline flatbuffers::Offset<SparseTensorIndexCOO> CreateSparseTensorIndexCOO(
    flatbuffers::FlatBufferBuilder &_fbb,
    const Buffer *indicesBuffer = 0) {
  SparseTensorIndexCOOBuilder builder_(_fbb);
  builder_.add_indicesBuffer(indicesBuffer);
  return builder_.Finish();
}

/// Compressed Sparse Row format, that is matrix-specific.
struct SparseMatrixIndexCSR FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_INDPTRBUFFER = 4,
    VT_INDICESBUFFER = 6
  };
  /// indptrBuffer stores the location and size of indptr array that
  /// represents the range of the rows.
  /// The i-th row spans from indptr[i] to indptr[i+1] in the data.
  /// The length of this array is 1 + (the number of rows), and the type
  /// of index value is long.
  ///
  /// For example, let X be the following 6x4 matrix:
  ///
  ///   X := [[0, 1, 2, 0],
  ///         [0, 0, 3, 0],
  ///         [0, 4, 0, 5],
  ///         [0, 0, 0, 0],
  ///         [6, 0, 7, 8],
  ///         [0, 9, 0, 0]].
  ///
  /// The array of non-zero values in X is:
  ///
  ///   values(X) = [1, 2, 3, 4, 5, 6, 7, 8, 9].
  ///
  /// And the indptr of X is:
  ///
  ///   indptr(X) = [0, 2, 3, 5, 5, 8, 10].
  const Buffer *indptrBuffer() const {
    return GetStruct<const Buffer *>(VT_INDPTRBUFFER);
  }
  /// indicesBuffer stores the location and size of the array that
  /// contains the column indices of the corresponding non-zero values.
  /// The type of index value is long.
  ///
  /// For example, the indices of the above X is:
  ///
  ///   indices(X) = [1, 2, 2, 1, 3, 0, 2, 3, 1].
  const Buffer *indicesBuffer() const {
    return GetStruct<const Buffer *>(VT_INDICESBUFFER);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<Buffer>(verifier, VT_INDPTRBUFFER) &&
           VerifyField<Buffer>(verifier, VT_INDICESBUFFER) &&
           verifier.EndTable();
  }
};

struct SparseMatrixIndexCSRBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_indptrBuffer(const Buffer *indptrBuffer) {
    fbb_.AddStruct(SparseMatrixIndexCSR::VT_INDPTRBUFFER, indptrBuffer);
  }
  void add_indicesBuffer(const Buffer *indicesBuffer) {
    fbb_.AddStruct(SparseMatrixIndexCSR::VT_INDICESBUFFER, indicesBuffer);
  }
  explicit SparseMatrixIndexCSRBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  SparseMatrixIndexCSRBuilder &operator=(const SparseMatrixIndexCSRBuilder &);
  flatbuffers::Offset<SparseMatrixIndexCSR> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<SparseMatrixIndexCSR>(end);
    return o;
  }
};

inline flatbuffers::Offset<SparseMatrixIndexCSR> CreateSparseMatrixIndexCSR(
    flatbuffers::FlatBufferBuilder &_fbb,
    const Buffer *indptrBuffer = 0,
    const Buffer *indicesBuffer = 0) {
  SparseMatrixIndexCSRBuilder builder_(_fbb);
  builder_.add_indicesBuffer(indicesBuffer);
  builder_.add_indptrBuffer(indptrBuffer);
  return builder_.Finish();
}

struct SparseTensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_TYPE_TYPE = 4,
    VT_TYPE = 6,
    VT_SHAPE = 8,
    VT_NON_ZERO_LENGTH = 10,
    VT_SPARSEINDEX_TYPE = 12,
    VT_SPARSEINDEX = 14,
    VT_DATA = 16
  };
  Type type_type() const {
    return static_cast<Type>(GetField<uint8_t>(VT_TYPE_TYPE, 0));
  }
  /// The type of data contained in a value cell.
  /// Currently only fixed-width value types are supported,
  /// no strings or nested types.
  const void *type() const {
    return GetPointer<const void *>(VT_TYPE);
  }
  template<typename T> const T *type_as() const;
  const Null *type_as_Null() const {
    return type_type() == Type_Null ? static_cast<const Null *>(type()) : nullptr;
  }
  const Int *type_as_Int() const {
    return type_type() == Type_Int ? static_cast<const Int *>(type()) : nullptr;
  }
  const FloatingPoint *type_as_FloatingPoint() const {
    return type_type() == Type_FloatingPoint ? static_cast<const FloatingPoint *>(type()) : nullptr;
  }
  const Binary *type_as_Binary() const {
    return type_type() == Type_Binary ? static_cast<const Binary *>(type()) : nullptr;
  }
  const Utf8 *type_as_Utf8() const {
    return type_type() == Type_Utf8 ? static_cast<const Utf8 *>(type()) : nullptr;
  }
  const Bool *type_as_Bool() const {
    return type_type() == Type_Bool ? static_cast<const Bool *>(type()) : nullptr;
  }
  const Decimal *type_as_Decimal() const {
    return type_type() == Type_Decimal ? static_cast<const Decimal *>(type()) : nullptr;
  }
  const Date *type_as_Date() const {
    return type_type() == Type_Date ? static_cast<const Date *>(type()) : nullptr;
  }
  const Time *type_as_Time() const {
    return type_type() == Type_Time ? static_cast<const Time *>(type()) : nullptr;
  }
  const Timestamp *type_as_Timestamp() const {
    return type_type() == Type_Timestamp ? static_cast<const Timestamp *>(type()) : nullptr;
  }
  const Interval *type_as_Interval() const {
    return type_type() == Type_Interval ? static_cast<const Interval *>(type()) : nullptr;
  }
  const List *type_as_List() const {
    return type_type() == Type_List ? static_cast<const List *>(type()) : nullptr;
  }
  const Struct_ *type_as_Struct_() const {
    return type_type() == Type_Struct_ ? static_cast<const Struct_ *>(type()) : nullptr;
  }
  const Union *type_as_Union() const {
    return type_type() == Type_Union ? static_cast<const Union *>(type()) : nullptr;
  }
  const FixedSizeBinary *type_as_FixedSizeBinary() const {
    return type_type() == Type_FixedSizeBinary ? static_cast<const FixedSizeBinary *>(type()) : nullptr;
  }
  const FixedSizeList *type_as_FixedSizeList() const {
    return type_type() == Type_FixedSizeList ? static_cast<const FixedSizeList *>(type()) : nullptr;
  }
  const Map *type_as_Map() const {
    return type_type() == Type_Map ? static_cast<const Map *>(type()) : nullptr;
  }
  /// The dimensions of the tensor, optionally named.
  const flatbuffers::Vector<flatbuffers::Offset<TensorDim>> *shape() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<TensorDim>> *>(VT_SHAPE);
  }
  /// The number of non-zero values in a sparse tensor.
  int64_t non_zero_length() const {
    return GetField<int64_t>(VT_NON_ZERO_LENGTH, 0);
  }
  SparseTensorIndex sparseIndex_type() const {
    return static_cast<SparseTensorIndex>(GetField<uint8_t>(VT_SPARSEINDEX_TYPE, 0));
  }
  /// Sparse tensor index
  const void *sparseIndex() const {
    return GetPointer<const void *>(VT_SPARSEINDEX);
  }
  template<typename T> const T *sparseIndex_as() const;
  const SparseTensorIndexCOO *sparseIndex_as_SparseTensorIndexCOO() const {
    return sparseIndex_type() == SparseTensorIndex_SparseTensorIndexCOO ? static_cast<const SparseTensorIndexCOO *>(sparseIndex()) : nullptr;
  }
  const SparseMatrixIndexCSR *sparseIndex_as_SparseMatrixIndexCSR() const {
    return sparseIndex_type() == SparseTensorIndex_SparseMatrixIndexCSR ? static_cast<const SparseMatrixIndexCSR *>(sparseIndex()) : nullptr;
  }
  /// The location and size of the tensor's data
  const Buffer *data() const {
    return GetStruct<const Buffer *>(VT_DATA);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint8_t>(verifier, VT_TYPE_TYPE) &&
           VerifyOffset(verifier, VT_TYPE) &&
           VerifyType(verifier, type(), type_type()) &&
           VerifyOffset(verifier, VT_SHAPE) &&
           verifier.VerifyVector(shape()) &&
           verifier.VerifyVectorOfTables(shape()) &&
           VerifyField<int64_t>(verifier, VT_NON_ZERO_LENGTH) &&
           VerifyField<uint8_t>(verifier, VT_SPARSEINDEX_TYPE) &&
           VerifyOffset(verifier, VT_SPARSEINDEX) &&
           VerifySparseTensorIndex(verifier, sparseIndex(), sparseIndex_type()) &&
           VerifyField<Buffer>(verifier, VT_DATA) &&
           verifier.EndTable();
  }
};

template<> inline const Null *SparseTensor::type_as<Null>() const {
  return type_as_Null();
}

template<> inline const Int *SparseTensor::type_as<Int>() const {
  return type_as_Int();
}

template<> inline const FloatingPoint *SparseTensor::type_as<FloatingPoint>() const {
  return type_as_FloatingPoint();
}

template<> inline const Binary *SparseTensor::type_as<Binary>() const {
  return type_as_Binary();
}

template<> inline const Utf8 *SparseTensor::type_as<Utf8>() const {
  return type_as_Utf8();
}

template<> inline const Bool *SparseTensor::type_as<Bool>() const {
  return type_as_Bool();
}

template<> inline const Decimal *SparseTensor::type_as<Decimal>() const {
  return type_as_Decimal();
}

template<> inline const Date *SparseTensor::type_as<Date>() const {
  return type_as_Date();
}

template<> inline const Time *SparseTensor::type_as<Time>() const {
  return type_as_Time();
}

template<> inline const Timestamp *SparseTensor::type_as<Timestamp>() const {
  return type_as_Timestamp();
}

template<> inline const Interval *SparseTensor::type_as<Interval>() const {
  return type_as_Interval();
}

template<> inline const List *SparseTensor::type_as<List>() const {
  return type_as_List();
}

template<> inline const Struct_ *SparseTensor::type_as<Struct_>() const {
  return type_as_Struct_();
}

template<> inline const Union *SparseTensor::type_as<Union>() const {
  return type_as_Union();
}

template<> inline const FixedSizeBinary *SparseTensor::type_as<FixedSizeBinary>() const {
  return type_as_FixedSizeBinary();
}

template<> inline const FixedSizeList *SparseTensor::type_as<FixedSizeList>() const {
  return type_as_FixedSizeList();
}

template<> inline const Map *SparseTensor::type_as<Map>() const {
  return type_as_Map();
}

template<> inline const SparseTensorIndexCOO *SparseTensor::sparseIndex_as<SparseTensorIndexCOO>() const {
  return sparseIndex_as_SparseTensorIndexCOO();
}

template<> inline const SparseMatrixIndexCSR *SparseTensor::sparseIndex_as<SparseMatrixIndexCSR>() const {
  return sparseIndex_as_SparseMatrixIndexCSR();
}

struct SparseTensorBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_type_type(Type type_type) {
    fbb_.AddElement<uint8_t>(SparseTensor::VT_TYPE_TYPE, static_cast<uint8_t>(type_type), 0);
  }
  void add_type(flatbuffers::Offset<void> type) {
    fbb_.AddOffset(SparseTensor::VT_TYPE, type);
  }
  void add_shape(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<TensorDim>>> shape) {
    fbb_.AddOffset(SparseTensor::VT_SHAPE, shape);
  }
  void add_non_zero_length(int64_t non_zero_length) {
    fbb_.AddElement<int64_t>(SparseTensor::VT_NON_ZERO_LENGTH, non_zero_length, 0);
  }
  void add_sparseIndex_type(SparseTensorIndex sparseIndex_type) {
    fbb_.AddElement<uint8_t>(SparseTensor::VT_SPARSEINDEX_TYPE, static_cast<uint8_t>(sparseIndex_type), 0);
  }
  void add_sparseIndex(flatbuffers::Offset<void> sparseIndex) {
    fbb_.AddOffset(SparseTensor::VT_SPARSEINDEX, sparseIndex);
  }
  void add_data(const Buffer *data) {
    fbb_.AddStruct(SparseTensor::VT_DATA, data);
  }
  explicit SparseTensorBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  SparseTensorBuilder &operator=(const SparseTensorBuilder &);
  flatbuffers::Offset<SparseTensor> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<SparseTensor>(end);
    return o;
  }
};

inline flatbuffers::Offset<SparseTensor> CreateSparseTensor(
    flatbuffers::FlatBufferBuilder &_fbb,
    Type type_type = Type_NONE,
    flatbuffers::Offset<void> type = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<TensorDim>>> shape = 0,
    int64_t non_zero_length = 0,
    SparseTensorIndex sparseIndex_type = SparseTensorIndex_NONE,
    flatbuffers::Offset<void> sparseIndex = 0,
    const Buffer *data = 0) {
  SparseTensorBuilder builder_(_fbb);
  builder_.add_non_zero_length(non_zero_length);
  builder_.add_data(data);
  builder_.add_sparseIndex(sparseIndex);
  builder_.add_shape(shape);
  builder_.add_type(type);
  builder_.add_sparseIndex_type(sparseIndex_type);
  builder_.add_type_type(type_type);
  return builder_.Finish();
}

inline flatbuffers::Offset<SparseTensor> CreateSparseTensorDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    Type type_type = Type_NONE,
    flatbuffers::Offset<void> type = 0,
    const std::vector<flatbuffers::Offset<TensorDim>> *shape = nullptr,
    int64_t non_zero_length = 0,
    SparseTensorIndex sparseIndex_type = SparseTensorIndex_NONE,
    flatbuffers::Offset<void> sparseIndex = 0,
    const Buffer *data = 0) {
  return org::apache::arrow::flatbuf::CreateSparseTensor(
      _fbb,
      type_type,
      type,
      shape ? _fbb.CreateVector<flatbuffers::Offset<TensorDim>>(*shape) : 0,
      non_zero_length,
      sparseIndex_type,
      sparseIndex,
      data);
}

inline bool VerifySparseTensorIndex(flatbuffers::Verifier &verifier, const void *obj, SparseTensorIndex type) {
  switch (type) {
    case SparseTensorIndex_NONE: {
      return true;
    }
    case SparseTensorIndex_SparseTensorIndexCOO: {
      auto ptr = reinterpret_cast<const SparseTensorIndexCOO *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case SparseTensorIndex_SparseMatrixIndexCSR: {
      auto ptr = reinterpret_cast<const SparseMatrixIndexCSR *>(obj);
      return verifier.VerifyTable(ptr);
    }
    default: return false;
  }
}

inline bool VerifySparseTensorIndexVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
  if (!values || !types) return !values && !types;
  if (values->size() != types->size()) return false;
  for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
    if (!VerifySparseTensorIndex(
        verifier,  values->Get(i), types->GetEnum<SparseTensorIndex>(i))) {
      return false;
    }
  }
  return true;
}

inline const org::apache::arrow::flatbuf::SparseTensor *GetSparseTensor(const void *buf) {
  return flatbuffers::GetRoot<org::apache::arrow::flatbuf::SparseTensor>(buf);
}

inline const org::apache::arrow::flatbuf::SparseTensor *GetSizePrefixedSparseTensor(const void *buf) {
  return flatbuffers::GetSizePrefixedRoot<org::apache::arrow::flatbuf::SparseTensor>(buf);
}

inline bool VerifySparseTensorBuffer(
    flatbuffers::Verifier &verifier) {
  return verifier.VerifyBuffer<org::apache::arrow::flatbuf::SparseTensor>(nullptr);
}

inline bool VerifySizePrefixedSparseTensorBuffer(
    flatbuffers::Verifier &verifier) {
  return verifier.VerifySizePrefixedBuffer<org::apache::arrow::flatbuf::SparseTensor>(nullptr);
}

inline void FinishSparseTensorBuffer(
    flatbuffers::FlatBufferBuilder &fbb,
    flatbuffers::Offset<org::apache::arrow::flatbuf::SparseTensor> root) {
  fbb.Finish(root);
}

inline void FinishSizePrefixedSparseTensorBuffer(
    flatbuffers::FlatBufferBuilder &fbb,
    flatbuffers::Offset<org::apache::arrow::flatbuf::SparseTensor> root) {
  fbb.FinishSizePrefixed(root);
}

}  // namespace flatbuf
}  // namespace arrow
}  // namespace apache
}  // namespace org

#endif  // FLATBUFFERS_GENERATED_TENSOR_ORG_APACHE_ARROW_FLATBUF_H_
