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


#ifndef FLATBUFFERS_GENERATED_EXPRESSION_ORG_APACHE_ARROW_COMPUTEIR_FLATBUF_H_
#define FLATBUFFERS_GENERATED_EXPRESSION_ORG_APACHE_ARROW_COMPUTEIR_FLATBUF_H_

#include "flatbuffers/flatbuffers.h"

#include "Schema_generated.h"
#include "Literal_generated.h"

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

struct MapKey;
struct MapKeyBuilder;

struct StructField;
struct StructFieldBuilder;

struct ArraySubscript;
struct ArraySubscriptBuilder;

struct ArraySlice;
struct ArraySliceBuilder;

struct FieldIndex;
struct FieldIndexBuilder;

struct FieldRef;
struct FieldRefBuilder;

struct Call;
struct CallBuilder;

struct CaseFragment;
struct CaseFragmentBuilder;

struct ConditionalCase;
struct ConditionalCaseBuilder;

struct SimpleCase;
struct SimpleCaseBuilder;

struct SortKey;
struct SortKeyBuilder;

struct Unbounded;
struct UnboundedBuilder;

struct Preceding;
struct PrecedingBuilder;

struct Following;
struct FollowingBuilder;

struct CurrentRow;
struct CurrentRowBuilder;

struct WindowCall;
struct WindowCallBuilder;

struct Cast;
struct CastBuilder;

struct Expression;
struct ExpressionBuilder;

/// A union of possible dereference operations
enum class Deref : uint8_t {
  NONE = 0,
  /// Access a value for a given map key
  MapKey = 1,
  /// Access the value at a struct field
  StructField = 2,
  /// Access the element at a given index in an array
  ArraySubscript = 3,
  /// Access a range of elements in an array
  ArraySlice = 4,
  /// Access a field of a relation
  FieldIndex = 5,
  MIN = NONE,
  MAX = FieldIndex
};

inline const Deref (&EnumValuesDeref())[6] {
  static const Deref values[] = {
    Deref::NONE,
    Deref::MapKey,
    Deref::StructField,
    Deref::ArraySubscript,
    Deref::ArraySlice,
    Deref::FieldIndex
  };
  return values;
}

inline const char * const *EnumNamesDeref() {
  static const char * const names[7] = {
    "NONE",
    "MapKey",
    "StructField",
    "ArraySubscript",
    "ArraySlice",
    "FieldIndex",
    nullptr
  };
  return names;
}

inline const char *EnumNameDeref(Deref e) {
  if (flatbuffers::IsOutRange(e, Deref::NONE, Deref::FieldIndex)) return "";
  const size_t index = static_cast<size_t>(e);
  return EnumNamesDeref()[index];
}

template<typename T> struct DerefTraits {
  static const Deref enum_value = Deref::NONE;
};

template<> struct DerefTraits<org::apache::arrow::computeir::flatbuf::MapKey> {
  static const Deref enum_value = Deref::MapKey;
};

template<> struct DerefTraits<org::apache::arrow::computeir::flatbuf::StructField> {
  static const Deref enum_value = Deref::StructField;
};

template<> struct DerefTraits<org::apache::arrow::computeir::flatbuf::ArraySubscript> {
  static const Deref enum_value = Deref::ArraySubscript;
};

template<> struct DerefTraits<org::apache::arrow::computeir::flatbuf::ArraySlice> {
  static const Deref enum_value = Deref::ArraySlice;
};

template<> struct DerefTraits<org::apache::arrow::computeir::flatbuf::FieldIndex> {
  static const Deref enum_value = Deref::FieldIndex;
};

bool VerifyDeref(flatbuffers::Verifier &verifier, const void *obj, Deref type);
bool VerifyDerefVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);

/// Whether lesser values should precede greater or vice versa,
/// also whether nulls should preced or follow values
enum class Ordering : uint8_t {
  ASCENDING_THEN_NULLS = 0,
  DESCENDING_THEN_NULLS = 1,
  NULLS_THEN_ASCENDING = 2,
  NULLS_THEN_DESCENDING = 3,
  MIN = ASCENDING_THEN_NULLS,
  MAX = NULLS_THEN_DESCENDING
};

inline const Ordering (&EnumValuesOrdering())[4] {
  static const Ordering values[] = {
    Ordering::ASCENDING_THEN_NULLS,
    Ordering::DESCENDING_THEN_NULLS,
    Ordering::NULLS_THEN_ASCENDING,
    Ordering::NULLS_THEN_DESCENDING
  };
  return values;
}

inline const char * const *EnumNamesOrdering() {
  static const char * const names[5] = {
    "ASCENDING_THEN_NULLS",
    "DESCENDING_THEN_NULLS",
    "NULLS_THEN_ASCENDING",
    "NULLS_THEN_DESCENDING",
    nullptr
  };
  return names;
}

inline const char *EnumNameOrdering(Ordering e) {
  if (flatbuffers::IsOutRange(e, Ordering::ASCENDING_THEN_NULLS, Ordering::NULLS_THEN_DESCENDING)) return "";
  const size_t index = static_cast<size_t>(e);
  return EnumNamesOrdering()[index];
}

/// A concrete bound, which can be an expression or unbounded
enum class ConcreteBoundImpl : uint8_t {
  NONE = 0,
  Expression = 1,
  Unbounded = 2,
  MIN = NONE,
  MAX = Unbounded
};

inline const ConcreteBoundImpl (&EnumValuesConcreteBoundImpl())[3] {
  static const ConcreteBoundImpl values[] = {
    ConcreteBoundImpl::NONE,
    ConcreteBoundImpl::Expression,
    ConcreteBoundImpl::Unbounded
  };
  return values;
}

inline const char * const *EnumNamesConcreteBoundImpl() {
  static const char * const names[4] = {
    "NONE",
    "Expression",
    "Unbounded",
    nullptr
  };
  return names;
}

inline const char *EnumNameConcreteBoundImpl(ConcreteBoundImpl e) {
  if (flatbuffers::IsOutRange(e, ConcreteBoundImpl::NONE, ConcreteBoundImpl::Unbounded)) return "";
  const size_t index = static_cast<size_t>(e);
  return EnumNamesConcreteBoundImpl()[index];
}

template<typename T> struct ConcreteBoundImplTraits {
  static const ConcreteBoundImpl enum_value = ConcreteBoundImpl::NONE;
};

template<> struct ConcreteBoundImplTraits<org::apache::arrow::computeir::flatbuf::Expression> {
  static const ConcreteBoundImpl enum_value = ConcreteBoundImpl::Expression;
};

template<> struct ConcreteBoundImplTraits<org::apache::arrow::computeir::flatbuf::Unbounded> {
  static const ConcreteBoundImpl enum_value = ConcreteBoundImpl::Unbounded;
};

bool VerifyConcreteBoundImpl(flatbuffers::Verifier &verifier, const void *obj, ConcreteBoundImpl type);
bool VerifyConcreteBoundImplVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);

enum class Bound : uint8_t {
  NONE = 0,
  Preceding = 1,
  Following = 2,
  CurrentRow = 3,
  MIN = NONE,
  MAX = CurrentRow
};

inline const Bound (&EnumValuesBound())[4] {
  static const Bound values[] = {
    Bound::NONE,
    Bound::Preceding,
    Bound::Following,
    Bound::CurrentRow
  };
  return values;
}

inline const char * const *EnumNamesBound() {
  static const char * const names[5] = {
    "NONE",
    "Preceding",
    "Following",
    "CurrentRow",
    nullptr
  };
  return names;
}

inline const char *EnumNameBound(Bound e) {
  if (flatbuffers::IsOutRange(e, Bound::NONE, Bound::CurrentRow)) return "";
  const size_t index = static_cast<size_t>(e);
  return EnumNamesBound()[index];
}

template<typename T> struct BoundTraits {
  static const Bound enum_value = Bound::NONE;
};

template<> struct BoundTraits<org::apache::arrow::computeir::flatbuf::Preceding> {
  static const Bound enum_value = Bound::Preceding;
};

template<> struct BoundTraits<org::apache::arrow::computeir::flatbuf::Following> {
  static const Bound enum_value = Bound::Following;
};

template<> struct BoundTraits<org::apache::arrow::computeir::flatbuf::CurrentRow> {
  static const Bound enum_value = Bound::CurrentRow;
};

bool VerifyBound(flatbuffers::Verifier &verifier, const void *obj, Bound type);
bool VerifyBoundVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);

/// The kind of window function to be executed
enum class Frame : uint8_t {
  Rows = 0,
  Range = 1,
  MIN = Rows,
  MAX = Range
};

inline const Frame (&EnumValuesFrame())[2] {
  static const Frame values[] = {
    Frame::Rows,
    Frame::Range
  };
  return values;
}

inline const char * const *EnumNamesFrame() {
  static const char * const names[3] = {
    "Rows",
    "Range",
    nullptr
  };
  return names;
}

inline const char *EnumNameFrame(Frame e) {
  if (flatbuffers::IsOutRange(e, Frame::Rows, Frame::Range)) return "";
  const size_t index = static_cast<size_t>(e);
  return EnumNamesFrame()[index];
}

/// Various expression types
///
/// WindowCall is a separate variant
/// due to special options for each that don't apply to generic
/// function calls. Again this is done to make it easier
/// for consumers to deal with the structure of the operation
enum class ExpressionImpl : uint8_t {
  NONE = 0,
  Literal = 1,
  FieldRef = 2,
  Call = 3,
  ConditionalCase = 4,
  SimpleCase = 5,
  WindowCall = 6,
  Cast = 7,
  MIN = NONE,
  MAX = Cast
};

inline const ExpressionImpl (&EnumValuesExpressionImpl())[8] {
  static const ExpressionImpl values[] = {
    ExpressionImpl::NONE,
    ExpressionImpl::Literal,
    ExpressionImpl::FieldRef,
    ExpressionImpl::Call,
    ExpressionImpl::ConditionalCase,
    ExpressionImpl::SimpleCase,
    ExpressionImpl::WindowCall,
    ExpressionImpl::Cast
  };
  return values;
}

inline const char * const *EnumNamesExpressionImpl() {
  static const char * const names[9] = {
    "NONE",
    "Literal",
    "FieldRef",
    "Call",
    "ConditionalCase",
    "SimpleCase",
    "WindowCall",
    "Cast",
    nullptr
  };
  return names;
}

inline const char *EnumNameExpressionImpl(ExpressionImpl e) {
  if (flatbuffers::IsOutRange(e, ExpressionImpl::NONE, ExpressionImpl::Cast)) return "";
  const size_t index = static_cast<size_t>(e);
  return EnumNamesExpressionImpl()[index];
}

template<typename T> struct ExpressionImplTraits {
  static const ExpressionImpl enum_value = ExpressionImpl::NONE;
};

template<> struct ExpressionImplTraits<org::apache::arrow::computeir::flatbuf::Literal> {
  static const ExpressionImpl enum_value = ExpressionImpl::Literal;
};

template<> struct ExpressionImplTraits<org::apache::arrow::computeir::flatbuf::FieldRef> {
  static const ExpressionImpl enum_value = ExpressionImpl::FieldRef;
};

template<> struct ExpressionImplTraits<org::apache::arrow::computeir::flatbuf::Call> {
  static const ExpressionImpl enum_value = ExpressionImpl::Call;
};

template<> struct ExpressionImplTraits<org::apache::arrow::computeir::flatbuf::ConditionalCase> {
  static const ExpressionImpl enum_value = ExpressionImpl::ConditionalCase;
};

template<> struct ExpressionImplTraits<org::apache::arrow::computeir::flatbuf::SimpleCase> {
  static const ExpressionImpl enum_value = ExpressionImpl::SimpleCase;
};

template<> struct ExpressionImplTraits<org::apache::arrow::computeir::flatbuf::WindowCall> {
  static const ExpressionImpl enum_value = ExpressionImpl::WindowCall;
};

template<> struct ExpressionImplTraits<org::apache::arrow::computeir::flatbuf::Cast> {
  static const ExpressionImpl enum_value = ExpressionImpl::Cast;
};

bool VerifyExpressionImpl(flatbuffers::Verifier &verifier, const void *obj, ExpressionImpl type);
bool VerifyExpressionImplVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);

/// Access a value for a given map key
struct MapKey FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef MapKeyBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_KEY = 4
  };
  /// Any expression can be a map key.
  const org::apache::arrow::computeir::flatbuf::Expression *key() const {
    return GetPointer<const org::apache::arrow::computeir::flatbuf::Expression *>(VT_KEY);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_KEY) &&
           verifier.VerifyTable(key()) &&
           verifier.EndTable();
  }
};

struct MapKeyBuilder {
  typedef MapKey Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_key(flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> key) {
    fbb_.AddOffset(MapKey::VT_KEY, key);
  }
  explicit MapKeyBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  MapKeyBuilder &operator=(const MapKeyBuilder &);
  flatbuffers::Offset<MapKey> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<MapKey>(end);
    fbb_.Required(o, MapKey::VT_KEY);
    return o;
  }
};

inline flatbuffers::Offset<MapKey> CreateMapKey(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> key = 0) {
  MapKeyBuilder builder_(_fbb);
  builder_.add_key(key);
  return builder_.Finish();
}

/// Struct field access
struct StructField FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef StructFieldBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_POSITION = 4
  };
  /// The position of the field in the struct schema
  uint32_t position() const {
    return GetField<uint32_t>(VT_POSITION, 0);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint32_t>(verifier, VT_POSITION) &&
           verifier.EndTable();
  }
};

struct StructFieldBuilder {
  typedef StructField Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_position(uint32_t position) {
    fbb_.AddElement<uint32_t>(StructField::VT_POSITION, position, 0);
  }
  explicit StructFieldBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  StructFieldBuilder &operator=(const StructFieldBuilder &);
  flatbuffers::Offset<StructField> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<StructField>(end);
    return o;
  }
};

inline flatbuffers::Offset<StructField> CreateStructField(
    flatbuffers::FlatBufferBuilder &_fbb,
    uint32_t position = 0) {
  StructFieldBuilder builder_(_fbb);
  builder_.add_position(position);
  return builder_.Finish();
}

/// Zero-based array index
struct ArraySubscript FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef ArraySubscriptBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_POSITION = 4
  };
  uint32_t position() const {
    return GetField<uint32_t>(VT_POSITION, 0);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint32_t>(verifier, VT_POSITION) &&
           verifier.EndTable();
  }
};

struct ArraySubscriptBuilder {
  typedef ArraySubscript Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_position(uint32_t position) {
    fbb_.AddElement<uint32_t>(ArraySubscript::VT_POSITION, position, 0);
  }
  explicit ArraySubscriptBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ArraySubscriptBuilder &operator=(const ArraySubscriptBuilder &);
  flatbuffers::Offset<ArraySubscript> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<ArraySubscript>(end);
    return o;
  }
};

inline flatbuffers::Offset<ArraySubscript> CreateArraySubscript(
    flatbuffers::FlatBufferBuilder &_fbb,
    uint32_t position = 0) {
  ArraySubscriptBuilder builder_(_fbb);
  builder_.add_position(position);
  return builder_.Finish();
}

/// Zero-based range of elements in an array
struct ArraySlice FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef ArraySliceBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_START_INCLUSIVE = 4,
    VT_END_EXCLUSIVE = 6
  };
  /// The start of an array slice, inclusive
  uint32_t start_inclusive() const {
    return GetField<uint32_t>(VT_START_INCLUSIVE, 0);
  }
  /// The end of an array slice, exclusive
  uint32_t end_exclusive() const {
    return GetField<uint32_t>(VT_END_EXCLUSIVE, 0);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint32_t>(verifier, VT_START_INCLUSIVE) &&
           VerifyField<uint32_t>(verifier, VT_END_EXCLUSIVE) &&
           verifier.EndTable();
  }
};

struct ArraySliceBuilder {
  typedef ArraySlice Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_start_inclusive(uint32_t start_inclusive) {
    fbb_.AddElement<uint32_t>(ArraySlice::VT_START_INCLUSIVE, start_inclusive, 0);
  }
  void add_end_exclusive(uint32_t end_exclusive) {
    fbb_.AddElement<uint32_t>(ArraySlice::VT_END_EXCLUSIVE, end_exclusive, 0);
  }
  explicit ArraySliceBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ArraySliceBuilder &operator=(const ArraySliceBuilder &);
  flatbuffers::Offset<ArraySlice> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<ArraySlice>(end);
    return o;
  }
};

inline flatbuffers::Offset<ArraySlice> CreateArraySlice(
    flatbuffers::FlatBufferBuilder &_fbb,
    uint32_t start_inclusive = 0,
    uint32_t end_exclusive = 0) {
  ArraySliceBuilder builder_(_fbb);
  builder_.add_end_exclusive(end_exclusive);
  builder_.add_start_inclusive(start_inclusive);
  return builder_.Finish();
}

/// Field name in a relation, in ordinal position of the relation's schema.
struct FieldIndex FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef FieldIndexBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_POSITION = 4
  };
  uint32_t position() const {
    return GetField<uint32_t>(VT_POSITION, 0);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint32_t>(verifier, VT_POSITION) &&
           verifier.EndTable();
  }
};

struct FieldIndexBuilder {
  typedef FieldIndex Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_position(uint32_t position) {
    fbb_.AddElement<uint32_t>(FieldIndex::VT_POSITION, position, 0);
  }
  explicit FieldIndexBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  FieldIndexBuilder &operator=(const FieldIndexBuilder &);
  flatbuffers::Offset<FieldIndex> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<FieldIndex>(end);
    return o;
  }
};

inline flatbuffers::Offset<FieldIndex> CreateFieldIndex(
    flatbuffers::FlatBufferBuilder &_fbb,
    uint32_t position = 0) {
  FieldIndexBuilder builder_(_fbb);
  builder_.add_position(position);
  return builder_.Finish();
}

/// Access the data of a field
struct FieldRef FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef FieldRefBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_REF_TYPE = 4,
    VT_REF = 6,
    VT_RELATION_INDEX = 8
  };
  org::apache::arrow::computeir::flatbuf::Deref ref_type() const {
    return static_cast<org::apache::arrow::computeir::flatbuf::Deref>(GetField<uint8_t>(VT_REF_TYPE, 0));
  }
  const void *ref() const {
    return GetPointer<const void *>(VT_REF);
  }
  template<typename T> const T *ref_as() const;
  const org::apache::arrow::computeir::flatbuf::MapKey *ref_as_MapKey() const {
    return ref_type() == org::apache::arrow::computeir::flatbuf::Deref::MapKey ? static_cast<const org::apache::arrow::computeir::flatbuf::MapKey *>(ref()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::StructField *ref_as_StructField() const {
    return ref_type() == org::apache::arrow::computeir::flatbuf::Deref::StructField ? static_cast<const org::apache::arrow::computeir::flatbuf::StructField *>(ref()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::ArraySubscript *ref_as_ArraySubscript() const {
    return ref_type() == org::apache::arrow::computeir::flatbuf::Deref::ArraySubscript ? static_cast<const org::apache::arrow::computeir::flatbuf::ArraySubscript *>(ref()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::ArraySlice *ref_as_ArraySlice() const {
    return ref_type() == org::apache::arrow::computeir::flatbuf::Deref::ArraySlice ? static_cast<const org::apache::arrow::computeir::flatbuf::ArraySlice *>(ref()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::FieldIndex *ref_as_FieldIndex() const {
    return ref_type() == org::apache::arrow::computeir::flatbuf::Deref::FieldIndex ? static_cast<const org::apache::arrow::computeir::flatbuf::FieldIndex *>(ref()) : nullptr;
  }
  /// For Expressions which might reference fields in multiple Relations,
  /// this index may be provided to indicate which Relation's fields
  /// `ref` points into. For example in the case of a join,
  /// 0 refers to the left relation and 1 to the right relation.
  int32_t relation_index() const {
    return GetField<int32_t>(VT_RELATION_INDEX, 0);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint8_t>(verifier, VT_REF_TYPE) &&
           VerifyOffsetRequired(verifier, VT_REF) &&
           VerifyDeref(verifier, ref(), ref_type()) &&
           VerifyField<int32_t>(verifier, VT_RELATION_INDEX) &&
           verifier.EndTable();
  }
};

template<> inline const org::apache::arrow::computeir::flatbuf::MapKey *FieldRef::ref_as<org::apache::arrow::computeir::flatbuf::MapKey>() const {
  return ref_as_MapKey();
}

template<> inline const org::apache::arrow::computeir::flatbuf::StructField *FieldRef::ref_as<org::apache::arrow::computeir::flatbuf::StructField>() const {
  return ref_as_StructField();
}

template<> inline const org::apache::arrow::computeir::flatbuf::ArraySubscript *FieldRef::ref_as<org::apache::arrow::computeir::flatbuf::ArraySubscript>() const {
  return ref_as_ArraySubscript();
}

template<> inline const org::apache::arrow::computeir::flatbuf::ArraySlice *FieldRef::ref_as<org::apache::arrow::computeir::flatbuf::ArraySlice>() const {
  return ref_as_ArraySlice();
}

template<> inline const org::apache::arrow::computeir::flatbuf::FieldIndex *FieldRef::ref_as<org::apache::arrow::computeir::flatbuf::FieldIndex>() const {
  return ref_as_FieldIndex();
}

struct FieldRefBuilder {
  typedef FieldRef Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_ref_type(org::apache::arrow::computeir::flatbuf::Deref ref_type) {
    fbb_.AddElement<uint8_t>(FieldRef::VT_REF_TYPE, static_cast<uint8_t>(ref_type), 0);
  }
  void add_ref(flatbuffers::Offset<void> ref) {
    fbb_.AddOffset(FieldRef::VT_REF, ref);
  }
  void add_relation_index(int32_t relation_index) {
    fbb_.AddElement<int32_t>(FieldRef::VT_RELATION_INDEX, relation_index, 0);
  }
  explicit FieldRefBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  FieldRefBuilder &operator=(const FieldRefBuilder &);
  flatbuffers::Offset<FieldRef> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<FieldRef>(end);
    fbb_.Required(o, FieldRef::VT_REF);
    return o;
  }
};

inline flatbuffers::Offset<FieldRef> CreateFieldRef(
    flatbuffers::FlatBufferBuilder &_fbb,
    org::apache::arrow::computeir::flatbuf::Deref ref_type = org::apache::arrow::computeir::flatbuf::Deref::NONE,
    flatbuffers::Offset<void> ref = 0,
    int32_t relation_index = 0) {
  FieldRefBuilder builder_(_fbb);
  builder_.add_relation_index(relation_index);
  builder_.add_ref(ref);
  builder_.add_ref_type(ref_type);
  return builder_.Finish();
}

/// A function call expression
struct Call FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef CallBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_NAME = 4,
    VT_ARGUMENTS = 6,
    VT_ORDERINGS = 8
  };
  /// The function to call
  const flatbuffers::String *name() const {
    return GetPointer<const flatbuffers::String *>(VT_NAME);
  }
  /// The arguments passed to `name`.
  const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>> *arguments() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>> *>(VT_ARGUMENTS);
  }
  /// Possible ordering of input. These are useful
  /// in aggregates where ordering in meaningful such as
  /// string concatenation
  const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>> *orderings() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>> *>(VT_ORDERINGS);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_NAME) &&
           verifier.VerifyString(name()) &&
           VerifyOffsetRequired(verifier, VT_ARGUMENTS) &&
           verifier.VerifyVector(arguments()) &&
           verifier.VerifyVectorOfTables(arguments()) &&
           VerifyOffset(verifier, VT_ORDERINGS) &&
           verifier.VerifyVector(orderings()) &&
           verifier.VerifyVectorOfTables(orderings()) &&
           verifier.EndTable();
  }
};

struct CallBuilder {
  typedef Call Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_name(flatbuffers::Offset<flatbuffers::String> name) {
    fbb_.AddOffset(Call::VT_NAME, name);
  }
  void add_arguments(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>>> arguments) {
    fbb_.AddOffset(Call::VT_ARGUMENTS, arguments);
  }
  void add_orderings(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>>> orderings) {
    fbb_.AddOffset(Call::VT_ORDERINGS, orderings);
  }
  explicit CallBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  CallBuilder &operator=(const CallBuilder &);
  flatbuffers::Offset<Call> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Call>(end);
    fbb_.Required(o, Call::VT_NAME);
    fbb_.Required(o, Call::VT_ARGUMENTS);
    return o;
  }
};

inline flatbuffers::Offset<Call> CreateCall(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<flatbuffers::String> name = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>>> arguments = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>>> orderings = 0) {
  CallBuilder builder_(_fbb);
  builder_.add_orderings(orderings);
  builder_.add_arguments(arguments);
  builder_.add_name(name);
  return builder_.Finish();
}

inline flatbuffers::Offset<Call> CreateCallDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    const char *name = nullptr,
    const std::vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>> *arguments = nullptr,
    const std::vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>> *orderings = nullptr) {
  auto name__ = name ? _fbb.CreateString(name) : 0;
  auto arguments__ = arguments ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>>(*arguments) : 0;
  auto orderings__ = orderings ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>>(*orderings) : 0;
  return org::apache::arrow::computeir::flatbuf::CreateCall(
      _fbb,
      name__,
      arguments__,
      orderings__);
}

/// A single WHEN x THEN y fragment.
struct CaseFragment FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef CaseFragmentBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_MATCH = 4,
    VT_RESULT = 6
  };
  const org::apache::arrow::computeir::flatbuf::Expression *match() const {
    return GetPointer<const org::apache::arrow::computeir::flatbuf::Expression *>(VT_MATCH);
  }
  const org::apache::arrow::computeir::flatbuf::Expression *result() const {
    return GetPointer<const org::apache::arrow::computeir::flatbuf::Expression *>(VT_RESULT);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_MATCH) &&
           verifier.VerifyTable(match()) &&
           VerifyOffsetRequired(verifier, VT_RESULT) &&
           verifier.VerifyTable(result()) &&
           verifier.EndTable();
  }
};

struct CaseFragmentBuilder {
  typedef CaseFragment Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_match(flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> match) {
    fbb_.AddOffset(CaseFragment::VT_MATCH, match);
  }
  void add_result(flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> result) {
    fbb_.AddOffset(CaseFragment::VT_RESULT, result);
  }
  explicit CaseFragmentBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  CaseFragmentBuilder &operator=(const CaseFragmentBuilder &);
  flatbuffers::Offset<CaseFragment> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<CaseFragment>(end);
    fbb_.Required(o, CaseFragment::VT_MATCH);
    fbb_.Required(o, CaseFragment::VT_RESULT);
    return o;
  }
};

inline flatbuffers::Offset<CaseFragment> CreateCaseFragment(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> match = 0,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> result = 0) {
  CaseFragmentBuilder builder_(_fbb);
  builder_.add_result(result);
  builder_.add_match(match);
  return builder_.Finish();
}

/// Conditional case statement expression
struct ConditionalCase FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef ConditionalCaseBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_CONDITIONS = 4,
    VT_ELSE_ = 6
  };
  /// List of conditions to evaluate
  const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>> *conditions() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>> *>(VT_CONDITIONS);
  }
  /// The default value if no cases match. This is typically NULL in SQL
  /// implementations.
  ///
  /// Defaulting to NULL is a frontend choice, so producers must specify NULL
  /// if that's their desired behavior.
  const org::apache::arrow::computeir::flatbuf::Expression *else_() const {
    return GetPointer<const org::apache::arrow::computeir::flatbuf::Expression *>(VT_ELSE_);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_CONDITIONS) &&
           verifier.VerifyVector(conditions()) &&
           verifier.VerifyVectorOfTables(conditions()) &&
           VerifyOffsetRequired(verifier, VT_ELSE_) &&
           verifier.VerifyTable(else_()) &&
           verifier.EndTable();
  }
};

struct ConditionalCaseBuilder {
  typedef ConditionalCase Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_conditions(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>>> conditions) {
    fbb_.AddOffset(ConditionalCase::VT_CONDITIONS, conditions);
  }
  void add_else_(flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> else_) {
    fbb_.AddOffset(ConditionalCase::VT_ELSE_, else_);
  }
  explicit ConditionalCaseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ConditionalCaseBuilder &operator=(const ConditionalCaseBuilder &);
  flatbuffers::Offset<ConditionalCase> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<ConditionalCase>(end);
    fbb_.Required(o, ConditionalCase::VT_CONDITIONS);
    fbb_.Required(o, ConditionalCase::VT_ELSE_);
    return o;
  }
};

inline flatbuffers::Offset<ConditionalCase> CreateConditionalCase(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>>> conditions = 0,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> else_ = 0) {
  ConditionalCaseBuilder builder_(_fbb);
  builder_.add_else_(else_);
  builder_.add_conditions(conditions);
  return builder_.Finish();
}

inline flatbuffers::Offset<ConditionalCase> CreateConditionalCaseDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    const std::vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>> *conditions = nullptr,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> else_ = 0) {
  auto conditions__ = conditions ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>>(*conditions) : 0;
  return org::apache::arrow::computeir::flatbuf::CreateConditionalCase(
      _fbb,
      conditions__,
      else_);
}

/// Switch-style case expression
struct SimpleCase FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef SimpleCaseBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_EXPRESSION = 4,
    VT_MATCHES = 6,
    VT_ELSE_ = 8
  };
  /// The expression whose value will be matched
  const org::apache::arrow::computeir::flatbuf::Expression *expression() const {
    return GetPointer<const org::apache::arrow::computeir::flatbuf::Expression *>(VT_EXPRESSION);
  }
  /// Matches for `expression`
  const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>> *matches() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>> *>(VT_MATCHES);
  }
  /// The default value if no cases match
  const org::apache::arrow::computeir::flatbuf::Expression *else_() const {
    return GetPointer<const org::apache::arrow::computeir::flatbuf::Expression *>(VT_ELSE_);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_EXPRESSION) &&
           verifier.VerifyTable(expression()) &&
           VerifyOffsetRequired(verifier, VT_MATCHES) &&
           verifier.VerifyVector(matches()) &&
           verifier.VerifyVectorOfTables(matches()) &&
           VerifyOffsetRequired(verifier, VT_ELSE_) &&
           verifier.VerifyTable(else_()) &&
           verifier.EndTable();
  }
};

struct SimpleCaseBuilder {
  typedef SimpleCase Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_expression(flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> expression) {
    fbb_.AddOffset(SimpleCase::VT_EXPRESSION, expression);
  }
  void add_matches(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>>> matches) {
    fbb_.AddOffset(SimpleCase::VT_MATCHES, matches);
  }
  void add_else_(flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> else_) {
    fbb_.AddOffset(SimpleCase::VT_ELSE_, else_);
  }
  explicit SimpleCaseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  SimpleCaseBuilder &operator=(const SimpleCaseBuilder &);
  flatbuffers::Offset<SimpleCase> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<SimpleCase>(end);
    fbb_.Required(o, SimpleCase::VT_EXPRESSION);
    fbb_.Required(o, SimpleCase::VT_MATCHES);
    fbb_.Required(o, SimpleCase::VT_ELSE_);
    return o;
  }
};

inline flatbuffers::Offset<SimpleCase> CreateSimpleCase(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> expression = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>>> matches = 0,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> else_ = 0) {
  SimpleCaseBuilder builder_(_fbb);
  builder_.add_else_(else_);
  builder_.add_matches(matches);
  builder_.add_expression(expression);
  return builder_.Finish();
}

inline flatbuffers::Offset<SimpleCase> CreateSimpleCaseDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> expression = 0,
    const std::vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>> *matches = nullptr,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> else_ = 0) {
  auto matches__ = matches ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::CaseFragment>>(*matches) : 0;
  return org::apache::arrow::computeir::flatbuf::CreateSimpleCase(
      _fbb,
      expression,
      matches__,
      else_);
}

/// An expression with an order
struct SortKey FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef SortKeyBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_EXPRESSION = 4,
    VT_ORDERING = 6
  };
  const org::apache::arrow::computeir::flatbuf::Expression *expression() const {
    return GetPointer<const org::apache::arrow::computeir::flatbuf::Expression *>(VT_EXPRESSION);
  }
  org::apache::arrow::computeir::flatbuf::Ordering ordering() const {
    return static_cast<org::apache::arrow::computeir::flatbuf::Ordering>(GetField<uint8_t>(VT_ORDERING, 0));
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_EXPRESSION) &&
           verifier.VerifyTable(expression()) &&
           VerifyField<uint8_t>(verifier, VT_ORDERING) &&
           verifier.EndTable();
  }
};

struct SortKeyBuilder {
  typedef SortKey Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_expression(flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> expression) {
    fbb_.AddOffset(SortKey::VT_EXPRESSION, expression);
  }
  void add_ordering(org::apache::arrow::computeir::flatbuf::Ordering ordering) {
    fbb_.AddElement<uint8_t>(SortKey::VT_ORDERING, static_cast<uint8_t>(ordering), 0);
  }
  explicit SortKeyBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  SortKeyBuilder &operator=(const SortKeyBuilder &);
  flatbuffers::Offset<SortKey> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<SortKey>(end);
    fbb_.Required(o, SortKey::VT_EXPRESSION);
    return o;
  }
};

inline flatbuffers::Offset<SortKey> CreateSortKey(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> expression = 0,
    org::apache::arrow::computeir::flatbuf::Ordering ordering = org::apache::arrow::computeir::flatbuf::Ordering::ASCENDING_THEN_NULLS) {
  SortKeyBuilder builder_(_fbb);
  builder_.add_expression(expression);
  builder_.add_ordering(ordering);
  return builder_.Finish();
}

/// An unbounded window bound
struct Unbounded FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef UnboundedBuilder Builder;
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           verifier.EndTable();
  }
};

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

inline flatbuffers::Offset<Unbounded> CreateUnbounded(
    flatbuffers::FlatBufferBuilder &_fbb) {
  UnboundedBuilder builder_(_fbb);
  return builder_.Finish();
}

/// Boundary is preceding rows, determined by the contained expression
struct Preceding FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef PrecedingBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_IMPL_TYPE = 4,
    VT_IMPL = 6
  };
  org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl impl_type() const {
    return static_cast<org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl>(GetField<uint8_t>(VT_IMPL_TYPE, 0));
  }
  const void *impl() const {
    return GetPointer<const void *>(VT_IMPL);
  }
  template<typename T> const T *impl_as() const;
  const org::apache::arrow::computeir::flatbuf::Expression *impl_as_Expression() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl::Expression ? static_cast<const org::apache::arrow::computeir::flatbuf::Expression *>(impl()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::Unbounded *impl_as_Unbounded() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl::Unbounded ? static_cast<const org::apache::arrow::computeir::flatbuf::Unbounded *>(impl()) : nullptr;
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint8_t>(verifier, VT_IMPL_TYPE) &&
           VerifyOffsetRequired(verifier, VT_IMPL) &&
           VerifyConcreteBoundImpl(verifier, impl(), impl_type()) &&
           verifier.EndTable();
  }
};

template<> inline const org::apache::arrow::computeir::flatbuf::Expression *Preceding::impl_as<org::apache::arrow::computeir::flatbuf::Expression>() const {
  return impl_as_Expression();
}

template<> inline const org::apache::arrow::computeir::flatbuf::Unbounded *Preceding::impl_as<org::apache::arrow::computeir::flatbuf::Unbounded>() const {
  return impl_as_Unbounded();
}

struct PrecedingBuilder {
  typedef Preceding Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_impl_type(org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl impl_type) {
    fbb_.AddElement<uint8_t>(Preceding::VT_IMPL_TYPE, static_cast<uint8_t>(impl_type), 0);
  }
  void add_impl(flatbuffers::Offset<void> impl) {
    fbb_.AddOffset(Preceding::VT_IMPL, impl);
  }
  explicit PrecedingBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  PrecedingBuilder &operator=(const PrecedingBuilder &);
  flatbuffers::Offset<Preceding> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Preceding>(end);
    fbb_.Required(o, Preceding::VT_IMPL);
    return o;
  }
};

inline flatbuffers::Offset<Preceding> CreatePreceding(
    flatbuffers::FlatBufferBuilder &_fbb,
    org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl impl_type = org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl::NONE,
    flatbuffers::Offset<void> impl = 0) {
  PrecedingBuilder builder_(_fbb);
  builder_.add_impl(impl);
  builder_.add_impl_type(impl_type);
  return builder_.Finish();
}

/// Boundary is following rows, determined by the contained expression
struct Following FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef FollowingBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_IMPL_TYPE = 4,
    VT_IMPL = 6
  };
  org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl impl_type() const {
    return static_cast<org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl>(GetField<uint8_t>(VT_IMPL_TYPE, 0));
  }
  const void *impl() const {
    return GetPointer<const void *>(VT_IMPL);
  }
  template<typename T> const T *impl_as() const;
  const org::apache::arrow::computeir::flatbuf::Expression *impl_as_Expression() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl::Expression ? static_cast<const org::apache::arrow::computeir::flatbuf::Expression *>(impl()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::Unbounded *impl_as_Unbounded() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl::Unbounded ? static_cast<const org::apache::arrow::computeir::flatbuf::Unbounded *>(impl()) : nullptr;
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint8_t>(verifier, VT_IMPL_TYPE) &&
           VerifyOffsetRequired(verifier, VT_IMPL) &&
           VerifyConcreteBoundImpl(verifier, impl(), impl_type()) &&
           verifier.EndTable();
  }
};

template<> inline const org::apache::arrow::computeir::flatbuf::Expression *Following::impl_as<org::apache::arrow::computeir::flatbuf::Expression>() const {
  return impl_as_Expression();
}

template<> inline const org::apache::arrow::computeir::flatbuf::Unbounded *Following::impl_as<org::apache::arrow::computeir::flatbuf::Unbounded>() const {
  return impl_as_Unbounded();
}

struct FollowingBuilder {
  typedef Following Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_impl_type(org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl impl_type) {
    fbb_.AddElement<uint8_t>(Following::VT_IMPL_TYPE, static_cast<uint8_t>(impl_type), 0);
  }
  void add_impl(flatbuffers::Offset<void> impl) {
    fbb_.AddOffset(Following::VT_IMPL, impl);
  }
  explicit FollowingBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  FollowingBuilder &operator=(const FollowingBuilder &);
  flatbuffers::Offset<Following> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Following>(end);
    fbb_.Required(o, Following::VT_IMPL);
    return o;
  }
};

inline flatbuffers::Offset<Following> CreateFollowing(
    flatbuffers::FlatBufferBuilder &_fbb,
    org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl impl_type = org::apache::arrow::computeir::flatbuf::ConcreteBoundImpl::NONE,
    flatbuffers::Offset<void> impl = 0) {
  FollowingBuilder builder_(_fbb);
  builder_.add_impl(impl);
  builder_.add_impl_type(impl_type);
  return builder_.Finish();
}

/// Boundary is the current row
struct CurrentRow FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef CurrentRowBuilder Builder;
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           verifier.EndTable();
  }
};

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

inline flatbuffers::Offset<CurrentRow> CreateCurrentRow(
    flatbuffers::FlatBufferBuilder &_fbb) {
  CurrentRowBuilder builder_(_fbb);
  return builder_.Finish();
}

/// An expression representing a window function call.
struct WindowCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef WindowCallBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_EXPRESSION = 4,
    VT_KIND = 6,
    VT_PARTITIONS = 8,
    VT_ORDERINGS = 10,
    VT_LOWER_BOUND_TYPE = 12,
    VT_LOWER_BOUND = 14,
    VT_UPPER_BOUND_TYPE = 16,
    VT_UPPER_BOUND = 18
  };
  /// The expression to operate over
  const org::apache::arrow::computeir::flatbuf::Expression *expression() const {
    return GetPointer<const org::apache::arrow::computeir::flatbuf::Expression *>(VT_EXPRESSION);
  }
  /// The kind of window frame
  org::apache::arrow::computeir::flatbuf::Frame kind() const {
    return static_cast<org::apache::arrow::computeir::flatbuf::Frame>(GetField<uint8_t>(VT_KIND, 0));
  }
  /// Partition keys
  const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>> *partitions() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>> *>(VT_PARTITIONS);
  }
  /// Sort keys
  const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>> *orderings() const {
    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>> *>(VT_ORDERINGS);
  }
  org::apache::arrow::computeir::flatbuf::Bound lower_bound_type() const {
    return static_cast<org::apache::arrow::computeir::flatbuf::Bound>(GetField<uint8_t>(VT_LOWER_BOUND_TYPE, 0));
  }
  /// Lower window bound
  const void *lower_bound() const {
    return GetPointer<const void *>(VT_LOWER_BOUND);
  }
  template<typename T> const T *lower_bound_as() const;
  const org::apache::arrow::computeir::flatbuf::Preceding *lower_bound_as_Preceding() const {
    return lower_bound_type() == org::apache::arrow::computeir::flatbuf::Bound::Preceding ? static_cast<const org::apache::arrow::computeir::flatbuf::Preceding *>(lower_bound()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::Following *lower_bound_as_Following() const {
    return lower_bound_type() == org::apache::arrow::computeir::flatbuf::Bound::Following ? static_cast<const org::apache::arrow::computeir::flatbuf::Following *>(lower_bound()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::CurrentRow *lower_bound_as_CurrentRow() const {
    return lower_bound_type() == org::apache::arrow::computeir::flatbuf::Bound::CurrentRow ? static_cast<const org::apache::arrow::computeir::flatbuf::CurrentRow *>(lower_bound()) : nullptr;
  }
  org::apache::arrow::computeir::flatbuf::Bound upper_bound_type() const {
    return static_cast<org::apache::arrow::computeir::flatbuf::Bound>(GetField<uint8_t>(VT_UPPER_BOUND_TYPE, 0));
  }
  /// Upper window bound
  const void *upper_bound() const {
    return GetPointer<const void *>(VT_UPPER_BOUND);
  }
  template<typename T> const T *upper_bound_as() const;
  const org::apache::arrow::computeir::flatbuf::Preceding *upper_bound_as_Preceding() const {
    return upper_bound_type() == org::apache::arrow::computeir::flatbuf::Bound::Preceding ? static_cast<const org::apache::arrow::computeir::flatbuf::Preceding *>(upper_bound()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::Following *upper_bound_as_Following() const {
    return upper_bound_type() == org::apache::arrow::computeir::flatbuf::Bound::Following ? static_cast<const org::apache::arrow::computeir::flatbuf::Following *>(upper_bound()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::CurrentRow *upper_bound_as_CurrentRow() const {
    return upper_bound_type() == org::apache::arrow::computeir::flatbuf::Bound::CurrentRow ? static_cast<const org::apache::arrow::computeir::flatbuf::CurrentRow *>(upper_bound()) : nullptr;
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_EXPRESSION) &&
           verifier.VerifyTable(expression()) &&
           VerifyField<uint8_t>(verifier, VT_KIND) &&
           VerifyOffsetRequired(verifier, VT_PARTITIONS) &&
           verifier.VerifyVector(partitions()) &&
           verifier.VerifyVectorOfTables(partitions()) &&
           VerifyOffsetRequired(verifier, VT_ORDERINGS) &&
           verifier.VerifyVector(orderings()) &&
           verifier.VerifyVectorOfTables(orderings()) &&
           VerifyField<uint8_t>(verifier, VT_LOWER_BOUND_TYPE) &&
           VerifyOffsetRequired(verifier, VT_LOWER_BOUND) &&
           VerifyBound(verifier, lower_bound(), lower_bound_type()) &&
           VerifyField<uint8_t>(verifier, VT_UPPER_BOUND_TYPE) &&
           VerifyOffsetRequired(verifier, VT_UPPER_BOUND) &&
           VerifyBound(verifier, upper_bound(), upper_bound_type()) &&
           verifier.EndTable();
  }
};

template<> inline const org::apache::arrow::computeir::flatbuf::Preceding *WindowCall::lower_bound_as<org::apache::arrow::computeir::flatbuf::Preceding>() const {
  return lower_bound_as_Preceding();
}

template<> inline const org::apache::arrow::computeir::flatbuf::Following *WindowCall::lower_bound_as<org::apache::arrow::computeir::flatbuf::Following>() const {
  return lower_bound_as_Following();
}

template<> inline const org::apache::arrow::computeir::flatbuf::CurrentRow *WindowCall::lower_bound_as<org::apache::arrow::computeir::flatbuf::CurrentRow>() const {
  return lower_bound_as_CurrentRow();
}

template<> inline const org::apache::arrow::computeir::flatbuf::Preceding *WindowCall::upper_bound_as<org::apache::arrow::computeir::flatbuf::Preceding>() const {
  return upper_bound_as_Preceding();
}

template<> inline const org::apache::arrow::computeir::flatbuf::Following *WindowCall::upper_bound_as<org::apache::arrow::computeir::flatbuf::Following>() const {
  return upper_bound_as_Following();
}

template<> inline const org::apache::arrow::computeir::flatbuf::CurrentRow *WindowCall::upper_bound_as<org::apache::arrow::computeir::flatbuf::CurrentRow>() const {
  return upper_bound_as_CurrentRow();
}

struct WindowCallBuilder {
  typedef WindowCall Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_expression(flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> expression) {
    fbb_.AddOffset(WindowCall::VT_EXPRESSION, expression);
  }
  void add_kind(org::apache::arrow::computeir::flatbuf::Frame kind) {
    fbb_.AddElement<uint8_t>(WindowCall::VT_KIND, static_cast<uint8_t>(kind), 0);
  }
  void add_partitions(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>>> partitions) {
    fbb_.AddOffset(WindowCall::VT_PARTITIONS, partitions);
  }
  void add_orderings(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>>> orderings) {
    fbb_.AddOffset(WindowCall::VT_ORDERINGS, orderings);
  }
  void add_lower_bound_type(org::apache::arrow::computeir::flatbuf::Bound lower_bound_type) {
    fbb_.AddElement<uint8_t>(WindowCall::VT_LOWER_BOUND_TYPE, static_cast<uint8_t>(lower_bound_type), 0);
  }
  void add_lower_bound(flatbuffers::Offset<void> lower_bound) {
    fbb_.AddOffset(WindowCall::VT_LOWER_BOUND, lower_bound);
  }
  void add_upper_bound_type(org::apache::arrow::computeir::flatbuf::Bound upper_bound_type) {
    fbb_.AddElement<uint8_t>(WindowCall::VT_UPPER_BOUND_TYPE, static_cast<uint8_t>(upper_bound_type), 0);
  }
  void add_upper_bound(flatbuffers::Offset<void> upper_bound) {
    fbb_.AddOffset(WindowCall::VT_UPPER_BOUND, upper_bound);
  }
  explicit WindowCallBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  WindowCallBuilder &operator=(const WindowCallBuilder &);
  flatbuffers::Offset<WindowCall> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<WindowCall>(end);
    fbb_.Required(o, WindowCall::VT_EXPRESSION);
    fbb_.Required(o, WindowCall::VT_PARTITIONS);
    fbb_.Required(o, WindowCall::VT_ORDERINGS);
    fbb_.Required(o, WindowCall::VT_LOWER_BOUND);
    fbb_.Required(o, WindowCall::VT_UPPER_BOUND);
    return o;
  }
};

inline flatbuffers::Offset<WindowCall> CreateWindowCall(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> expression = 0,
    org::apache::arrow::computeir::flatbuf::Frame kind = org::apache::arrow::computeir::flatbuf::Frame::Rows,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>>> partitions = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>>> orderings = 0,
    org::apache::arrow::computeir::flatbuf::Bound lower_bound_type = org::apache::arrow::computeir::flatbuf::Bound::NONE,
    flatbuffers::Offset<void> lower_bound = 0,
    org::apache::arrow::computeir::flatbuf::Bound upper_bound_type = org::apache::arrow::computeir::flatbuf::Bound::NONE,
    flatbuffers::Offset<void> upper_bound = 0) {
  WindowCallBuilder builder_(_fbb);
  builder_.add_upper_bound(upper_bound);
  builder_.add_lower_bound(lower_bound);
  builder_.add_orderings(orderings);
  builder_.add_partitions(partitions);
  builder_.add_expression(expression);
  builder_.add_upper_bound_type(upper_bound_type);
  builder_.add_lower_bound_type(lower_bound_type);
  builder_.add_kind(kind);
  return builder_.Finish();
}

inline flatbuffers::Offset<WindowCall> CreateWindowCallDirect(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> expression = 0,
    org::apache::arrow::computeir::flatbuf::Frame kind = org::apache::arrow::computeir::flatbuf::Frame::Rows,
    const std::vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>> *partitions = nullptr,
    const std::vector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>> *orderings = nullptr,
    org::apache::arrow::computeir::flatbuf::Bound lower_bound_type = org::apache::arrow::computeir::flatbuf::Bound::NONE,
    flatbuffers::Offset<void> lower_bound = 0,
    org::apache::arrow::computeir::flatbuf::Bound upper_bound_type = org::apache::arrow::computeir::flatbuf::Bound::NONE,
    flatbuffers::Offset<void> upper_bound = 0) {
  auto partitions__ = partitions ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression>>(*partitions) : 0;
  auto orderings__ = orderings ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::SortKey>>(*orderings) : 0;
  return org::apache::arrow::computeir::flatbuf::CreateWindowCall(
      _fbb,
      expression,
      kind,
      partitions__,
      orderings__,
      lower_bound_type,
      lower_bound,
      upper_bound_type,
      upper_bound);
}

/// A cast expression
struct Cast FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef CastBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_OPERAND = 4,
    VT_TO = 6
  };
  /// The expression to cast
  const org::apache::arrow::computeir::flatbuf::Expression *operand() const {
    return GetPointer<const org::apache::arrow::computeir::flatbuf::Expression *>(VT_OPERAND);
  }
  /// The type to cast to. This value is a `Field` to allow complete representation
  /// of arrow types.
  ///
  /// `Type` is unable to completely represent complex types like lists and
  /// maps.
  const org::apache::arrow::flatbuf::Field *to() const {
    return GetPointer<const org::apache::arrow::flatbuf::Field *>(VT_TO);
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_OPERAND) &&
           verifier.VerifyTable(operand()) &&
           VerifyOffsetRequired(verifier, VT_TO) &&
           verifier.VerifyTable(to()) &&
           verifier.EndTable();
  }
};

struct CastBuilder {
  typedef Cast Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_operand(flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> operand) {
    fbb_.AddOffset(Cast::VT_OPERAND, operand);
  }
  void add_to(flatbuffers::Offset<org::apache::arrow::flatbuf::Field> to) {
    fbb_.AddOffset(Cast::VT_TO, to);
  }
  explicit CastBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  CastBuilder &operator=(const CastBuilder &);
  flatbuffers::Offset<Cast> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Cast>(end);
    fbb_.Required(o, Cast::VT_OPERAND);
    fbb_.Required(o, Cast::VT_TO);
    return o;
  }
};

inline flatbuffers::Offset<Cast> CreateCast(
    flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<org::apache::arrow::computeir::flatbuf::Expression> operand = 0,
    flatbuffers::Offset<org::apache::arrow::flatbuf::Field> to = 0) {
  CastBuilder builder_(_fbb);
  builder_.add_to(to);
  builder_.add_operand(operand);
  return builder_.Finish();
}

/// Expression types
///
/// Expressions have a concrete `impl` value, which is a specific operation.
///
/// This is a workaround for flatbuffers' lack of support for direct use of
/// union types.
struct Expression FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
  typedef ExpressionBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_IMPL_TYPE = 4,
    VT_IMPL = 6
  };
  org::apache::arrow::computeir::flatbuf::ExpressionImpl impl_type() const {
    return static_cast<org::apache::arrow::computeir::flatbuf::ExpressionImpl>(GetField<uint8_t>(VT_IMPL_TYPE, 0));
  }
  const void *impl() const {
    return GetPointer<const void *>(VT_IMPL);
  }
  template<typename T> const T *impl_as() const;
  const org::apache::arrow::computeir::flatbuf::Literal *impl_as_Literal() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ExpressionImpl::Literal ? static_cast<const org::apache::arrow::computeir::flatbuf::Literal *>(impl()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::FieldRef *impl_as_FieldRef() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ExpressionImpl::FieldRef ? static_cast<const org::apache::arrow::computeir::flatbuf::FieldRef *>(impl()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::Call *impl_as_Call() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ExpressionImpl::Call ? static_cast<const org::apache::arrow::computeir::flatbuf::Call *>(impl()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::ConditionalCase *impl_as_ConditionalCase() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ExpressionImpl::ConditionalCase ? static_cast<const org::apache::arrow::computeir::flatbuf::ConditionalCase *>(impl()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::SimpleCase *impl_as_SimpleCase() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ExpressionImpl::SimpleCase ? static_cast<const org::apache::arrow::computeir::flatbuf::SimpleCase *>(impl()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::WindowCall *impl_as_WindowCall() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ExpressionImpl::WindowCall ? static_cast<const org::apache::arrow::computeir::flatbuf::WindowCall *>(impl()) : nullptr;
  }
  const org::apache::arrow::computeir::flatbuf::Cast *impl_as_Cast() const {
    return impl_type() == org::apache::arrow::computeir::flatbuf::ExpressionImpl::Cast ? static_cast<const org::apache::arrow::computeir::flatbuf::Cast *>(impl()) : nullptr;
  }
  bool Verify(flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<uint8_t>(verifier, VT_IMPL_TYPE) &&
           VerifyOffsetRequired(verifier, VT_IMPL) &&
           VerifyExpressionImpl(verifier, impl(), impl_type()) &&
           verifier.EndTable();
  }
};

template<> inline const org::apache::arrow::computeir::flatbuf::Literal *Expression::impl_as<org::apache::arrow::computeir::flatbuf::Literal>() const {
  return impl_as_Literal();
}

template<> inline const org::apache::arrow::computeir::flatbuf::FieldRef *Expression::impl_as<org::apache::arrow::computeir::flatbuf::FieldRef>() const {
  return impl_as_FieldRef();
}

template<> inline const org::apache::arrow::computeir::flatbuf::Call *Expression::impl_as<org::apache::arrow::computeir::flatbuf::Call>() const {
  return impl_as_Call();
}

template<> inline const org::apache::arrow::computeir::flatbuf::ConditionalCase *Expression::impl_as<org::apache::arrow::computeir::flatbuf::ConditionalCase>() const {
  return impl_as_ConditionalCase();
}

template<> inline const org::apache::arrow::computeir::flatbuf::SimpleCase *Expression::impl_as<org::apache::arrow::computeir::flatbuf::SimpleCase>() const {
  return impl_as_SimpleCase();
}

template<> inline const org::apache::arrow::computeir::flatbuf::WindowCall *Expression::impl_as<org::apache::arrow::computeir::flatbuf::WindowCall>() const {
  return impl_as_WindowCall();
}

template<> inline const org::apache::arrow::computeir::flatbuf::Cast *Expression::impl_as<org::apache::arrow::computeir::flatbuf::Cast>() const {
  return impl_as_Cast();
}

struct ExpressionBuilder {
  typedef Expression Table;
  flatbuffers::FlatBufferBuilder &fbb_;
  flatbuffers::uoffset_t start_;
  void add_impl_type(org::apache::arrow::computeir::flatbuf::ExpressionImpl impl_type) {
    fbb_.AddElement<uint8_t>(Expression::VT_IMPL_TYPE, static_cast<uint8_t>(impl_type), 0);
  }
  void add_impl(flatbuffers::Offset<void> impl) {
    fbb_.AddOffset(Expression::VT_IMPL, impl);
  }
  explicit ExpressionBuilder(flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ExpressionBuilder &operator=(const ExpressionBuilder &);
  flatbuffers::Offset<Expression> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = flatbuffers::Offset<Expression>(end);
    fbb_.Required(o, Expression::VT_IMPL);
    return o;
  }
};

inline flatbuffers::Offset<Expression> CreateExpression(
    flatbuffers::FlatBufferBuilder &_fbb,
    org::apache::arrow::computeir::flatbuf::ExpressionImpl impl_type = org::apache::arrow::computeir::flatbuf::ExpressionImpl::NONE,
    flatbuffers::Offset<void> impl = 0) {
  ExpressionBuilder builder_(_fbb);
  builder_.add_impl(impl);
  builder_.add_impl_type(impl_type);
  return builder_.Finish();
}

inline bool VerifyDeref(flatbuffers::Verifier &verifier, const void *obj, Deref type) {
  switch (type) {
    case Deref::NONE: {
      return true;
    }
    case Deref::MapKey: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::MapKey *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Deref::StructField: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::StructField *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Deref::ArraySubscript: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::ArraySubscript *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Deref::ArraySlice: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::ArraySlice *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Deref::FieldIndex: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::FieldIndex *>(obj);
      return verifier.VerifyTable(ptr);
    }
    default: return true;
  }
}

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

inline bool VerifyConcreteBoundImpl(flatbuffers::Verifier &verifier, const void *obj, ConcreteBoundImpl type) {
  switch (type) {
    case ConcreteBoundImpl::NONE: {
      return true;
    }
    case ConcreteBoundImpl::Expression: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::Expression *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case ConcreteBoundImpl::Unbounded: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::Unbounded *>(obj);
      return verifier.VerifyTable(ptr);
    }
    default: return true;
  }
}

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

inline bool VerifyBound(flatbuffers::Verifier &verifier, const void *obj, Bound type) {
  switch (type) {
    case Bound::NONE: {
      return true;
    }
    case Bound::Preceding: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::Preceding *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Bound::Following: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::Following *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case Bound::CurrentRow: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::CurrentRow *>(obj);
      return verifier.VerifyTable(ptr);
    }
    default: return true;
  }
}

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

inline bool VerifyExpressionImpl(flatbuffers::Verifier &verifier, const void *obj, ExpressionImpl type) {
  switch (type) {
    case ExpressionImpl::NONE: {
      return true;
    }
    case ExpressionImpl::Literal: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::Literal *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case ExpressionImpl::FieldRef: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::FieldRef *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case ExpressionImpl::Call: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::Call *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case ExpressionImpl::ConditionalCase: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::ConditionalCase *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case ExpressionImpl::SimpleCase: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::SimpleCase *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case ExpressionImpl::WindowCall: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::WindowCall *>(obj);
      return verifier.VerifyTable(ptr);
    }
    case ExpressionImpl::Cast: {
      auto ptr = reinterpret_cast<const org::apache::arrow::computeir::flatbuf::Cast *>(obj);
      return verifier.VerifyTable(ptr);
    }
    default: return true;
  }
}

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

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

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

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

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

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

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

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

#endif  // FLATBUFFERS_GENERATED_EXPRESSION_ORG_APACHE_ARROW_COMPUTEIR_FLATBUF_H_
