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


#ifndef FLATBUFFERS_GENERATED_SCHEMA_ORG_APACHE_ARROW_FLATBUF_H_
#define FLATBUFFERS_GENERATED_SCHEMA_ORG_APACHE_ARROW_FLATBUF_H_

#include "flatbuffers/flatbuffers.h"

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

struct Null;

struct Struct_;

struct List;

struct FixedSizeList;

struct Map;

struct Union;

struct Int;

struct FloatingPoint;

struct Utf8;

struct Binary;

struct FixedSizeBinary;

struct Bool;

struct Decimal;

struct Date;

struct Time;

struct Timestamp;

struct Interval;

struct KeyValue;

struct DictionaryEncoding;

struct Field;

struct Buffer;

struct Schema;

enum MetadataVersion {
  /// 0.1.0
  MetadataVersion_V1 = 0  /// 0.2.0
,
  MetadataVersion_V2 = 1  /// 0.3.0 -> 0.7.1
,
  MetadataVersion_V3 = 2  /// >= 0.8.0
,
  MetadataVersion_V4 = 3,
  MetadataVersion_MIN = MetadataVersion_V1,
  MetadataVersion_MAX = MetadataVersion_V4
};

inline const MetadataVersion (&EnumValuesMetadataVersion())[4] {
  static const MetadataVersion values[] = {
    MetadataVersion_V1,
    MetadataVersion_V2,
    MetadataVersion_V3,
    MetadataVersion_V4
  };
  return values;
}

inline const char * const *EnumNamesMetadataVersion() {
  static const char * const names[] = {
    "V1",
    "V2",
    "V3",
    "V4",
    nullptr
  };
  return names;
}

inline const char *EnumNameMetadataVersion(MetadataVersion e) {
  const size_t index = static_cast<int>(e);
  return EnumNamesMetadataVersion()[index];
}

enum UnionMode {
  UnionMode_Sparse = 0,
  UnionMode_Dense = 1,
  UnionMode_MIN = UnionMode_Sparse,
  UnionMode_MAX = UnionMode_Dense
};

inline const UnionMode (&EnumValuesUnionMode())[2] {
  static const UnionMode values[] = {
    UnionMode_Sparse,
    UnionMode_Dense
  };
  return values;
}

inline const char * const *EnumNamesUnionMode() {
  static const char * const names[] = {
    "Sparse",
    "Dense",
    nullptr
  };
  return names;
}

inline const char *EnumNameUnionMode(UnionMode e) {
  const size_t index = static_cast<int>(e);
  return EnumNamesUnionMode()[index];
}

enum Precision {
  Precision_HALF = 0,
  Precision_SINGLE = 1,
  Precision_DOUBLE = 2,
  Precision_MIN = Precision_HALF,
  Precision_MAX = Precision_DOUBLE
};

inline const Precision (&EnumValuesPrecision())[3] {
  static const Precision values[] = {
    Precision_HALF,
    Precision_SINGLE,
    Precision_DOUBLE
  };
  return values;
}

inline const char * const *EnumNamesPrecision() {
  static const char * const names[] = {
    "HALF",
    "SINGLE",
    "DOUBLE",
    nullptr
  };
  return names;
}

inline const char *EnumNamePrecision(Precision e) {
  const size_t index = static_cast<int>(e);
  return EnumNamesPrecision()[index];
}

enum DateUnit {
  DateUnit_DAY = 0,
  DateUnit_MILLISECOND = 1,
  DateUnit_MIN = DateUnit_DAY,
  DateUnit_MAX = DateUnit_MILLISECOND
};

inline const DateUnit (&EnumValuesDateUnit())[2] {
  static const DateUnit values[] = {
    DateUnit_DAY,
    DateUnit_MILLISECOND
  };
  return values;
}

inline const char * const *EnumNamesDateUnit() {
  static const char * const names[] = {
    "DAY",
    "MILLISECOND",
    nullptr
  };
  return names;
}

inline const char *EnumNameDateUnit(DateUnit e) {
  const size_t index = static_cast<int>(e);
  return EnumNamesDateUnit()[index];
}

enum TimeUnit {
  TimeUnit_SECOND = 0,
  TimeUnit_MILLISECOND = 1,
  TimeUnit_MICROSECOND = 2,
  TimeUnit_NANOSECOND = 3,
  TimeUnit_MIN = TimeUnit_SECOND,
  TimeUnit_MAX = TimeUnit_NANOSECOND
};

inline const TimeUnit (&EnumValuesTimeUnit())[4] {
  static const TimeUnit values[] = {
    TimeUnit_SECOND,
    TimeUnit_MILLISECOND,
    TimeUnit_MICROSECOND,
    TimeUnit_NANOSECOND
  };
  return values;
}

inline const char * const *EnumNamesTimeUnit() {
  static const char * const names[] = {
    "SECOND",
    "MILLISECOND",
    "MICROSECOND",
    "NANOSECOND",
    nullptr
  };
  return names;
}

inline const char *EnumNameTimeUnit(TimeUnit e) {
  const size_t index = static_cast<int>(e);
  return EnumNamesTimeUnit()[index];
}

enum IntervalUnit {
  IntervalUnit_YEAR_MONTH = 0,
  IntervalUnit_DAY_TIME = 1,
  IntervalUnit_MIN = IntervalUnit_YEAR_MONTH,
  IntervalUnit_MAX = IntervalUnit_DAY_TIME
};

inline const IntervalUnit (&EnumValuesIntervalUnit())[2] {
  static const IntervalUnit values[] = {
    IntervalUnit_YEAR_MONTH,
    IntervalUnit_DAY_TIME
  };
  return values;
}

inline const char * const *EnumNamesIntervalUnit() {
  static const char * const names[] = {
    "YEAR_MONTH",
    "DAY_TIME",
    nullptr
  };
  return names;
}

inline const char *EnumNameIntervalUnit(IntervalUnit e) {
  const size_t index = static_cast<int>(e);
  return EnumNamesIntervalUnit()[index];
}

/// ----------------------------------------------------------------------
/// Top-level Type value, enabling extensible type-specific metadata. We can
/// add new logical types to Type without breaking backwards compatibility
enum Type {
  Type_NONE = 0,
  Type_Null = 1,
  Type_Int = 2,
  Type_FloatingPoint = 3,
  Type_Binary = 4,
  Type_Utf8 = 5,
  Type_Bool = 6,
  Type_Decimal = 7,
  Type_Date = 8,
  Type_Time = 9,
  Type_Timestamp = 10,
  Type_Interval = 11,
  Type_List = 12,
  Type_Struct_ = 13,
  Type_Union = 14,
  Type_FixedSizeBinary = 15,
  Type_FixedSizeList = 16,
  Type_Map = 17,
  Type_MIN = Type_NONE,
  Type_MAX = Type_Map
};

inline const Type (&EnumValuesType())[18] {
  static const Type values[] = {
    Type_NONE,
    Type_Null,
    Type_Int,
    Type_FloatingPoint,
    Type_Binary,
    Type_Utf8,
    Type_Bool,
    Type_Decimal,
    Type_Date,
    Type_Time,
    Type_Timestamp,
    Type_Interval,
    Type_List,
    Type_Struct_,
    Type_Union,
    Type_FixedSizeBinary,
    Type_FixedSizeList,
    Type_Map
  };
  return values;
}

inline const char * const *EnumNamesType() {
  static const char * const names[] = {
    "NONE",
    "Null",
    "Int",
    "FloatingPoint",
    "Binary",
    "Utf8",
    "Bool",
    "Decimal",
    "Date",
    "Time",
    "Timestamp",
    "Interval",
    "List",
    "Struct_",
    "Union",
    "FixedSizeBinary",
    "FixedSizeList",
    "Map",
    nullptr
  };
  return names;
}

inline const char *EnumNameType(Type e) {
  const size_t index = static_cast<int>(e);
  return EnumNamesType()[index];
}

template<typename T> struct TypeTraits {
  static const Type enum_value = Type_NONE;
};

template<> struct TypeTraits<Null> {
  static const Type enum_value = Type_Null;
};

template<> struct TypeTraits<Int> {
  static const Type enum_value = Type_Int;
};

template<> struct TypeTraits<FloatingPoint> {
  static const Type enum_value = Type_FloatingPoint;
};

template<> struct TypeTraits<Binary> {
  static const Type enum_value = Type_Binary;
};

template<> struct TypeTraits<Utf8> {
  static const Type enum_value = Type_Utf8;
};

template<> struct TypeTraits<Bool> {
  static const Type enum_value = Type_Bool;
};

template<> struct TypeTraits<Decimal> {
  static const Type enum_value = Type_Decimal;
};

template<> struct TypeTraits<Date> {
  static const Type enum_value = Type_Date;
};

template<> struct TypeTraits<Time> {
  static const Type enum_value = Type_Time;
};

template<> struct TypeTraits<Timestamp> {
  static const Type enum_value = Type_Timestamp;
};

template<> struct TypeTraits<Interval> {
  static const Type enum_value = Type_Interval;
};

template<> struct TypeTraits<List> {
  static const Type enum_value = Type_List;
};

template<> struct TypeTraits<Struct_> {
  static const Type enum_value = Type_Struct_;
};

template<> struct TypeTraits<Union> {
  static const Type enum_value = Type_Union;
};

template<> struct TypeTraits<FixedSizeBinary> {
  static const Type enum_value = Type_FixedSizeBinary;
};

template<> struct TypeTraits<FixedSizeList> {
  static const Type enum_value = Type_FixedSizeList;
};

template<> struct TypeTraits<Map> {
  static const Type enum_value = Type_Map;
};

bool VerifyType(flatbuffers::Verifier &verifier, const void *obj, Type type);
bool VerifyTypeVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);

/// ----------------------------------------------------------------------
/// Endianness of the platform producing the data
enum Endianness {
  Endianness_Little = 0,
  Endianness_Big = 1,
  Endianness_MIN = Endianness_Little,
  Endianness_MAX = Endianness_Big
};

inline const Endianness (&EnumValuesEndianness())[2] {
  static const Endianness values[] = {
    Endianness_Little,
    Endianness_Big
  };
  return values;
}

inline const char * const *EnumNamesEndianness() {
  static const char * const names[] = {
    "Little",
    "Big",
    nullptr
  };
  return names;
}

inline const char *EnumNameEndianness(Endianness e) {
  const size_t index = static_cast<int>(e);
  return EnumNamesEndianness()[index];
}

/// ----------------------------------------------------------------------
/// A Buffer represents a single contiguous memory segment
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Buffer FLATBUFFERS_FINAL_CLASS {
 private:
  int64_t offset_;
  int64_t length_;

 public:
  Buffer() {
    memset(this, 0, sizeof(Buffer));
  }
  Buffer(int64_t _offset, int64_t _length)
      : offset_(flatbuffers::EndianScalar(_offset)),
        length_(flatbuffers::EndianScalar(_length)) {
  }
  /// The relative offset into the shared memory page where the bytes for this
  /// buffer starts
  int64_t offset() const {
    return flatbuffers::EndianScalar(offset_);
  }
  /// The absolute length (in bytes) of the memory buffer. The memory is found
  /// from offset (inclusive) to offset + length (non-inclusive).
  int64_t length() const {
    return flatbuffers::EndianScalar(length_);
  }
};
FLATBUFFERS_STRUCT_END(Buffer, 16);

/// These are stored in the flatbuffer in the Type union below
struct Null FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           verifier.EndTable();
  }
};

struct NullBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  explicit NullBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  NullBuilder &operator=(const NullBuilder &);
  flatbuffers::Offset<Null> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Null>(end);
    return o;
  }
};

inline flatbuffers::Offset<Null> CreateNull(
    flatbuffers::FlatBufferBuilder &_fbb) {
  NullBuilder builder_(_fbb);
  return builder_.Finish();
}

/// A Struct_ in the flatbuffer metadata is the same as an Arrow Struct
/// (according to the physical memory layout). We used Struct_ here as
/// Struct is a reserved word in Flatbuffers
struct Struct_ FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           verifier.EndTable();
  }
};

struct Struct_Builder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  explicit Struct_Builder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  Struct_Builder &operator=(const Struct_Builder &);
  flatbuffers::Offset<Struct_> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Struct_>(end);
    return o;
  }
};

inline flatbuffers::Offset<Struct_> CreateStruct_(
    flatbuffers::FlatBufferBuilder &_fbb) {
  Struct_Builder builder_(_fbb);
  return builder_.Finish();
}

struct List FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           verifier.EndTable();
  }
};

struct ListBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  explicit ListBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ListBuilder &operator=(const ListBuilder &);
  flatbuffers::Offset<List> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<List>(end);
    return o;
  }
};

inline flatbuffers::Offset<List> CreateList(
    flatbuffers::FlatBufferBuilder &_fbb) {
  ListBuilder builder_(_fbb);
  return builder_.Finish();
}

struct FixedSizeList FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_LISTSIZE = 4
  };
  /// Number of list items per value
  int32_t listSize() const {
    return GetField<int32_t>(VT_LISTSIZE, 0);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int32_t>(verifier, VT_LISTSIZE) &&
           verifier.EndTable();
  }
};

struct FixedSizeListBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_listSize(int32_t listSize) {
    fbb_.AddElement<int32_t>(FixedSizeList::VT_LISTSIZE, listSize, 0);
  }
  explicit FixedSizeListBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  FixedSizeListBuilder &operator=(const FixedSizeListBuilder &);
  flatbuffers::Offset<FixedSizeList> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<FixedSizeList>(end);
    return o;
  }
};

inline flatbuffers::Offset<FixedSizeList> CreateFixedSizeList(
    flatbuffers::FlatBufferBuilder &_fbb,
    int32_t listSize = 0) {
  FixedSizeListBuilder builder_(_fbb);
  builder_.add_listSize(listSize);
  return builder_.Finish();
}

/// A Map is a logical nested type that is represented as
///
/// List<entry: Struct<key: K, value: V>>
///
/// In this layout, the keys and values are each respectively contiguous. We do
/// not constrain the key and value types, so the application is responsible
/// for ensuring that the keys are hashable and unique. Whether the keys are sorted
/// may be set in the metadata for this field
///
/// In a Field with Map type, the Field has a child Struct field, which then
/// has two children: key type and the second the value type. The names of the
/// child fields may be respectively "entry", "key", and "value", but this is
/// not enforced
///
/// Map
///   - child[0] entry: Struct
///     - child[0] key: K
///     - child[1] value: V
///
/// Neither the "entry" field nor the "key" field may be nullable.
///
/// The metadata is structured so that Arrow systems without special handling
/// for Map can make Map an alias for List. The "layout" attribute for the Map
/// field must have the same contents as a List.
struct Map FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_KEYSSORTED = 4
  };
  /// Set to true if the keys within each value are sorted
  bool keysSorted() const {
    return GetField<uint8_t>(VT_KEYSSORTED, 0) != 0;
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint8_t>(verifier, VT_KEYSSORTED) &&
           verifier.EndTable();
  }
};

struct MapBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_keysSorted(bool keysSorted) {
    fbb_.AddElement<uint8_t>(Map::VT_KEYSSORTED, static_cast<uint8_t>(keysSorted), 0);
  }
  explicit MapBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  MapBuilder &operator=(const MapBuilder &);
  flatbuffers::Offset<Map> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Map>(end);
    return o;
  }
};

inline flatbuffers::Offset<Map> CreateMap(
    flatbuffers::FlatBufferBuilder &_fbb,
    bool keysSorted = false) {
  MapBuilder builder_(_fbb);
  builder_.add_keysSorted(keysSorted);
  return builder_.Finish();
}

/// A union is a complex type with children in Field
/// By default ids in the type vector refer to the offsets in the children
/// optionally typeIds provides an indirection between the child offset and the type id
/// for each child typeIds[offset] is the id used in the type vector
struct Union FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_MODE = 4,
    VT_TYPEIDS = 6
  };
  UnionMode mode() const {
    return static_cast<UnionMode>(GetField<int16_t>(VT_MODE, 0));
  }
  const flatbuffers::Vector<int32_t> *typeIds() const {
    return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_TYPEIDS);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int16_t>(verifier, VT_MODE) &&
           VerifyOffset(verifier, VT_TYPEIDS) &&
           verifier.VerifyVector(typeIds()) &&
           verifier.EndTable();
  }
};

struct UnionBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_mode(UnionMode mode) {
    fbb_.AddElement<int16_t>(Union::VT_MODE, static_cast<int16_t>(mode), 0);
  }
  void add_typeIds(flatbuffers::Offset<flatbuffers::Vector<int32_t>> typeIds) {
    fbb_.AddOffset(Union::VT_TYPEIDS, typeIds);
  }
  explicit UnionBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  UnionBuilder &operator=(const UnionBuilder &);
  flatbuffers::Offset<Union> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Union>(end);
    return o;
  }
};

inline flatbuffers::Offset<Union> CreateUnion(
    flatbuffers::FlatBufferBuilder &_fbb,
    UnionMode mode = UnionMode_Sparse,
    flatbuffers::Offset<flatbuffers::Vector<int32_t>> typeIds = 0) {
  UnionBuilder builder_(_fbb);
  builder_.add_typeIds(typeIds);
  builder_.add_mode(mode);
  return builder_.Finish();
}

inline flatbuffers::Offset<Union> CreateUnionDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    UnionMode mode = UnionMode_Sparse,
    const std::vector<int32_t> *typeIds = nullptr) {
  return org::apache::arrow::flatbuf::CreateUnion(
      _fbb,
      mode,
      typeIds ? _fbb.CreateVector<int32_t>(*typeIds) : 0);
}

struct Int FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_BITWIDTH = 4,
    VT_IS_SIGNED = 6
  };
  int32_t bitWidth() const {
    return GetField<int32_t>(VT_BITWIDTH, 0);
  }
  bool is_signed() const {
    return GetField<uint8_t>(VT_IS_SIGNED, 0) != 0;
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int32_t>(verifier, VT_BITWIDTH) &&
           VerifyField<uint8_t>(verifier, VT_IS_SIGNED) &&
           verifier.EndTable();
  }
};

struct IntBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_bitWidth(int32_t bitWidth) {
    fbb_.AddElement<int32_t>(Int::VT_BITWIDTH, bitWidth, 0);
  }
  void add_is_signed(bool is_signed) {
    fbb_.AddElement<uint8_t>(Int::VT_IS_SIGNED, static_cast<uint8_t>(is_signed), 0);
  }
  explicit IntBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  IntBuilder &operator=(const IntBuilder &);
  flatbuffers::Offset<Int> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Int>(end);
    return o;
  }
};

inline flatbuffers::Offset<Int> CreateInt(
    flatbuffers::FlatBufferBuilder &_fbb,
    int32_t bitWidth = 0,
    bool is_signed = false) {
  IntBuilder builder_(_fbb);
  builder_.add_bitWidth(bitWidth);
  builder_.add_is_signed(is_signed);
  return builder_.Finish();
}

struct FloatingPoint FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_PRECISION = 4
  };
  Precision precision() const {
    return static_cast<Precision>(GetField<int16_t>(VT_PRECISION, 0));
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int16_t>(verifier, VT_PRECISION) &&
           verifier.EndTable();
  }
};

struct FloatingPointBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_precision(Precision precision) {
    fbb_.AddElement<int16_t>(FloatingPoint::VT_PRECISION, static_cast<int16_t>(precision), 0);
  }
  explicit FloatingPointBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  FloatingPointBuilder &operator=(const FloatingPointBuilder &);
  flatbuffers::Offset<FloatingPoint> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<FloatingPoint>(end);
    return o;
  }
};

inline flatbuffers::Offset<FloatingPoint> CreateFloatingPoint(
    flatbuffers::FlatBufferBuilder &_fbb,
    Precision precision = Precision_HALF) {
  FloatingPointBuilder builder_(_fbb);
  builder_.add_precision(precision);
  return builder_.Finish();
}

/// Unicode with UTF-8 encoding
struct Utf8 FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           verifier.EndTable();
  }
};

struct Utf8Builder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  explicit Utf8Builder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  Utf8Builder &operator=(const Utf8Builder &);
  flatbuffers::Offset<Utf8> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Utf8>(end);
    return o;
  }
};

inline flatbuffers::Offset<Utf8> CreateUtf8(
    flatbuffers::FlatBufferBuilder &_fbb) {
  Utf8Builder builder_(_fbb);
  return builder_.Finish();
}

struct Binary FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           verifier.EndTable();
  }
};

struct BinaryBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  explicit BinaryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  BinaryBuilder &operator=(const BinaryBuilder &);
  flatbuffers::Offset<Binary> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Binary>(end);
    return o;
  }
};

inline flatbuffers::Offset<Binary> CreateBinary(
    flatbuffers::FlatBufferBuilder &_fbb) {
  BinaryBuilder builder_(_fbb);
  return builder_.Finish();
}

struct FixedSizeBinary FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_BYTEWIDTH = 4
  };
  /// Number of bytes per value
  int32_t byteWidth() const {
    return GetField<int32_t>(VT_BYTEWIDTH, 0);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int32_t>(verifier, VT_BYTEWIDTH) &&
           verifier.EndTable();
  }
};

struct FixedSizeBinaryBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_byteWidth(int32_t byteWidth) {
    fbb_.AddElement<int32_t>(FixedSizeBinary::VT_BYTEWIDTH, byteWidth, 0);
  }
  explicit FixedSizeBinaryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  FixedSizeBinaryBuilder &operator=(const FixedSizeBinaryBuilder &);
  flatbuffers::Offset<FixedSizeBinary> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<FixedSizeBinary>(end);
    return o;
  }
};

inline flatbuffers::Offset<FixedSizeBinary> CreateFixedSizeBinary(
    flatbuffers::FlatBufferBuilder &_fbb,
    int32_t byteWidth = 0) {
  FixedSizeBinaryBuilder builder_(_fbb);
  builder_.add_byteWidth(byteWidth);
  return builder_.Finish();
}

struct Bool FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           verifier.EndTable();
  }
};

struct BoolBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  explicit BoolBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  BoolBuilder &operator=(const BoolBuilder &);
  flatbuffers::Offset<Bool> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Bool>(end);
    return o;
  }
};

inline flatbuffers::Offset<Bool> CreateBool(
    flatbuffers::FlatBufferBuilder &_fbb) {
  BoolBuilder builder_(_fbb);
  return builder_.Finish();
}

struct Decimal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_PRECISION = 4,
    VT_SCALE = 6
  };
  /// Total number of decimal digits
  int32_t precision() const {
    return GetField<int32_t>(VT_PRECISION, 0);
  }
  /// Number of digits after the decimal point "."
  int32_t scale() const {
    return GetField<int32_t>(VT_SCALE, 0);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int32_t>(verifier, VT_PRECISION) &&
           VerifyField<int32_t>(verifier, VT_SCALE) &&
           verifier.EndTable();
  }
};

struct DecimalBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_precision(int32_t precision) {
    fbb_.AddElement<int32_t>(Decimal::VT_PRECISION, precision, 0);
  }
  void add_scale(int32_t scale) {
    fbb_.AddElement<int32_t>(Decimal::VT_SCALE, scale, 0);
  }
  explicit DecimalBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  DecimalBuilder &operator=(const DecimalBuilder &);
  flatbuffers::Offset<Decimal> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Decimal>(end);
    return o;
  }
};

inline flatbuffers::Offset<Decimal> CreateDecimal(
    flatbuffers::FlatBufferBuilder &_fbb,
    int32_t precision = 0,
    int32_t scale = 0) {
  DecimalBuilder builder_(_fbb);
  builder_.add_scale(scale);
  builder_.add_precision(precision);
  return builder_.Finish();
}

/// Date is either a 32-bit or 64-bit type representing elapsed time since UNIX
/// epoch (1970-01-01), stored in either of two units:
///
/// * Milliseconds (64 bits) indicating UNIX time elapsed since the epoch (no
///   leap seconds), where the values are evenly divisible by 86400000
/// * Days (32 bits) since the UNIX epoch
struct Date FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_UNIT = 4
  };
  DateUnit unit() const {
    return static_cast<DateUnit>(GetField<int16_t>(VT_UNIT, 1));
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int16_t>(verifier, VT_UNIT) &&
           verifier.EndTable();
  }
};

struct DateBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_unit(DateUnit unit) {
    fbb_.AddElement<int16_t>(Date::VT_UNIT, static_cast<int16_t>(unit), 1);
  }
  explicit DateBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  DateBuilder &operator=(const DateBuilder &);
  flatbuffers::Offset<Date> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Date>(end);
    return o;
  }
};

inline flatbuffers::Offset<Date> CreateDate(
    flatbuffers::FlatBufferBuilder &_fbb,
    DateUnit unit = DateUnit_MILLISECOND) {
  DateBuilder builder_(_fbb);
  builder_.add_unit(unit);
  return builder_.Finish();
}

/// Time type. The physical storage type depends on the unit
/// - SECOND and MILLISECOND: 32 bits
/// - MICROSECOND and NANOSECOND: 64 bits
struct Time FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_UNIT = 4,
    VT_BITWIDTH = 6
  };
  TimeUnit unit() const {
    return static_cast<TimeUnit>(GetField<int16_t>(VT_UNIT, 1));
  }
  int32_t bitWidth() const {
    return GetField<int32_t>(VT_BITWIDTH, 32);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int16_t>(verifier, VT_UNIT) &&
           VerifyField<int32_t>(verifier, VT_BITWIDTH) &&
           verifier.EndTable();
  }
};

struct TimeBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_unit(TimeUnit unit) {
    fbb_.AddElement<int16_t>(Time::VT_UNIT, static_cast<int16_t>(unit), 1);
  }
  void add_bitWidth(int32_t bitWidth) {
    fbb_.AddElement<int32_t>(Time::VT_BITWIDTH, bitWidth, 32);
  }
  explicit TimeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  TimeBuilder &operator=(const TimeBuilder &);
  flatbuffers::Offset<Time> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Time>(end);
    return o;
  }
};

inline flatbuffers::Offset<Time> CreateTime(
    flatbuffers::FlatBufferBuilder &_fbb,
    TimeUnit unit = TimeUnit_MILLISECOND,
    int32_t bitWidth = 32) {
  TimeBuilder builder_(_fbb);
  builder_.add_bitWidth(bitWidth);
  builder_.add_unit(unit);
  return builder_.Finish();
}

/// Time elapsed from the Unix epoch, 00:00:00.000 on 1 January 1970, excluding
/// leap seconds, as a 64-bit integer. Note that UNIX time does not include
/// leap seconds.
///
/// The Timestamp metadata supports both "time zone naive" and "time zone
/// aware" timestamps. Read about the timezone attribute for more detail
struct Timestamp FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_UNIT = 4,
    VT_TIMEZONE = 6
  };
  TimeUnit unit() const {
    return static_cast<TimeUnit>(GetField<int16_t>(VT_UNIT, 0));
  }
  /// The time zone is a string indicating the name of a time zone, one of:
  ///
  /// * As used in the Olson time zone database (the "tz database" or
  ///   "tzdata"), such as "America/New_York"
  /// * An absolute time zone offset of the form +XX:XX or -XX:XX, such as +07:30
  ///
  /// Whether a timezone string is present indicates different semantics about
  /// the data:
  ///
  /// * If the time zone is null or equal to an empty string, the data is "time
  ///   zone naive" and shall be displayed *as is* to the user, not localized
  ///   to the locale of the user. This data can be though of as UTC but
  ///   without having "UTC" as the time zone, it is not considered to be
  ///   localized to any time zone
  ///
  /// * If the time zone is set to a valid value, values can be displayed as
  ///   "localized" to that time zone, even though the underlying 64-bit
  ///   integers are identical to the same data stored in UTC. Converting
  ///   between time zones is a metadata-only operation and does not change the
  ///   underlying values
  const flatbuffers::String *timezone() const {
    return GetPointer<const flatbuffers::String *>(VT_TIMEZONE);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int16_t>(verifier, VT_UNIT) &&
           VerifyOffset(verifier, VT_TIMEZONE) &&
           verifier.VerifyString(timezone()) &&
           verifier.EndTable();
  }
};

struct TimestampBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_unit(TimeUnit unit) {
    fbb_.AddElement<int16_t>(Timestamp::VT_UNIT, static_cast<int16_t>(unit), 0);
  }
  void add_timezone(flatbuffers::Offset<flatbuffers::String> timezone) {
    fbb_.AddOffset(Timestamp::VT_TIMEZONE, timezone);
  }
  explicit TimestampBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  TimestampBuilder &operator=(const TimestampBuilder &);
  flatbuffers::Offset<Timestamp> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Timestamp>(end);
    return o;
  }
};

inline flatbuffers::Offset<Timestamp> CreateTimestamp(
    flatbuffers::FlatBufferBuilder &_fbb,
    TimeUnit unit = TimeUnit_SECOND,
    flatbuffers::Offset<flatbuffers::String> timezone = 0) {
  TimestampBuilder builder_(_fbb);
  builder_.add_timezone(timezone);
  builder_.add_unit(unit);
  return builder_.Finish();
}

inline flatbuffers::Offset<Timestamp> CreateTimestampDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    TimeUnit unit = TimeUnit_SECOND,
    const char *timezone = nullptr) {
  return org::apache::arrow::flatbuf::CreateTimestamp(
      _fbb,
      unit,
      timezone ? _fbb.CreateString(timezone) : 0);
}

struct Interval FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_UNIT = 4
  };
  IntervalUnit unit() const {
    return static_cast<IntervalUnit>(GetField<int16_t>(VT_UNIT, 0));
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int16_t>(verifier, VT_UNIT) &&
           verifier.EndTable();
  }
};

struct IntervalBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_unit(IntervalUnit unit) {
    fbb_.AddElement<int16_t>(Interval::VT_UNIT, static_cast<int16_t>(unit), 0);
  }
  explicit IntervalBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  IntervalBuilder &operator=(const IntervalBuilder &);
  flatbuffers::Offset<Interval> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Interval>(end);
    return o;
  }
};

inline flatbuffers::Offset<Interval> CreateInterval(
    flatbuffers::FlatBufferBuilder &_fbb,
    IntervalUnit unit = IntervalUnit_YEAR_MONTH) {
  IntervalBuilder builder_(_fbb);
  builder_.add_unit(unit);
  return builder_.Finish();
}

/// ----------------------------------------------------------------------
/// user defined key value pairs to add custom metadata to arrow
/// key namespacing is the responsibility of the user
struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_KEY = 4,
    VT_VALUE = 6
  };
  const flatbuffers::String *key() const {
    return GetPointer<const flatbuffers::String *>(VT_KEY);
  }
  const flatbuffers::String *value() const {
    return GetPointer<const flatbuffers::String *>(VT_VALUE);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffset(verifier, VT_KEY) &&
           verifier.VerifyString(key()) &&
           VerifyOffset(verifier, VT_VALUE) &&
           verifier.VerifyString(value()) &&
           verifier.EndTable();
  }
};

struct KeyValueBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_key(flatbuffers::Offset<flatbuffers::String> key) {
    fbb_.AddOffset(KeyValue::VT_KEY, key);
  }
  void add_value(flatbuffers::Offset<flatbuffers::String> value) {
    fbb_.AddOffset(KeyValue::VT_VALUE, value);
  }
  explicit KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  KeyValueBuilder &operator=(const KeyValueBuilder &);
  flatbuffers::Offset<KeyValue> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<KeyValue>(end);
    return o;
  }
};

inline flatbuffers::Offset<KeyValue> CreateKeyValue(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<flatbuffers::String> key = 0,
    flatbuffers::Offset<flatbuffers::String> value = 0) {
  KeyValueBuilder builder_(_fbb);
  builder_.add_value(value);
  builder_.add_key(key);
  return builder_.Finish();
}

inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    const char *key = nullptr,
    const char *value = nullptr) {
  return org::apache::arrow::flatbuf::CreateKeyValue(
      _fbb,
      key ? _fbb.CreateString(key) : 0,
      value ? _fbb.CreateString(value) : 0);
}

/// ----------------------------------------------------------------------
/// Dictionary encoding metadata
struct DictionaryEncoding FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_ID = 4,
    VT_INDEXTYPE = 6,
    VT_ISORDERED = 8
  };
  /// The known dictionary id in the application where this data is used. In
  /// the file or streaming formats, the dictionary ids are found in the
  /// DictionaryBatch messages
  int64_t id() const {
    return GetField<int64_t>(VT_ID, 0);
  }
  /// The dictionary indices are constrained to be positive integers. If this
  /// field is null, the indices must be signed int32
  const Int *indexType() const {
    return GetPointer<const Int *>(VT_INDEXTYPE);
  }
  /// By default, dictionaries are not ordered, or the order does not have
  /// semantic meaning. In some statistical, applications, dictionary-encoding
  /// is used to represent ordered categorical data, and we provide a way to
  /// preserve that metadata here
  bool isOrdered() const {
    return GetField<uint8_t>(VT_ISORDERED, 0) != 0;
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int64_t>(verifier, VT_ID) &&
           VerifyOffset(verifier, VT_INDEXTYPE) &&
           verifier.VerifyTable(indexType()) &&
           VerifyField<uint8_t>(verifier, VT_ISORDERED) &&
           verifier.EndTable();
  }
};

struct DictionaryEncodingBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_id(int64_t id) {
    fbb_.AddElement<int64_t>(DictionaryEncoding::VT_ID, id, 0);
  }
  void add_indexType(flatbuffers::Offset<Int> indexType) {
    fbb_.AddOffset(DictionaryEncoding::VT_INDEXTYPE, indexType);
  }
  void add_isOrdered(bool isOrdered) {
    fbb_.AddElement<uint8_t>(DictionaryEncoding::VT_ISORDERED, static_cast<uint8_t>(isOrdered), 0);
  }
  explicit DictionaryEncodingBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  DictionaryEncodingBuilder &operator=(const DictionaryEncodingBuilder &);
  flatbuffers::Offset<DictionaryEncoding> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<DictionaryEncoding>(end);
    return o;
  }
};

inline flatbuffers::Offset<DictionaryEncoding> CreateDictionaryEncoding(
    flatbuffers::FlatBufferBuilder &_fbb,
    int64_t id = 0,
    flatbuffers::Offset<Int> indexType = 0,
    bool isOrdered = false) {
  DictionaryEncodingBuilder builder_(_fbb);
  builder_.add_id(id);
  builder_.add_indexType(indexType);
  builder_.add_isOrdered(isOrdered);
  return builder_.Finish();
}

/// ----------------------------------------------------------------------
/// A field represents a named column in a record / row batch or child of a
/// nested type.
///
/// - children is only for nested Arrow arrays
/// - For primitive types, children will have length 0
/// - nullable should default to true in general
struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_NAME = 4,
    VT_NULLABLE = 6,
    VT_TYPE_TYPE = 8,
    VT_TYPE = 10,
    VT_DICTIONARY = 12,
    VT_CHILDREN = 14,
    VT_CUSTOM_METADATA = 16
  };
  const flatbuffers::String *name() const {
    return GetPointer<const flatbuffers::String *>(VT_NAME);
  }
  bool nullable() const {
    return GetField<uint8_t>(VT_NULLABLE, 0) != 0;
  }
  Type type_type() const {
    return static_cast<Type>(GetField<uint8_t>(VT_TYPE_TYPE, 0));
  }
  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;
  }
  const DictionaryEncoding *dictionary() const {
    return GetPointer<const DictionaryEncoding *>(VT_DICTIONARY);
  }
  const flatbuffers::Vector<flatbuffers::Offset<Field>> *children() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Field>> *>(VT_CHILDREN);
  }
  const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *custom_metadata() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_CUSTOM_METADATA);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffset(verifier, VT_NAME) &&
           verifier.VerifyString(name()) &&
           VerifyField<uint8_t>(verifier, VT_NULLABLE) &&
           VerifyField<uint8_t>(verifier, VT_TYPE_TYPE) &&
           VerifyOffset(verifier, VT_TYPE) &&
           VerifyType(verifier, type(), type_type()) &&
           VerifyOffset(verifier, VT_DICTIONARY) &&
           verifier.VerifyTable(dictionary()) &&
           VerifyOffset(verifier, VT_CHILDREN) &&
           verifier.VerifyVector(children()) &&
           verifier.VerifyVectorOfTables(children()) &&
           VerifyOffset(verifier, VT_CUSTOM_METADATA) &&
           verifier.VerifyVector(custom_metadata()) &&
           verifier.VerifyVectorOfTables(custom_metadata()) &&
           verifier.EndTable();
  }
};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

struct FieldBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_name(flatbuffers::Offset<flatbuffers::String> name) {
    fbb_.AddOffset(Field::VT_NAME, name);
  }
  void add_nullable(bool nullable) {
    fbb_.AddElement<uint8_t>(Field::VT_NULLABLE, static_cast<uint8_t>(nullable), 0);
  }
  void add_type_type(Type type_type) {
    fbb_.AddElement<uint8_t>(Field::VT_TYPE_TYPE, static_cast<uint8_t>(type_type), 0);
  }
  void add_type(flatbuffers::Offset<void> type) {
    fbb_.AddOffset(Field::VT_TYPE, type);
  }
  void add_dictionary(flatbuffers::Offset<DictionaryEncoding> dictionary) {
    fbb_.AddOffset(Field::VT_DICTIONARY, dictionary);
  }
  void add_children(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> children) {
    fbb_.AddOffset(Field::VT_CHILDREN, children);
  }
  void add_custom_metadata(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> custom_metadata) {
    fbb_.AddOffset(Field::VT_CUSTOM_METADATA, custom_metadata);
  }
  explicit FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  FieldBuilder &operator=(const FieldBuilder &);
  flatbuffers::Offset<Field> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Field>(end);
    return o;
  }
};

inline flatbuffers::Offset<Field> CreateField(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<flatbuffers::String> name = 0,
    bool nullable = false,
    Type type_type = Type_NONE,
    flatbuffers::Offset<void> type = 0,
    flatbuffers::Offset<DictionaryEncoding> dictionary = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> children = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> custom_metadata = 0) {
  FieldBuilder builder_(_fbb);
  builder_.add_custom_metadata(custom_metadata);
  builder_.add_children(children);
  builder_.add_dictionary(dictionary);
  builder_.add_type(type);
  builder_.add_name(name);
  builder_.add_type_type(type_type);
  builder_.add_nullable(nullable);
  return builder_.Finish();
}

inline flatbuffers::Offset<Field> CreateFieldDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    const char *name = nullptr,
    bool nullable = false,
    Type type_type = Type_NONE,
    flatbuffers::Offset<void> type = 0,
    flatbuffers::Offset<DictionaryEncoding> dictionary = 0,
    const std::vector<flatbuffers::Offset<Field>> *children = nullptr,
    const std::vector<flatbuffers::Offset<KeyValue>> *custom_metadata = nullptr) {
  return org::apache::arrow::flatbuf::CreateField(
      _fbb,
      name ? _fbb.CreateString(name) : 0,
      nullable,
      type_type,
      type,
      dictionary,
      children ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*children) : 0,
      custom_metadata ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*custom_metadata) : 0);
}

/// ----------------------------------------------------------------------
/// A Schema describes the columns in a row batch
struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  enum {
    VT_ENDIANNESS = 4,
    VT_FIELDS = 6,
    VT_CUSTOM_METADATA = 8
  };
  /// endianness of the buffer
  /// it is Little Endian by default
  /// if endianness doesn't match the underlying system then the vectors need to be converted
  Endianness endianness() const {
    return static_cast<Endianness>(GetField<int16_t>(VT_ENDIANNESS, 0));
  }
  const flatbuffers::Vector<flatbuffers::Offset<Field>> *fields() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Field>> *>(VT_FIELDS);
  }
  const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *custom_metadata() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_CUSTOM_METADATA);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int16_t>(verifier, VT_ENDIANNESS) &&
           VerifyOffset(verifier, VT_FIELDS) &&
           verifier.VerifyVector(fields()) &&
           verifier.VerifyVectorOfTables(fields()) &&
           VerifyOffset(verifier, VT_CUSTOM_METADATA) &&
           verifier.VerifyVector(custom_metadata()) &&
           verifier.VerifyVectorOfTables(custom_metadata()) &&
           verifier.EndTable();
  }
};

struct SchemaBuilder {
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_endianness(Endianness endianness) {
    fbb_.AddElement<int16_t>(Schema::VT_ENDIANNESS, static_cast<int16_t>(endianness), 0);
  }
  void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields) {
    fbb_.AddOffset(Schema::VT_FIELDS, fields);
  }
  void add_custom_metadata(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> custom_metadata) {
    fbb_.AddOffset(Schema::VT_CUSTOM_METADATA, custom_metadata);
  }
  explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  SchemaBuilder &operator=(const SchemaBuilder &);
  flatbuffers::Offset<Schema> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Schema>(end);
    return o;
  }
};

inline flatbuffers::Offset<Schema> CreateSchema(
    flatbuffers::FlatBufferBuilder &_fbb,
    Endianness endianness = Endianness_Little,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> custom_metadata = 0) {
  SchemaBuilder builder_(_fbb);
  builder_.add_custom_metadata(custom_metadata);
  builder_.add_fields(fields);
  builder_.add_endianness(endianness);
  return builder_.Finish();
}

inline flatbuffers::Offset<Schema> CreateSchemaDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    Endianness endianness = Endianness_Little,
    const std::vector<flatbuffers::Offset<Field>> *fields = nullptr,
    const std::vector<flatbuffers::Offset<KeyValue>> *custom_metadata = nullptr) {
  return org::apache::arrow::flatbuf::CreateSchema(
      _fbb,
      endianness,
      fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0,
      custom_metadata ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*custom_metadata) : 0);
}

inline bool VerifyType(flatbuffers::Verifier &verifier, const void *obj, Type type) {
  switch (type) {
    case Type_NONE: {
      return true;
    }
    case Type_Null: {
      auto ptr = reinterpret_cast<const Null *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Int: {
      auto ptr = reinterpret_cast<const Int *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_FloatingPoint: {
      auto ptr = reinterpret_cast<const FloatingPoint *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Binary: {
      auto ptr = reinterpret_cast<const Binary *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Utf8: {
      auto ptr = reinterpret_cast<const Utf8 *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Bool: {
      auto ptr = reinterpret_cast<const Bool *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Decimal: {
      auto ptr = reinterpret_cast<const Decimal *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Date: {
      auto ptr = reinterpret_cast<const Date *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Time: {
      auto ptr = reinterpret_cast<const Time *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Timestamp: {
      auto ptr = reinterpret_cast<const Timestamp *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Interval: {
      auto ptr = reinterpret_cast<const Interval *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_List: {
      auto ptr = reinterpret_cast<const List *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Struct_: {
      auto ptr = reinterpret_cast<const Struct_ *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Union: {
      auto ptr = reinterpret_cast<const Union *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_FixedSizeBinary: {
      auto ptr = reinterpret_cast<const FixedSizeBinary *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_FixedSizeList: {
      auto ptr = reinterpret_cast<const FixedSizeList *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Type_Map: {
      auto ptr = reinterpret_cast<const Map *>(obj);
      return verifier.VerifyTable(ptr);
    }
    default: return false;
  }
}

inline bool VerifyTypeVector(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 (!VerifyType(
        verifier,  values->Get(i), types->GetEnum<Type>(i))) {
      return false;
    }
  }
  return true;
}

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

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

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

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

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

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

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

#endif  // FLATBUFFERS_GENERATED_SCHEMA_ORG_APACHE_ARROW_FLATBUF_H_
