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


#ifndef FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
#define FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_

#include "flatbuffers/flatbuffers.h"

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

namespace reflection {

struct Type;
struct TypeBuilder;

struct KeyValue;
struct KeyValueBuilder;

struct EnumVal;
struct EnumValBuilder;

struct Enum;
struct EnumBuilder;

struct Field;
struct FieldBuilder;

struct Object;
struct ObjectBuilder;

struct RPCCall;
struct RPCCallBuilder;

struct Service;
struct ServiceBuilder;

struct SchemaFile;
struct SchemaFileBuilder;

struct Schema;
struct SchemaBuilder;

enum BaseType {
  None = 0,
  UType = 1,
  Bool = 2,
  Byte = 3,
  UByte = 4,
  Short = 5,
  UShort = 6,
  Int = 7,
  UInt = 8,
  Long = 9,
  ULong = 10,
  Float = 11,
  Double = 12,
  String = 13,
  Vector = 14,
  Obj = 15,
  Union = 16,
  Array = 17,
  Vector64 = 18,
  MaxBaseType = 19
};

inline const BaseType (&EnumValuesBaseType())[20] {
  static const BaseType values[] = {
    None,
    UType,
    Bool,
    Byte,
    UByte,
    Short,
    UShort,
    Int,
    UInt,
    Long,
    ULong,
    Float,
    Double,
    String,
    Vector,
    Obj,
    Union,
    Array,
    Vector64,
    MaxBaseType
  };
  return values;
}

inline const char * const *EnumNamesBaseType() {
  static const char * const names[21] = {
    "None",
    "UType",
    "Bool",
    "Byte",
    "UByte",
    "Short",
    "UShort",
    "Int",
    "UInt",
    "Long",
    "ULong",
    "Float",
    "Double",
    "String",
    "Vector",
    "Obj",
    "Union",
    "Array",
    "Vector64",
    "MaxBaseType",
    nullptr
  };
  return names;
}

inline const char *EnumNameBaseType(BaseType e) {
  if (::flatbuffers::IsOutRange(e, None, MaxBaseType)) return "";
  const size_t index = static_cast<size_t>(e);
  return EnumNamesBaseType()[index];
}

/// New schema language features that are not supported by old code generators.
enum AdvancedFeatures {
  AdvancedArrayFeatures = 1ULL,
  AdvancedUnionFeatures = 2ULL,
  OptionalScalars = 4ULL,
  DefaultVectorsAndStrings = 8ULL
};

inline const AdvancedFeatures (&EnumValuesAdvancedFeatures())[4] {
  static const AdvancedFeatures values[] = {
    AdvancedArrayFeatures,
    AdvancedUnionFeatures,
    OptionalScalars,
    DefaultVectorsAndStrings
  };
  return values;
}

inline const char * const *EnumNamesAdvancedFeatures() {
  static const char * const names[9] = {
    "AdvancedArrayFeatures",
    "AdvancedUnionFeatures",
    "",
    "OptionalScalars",
    "",
    "",
    "",
    "DefaultVectorsAndStrings",
    nullptr
  };
  return names;
}

inline const char *EnumNameAdvancedFeatures(AdvancedFeatures e) {
  if (::flatbuffers::IsOutRange(e, AdvancedArrayFeatures, DefaultVectorsAndStrings)) return "";
  const size_t index = static_cast<size_t>(e) - static_cast<size_t>(AdvancedArrayFeatures);
  return EnumNamesAdvancedFeatures()[index];
}

struct Type FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef TypeBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_BASE_TYPE = 4,
    VT_ELEMENT = 6,
    VT_INDEX = 8,
    VT_FIXED_LENGTH = 10,
    VT_BASE_SIZE = 12,
    VT_ELEMENT_SIZE = 14
  };
  reflection::BaseType base_type() const {
    return static_cast<reflection::BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
  }
  reflection::BaseType element() const {
    return static_cast<reflection::BaseType>(GetField<int8_t>(VT_ELEMENT, 0));
  }
  int32_t index() const {
    return GetField<int32_t>(VT_INDEX, -1);
  }
  uint16_t fixed_length() const {
    return GetField<uint16_t>(VT_FIXED_LENGTH, 0);
  }
  /// The size (octets) of the `base_type` field.
  uint32_t base_size() const {
    return GetField<uint32_t>(VT_BASE_SIZE, 4);
  }
  /// The size (octets) of the `element` field, if present.
  uint32_t element_size() const {
    return GetField<uint32_t>(VT_ELEMENT_SIZE, 0);
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<int8_t>(verifier, VT_BASE_TYPE, 1) &&
           VerifyField<int8_t>(verifier, VT_ELEMENT, 1) &&
           VerifyField<int32_t>(verifier, VT_INDEX, 4) &&
           VerifyField<uint16_t>(verifier, VT_FIXED_LENGTH, 2) &&
           VerifyField<uint32_t>(verifier, VT_BASE_SIZE, 4) &&
           VerifyField<uint32_t>(verifier, VT_ELEMENT_SIZE, 4) &&
           verifier.EndTable();
  }
};

struct TypeBuilder {
  typedef Type Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_base_type(reflection::BaseType base_type) {
    fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0);
  }
  void add_element(reflection::BaseType element) {
    fbb_.AddElement<int8_t>(Type::VT_ELEMENT, static_cast<int8_t>(element), 0);
  }
  void add_index(int32_t index) {
    fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
  }
  void add_fixed_length(uint16_t fixed_length) {
    fbb_.AddElement<uint16_t>(Type::VT_FIXED_LENGTH, fixed_length, 0);
  }
  void add_base_size(uint32_t base_size) {
    fbb_.AddElement<uint32_t>(Type::VT_BASE_SIZE, base_size, 4);
  }
  void add_element_size(uint32_t element_size) {
    fbb_.AddElement<uint32_t>(Type::VT_ELEMENT_SIZE, element_size, 0);
  }
  explicit TypeBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<Type> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<Type>(end);
    return o;
  }
};

inline ::flatbuffers::Offset<Type> CreateType(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    reflection::BaseType base_type = reflection::None,
    reflection::BaseType element = reflection::None,
    int32_t index = -1,
    uint16_t fixed_length = 0,
    uint32_t base_size = 4,
    uint32_t element_size = 0) {
  TypeBuilder builder_(_fbb);
  builder_.add_element_size(element_size);
  builder_.add_base_size(base_size);
  builder_.add_index(index);
  builder_.add_fixed_length(fixed_length);
  builder_.add_element(element);
  builder_.add_base_type(base_type);
  return builder_.Finish();
}

struct KeyValue FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef KeyValueBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_KEY = 4,
    VT_VALUE = 6
  };
  const ::flatbuffers::String *key() const {
    return GetPointer<const ::flatbuffers::String *>(VT_KEY);
  }
  bool KeyCompareLessThan(const KeyValue * const o) const {
    return *key() < *o->key();
  }
  int KeyCompareWithValue(const char *_key) const {
    return strcmp(key()->c_str(), _key);
  }
  const ::flatbuffers::String *value() const {
    return GetPointer<const ::flatbuffers::String *>(VT_VALUE);
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_KEY) &&
           verifier.VerifyString(key()) &&
           VerifyOffset(verifier, VT_VALUE) &&
           verifier.VerifyString(value()) &&
           verifier.EndTable();
  }
};

struct KeyValueBuilder {
  typedef KeyValue Table;
  ::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();
  }
  ::flatbuffers::Offset<KeyValue> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<KeyValue>(end);
    fbb_.Required(o, KeyValue::VT_KEY);
    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) {
  auto key__ = key ? _fbb.CreateString(key) : 0;
  auto value__ = value ? _fbb.CreateString(value) : 0;
  return reflection::CreateKeyValue(
      _fbb,
      key__,
      value__);
}

struct EnumVal FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef EnumValBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_NAME = 4,
    VT_VALUE = 6,
    VT_UNION_TYPE = 10,
    VT_DOCUMENTATION = 12,
    VT_ATTRIBUTES = 14
  };
  const ::flatbuffers::String *name() const {
    return GetPointer<const ::flatbuffers::String *>(VT_NAME);
  }
  int64_t value() const {
    return GetField<int64_t>(VT_VALUE, 0);
  }
  bool KeyCompareLessThan(const EnumVal * const o) const {
    return value() < o->value();
  }
  int KeyCompareWithValue(int64_t _value) const {
    return static_cast<int>(value() > _value) - static_cast<int>(value() < _value);
  }
  const reflection::Type *union_type() const {
    return GetPointer<const reflection::Type *>(VT_UNION_TYPE);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *>(VT_DOCUMENTATION);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_NAME) &&
           verifier.VerifyString(name()) &&
           VerifyField<int64_t>(verifier, VT_VALUE, 8) &&
           VerifyOffset(verifier, VT_UNION_TYPE) &&
           verifier.VerifyTable(union_type()) &&
           VerifyOffset(verifier, VT_DOCUMENTATION) &&
           verifier.VerifyVector(documentation()) &&
           verifier.VerifyVectorOfStrings(documentation()) &&
           VerifyOffset(verifier, VT_ATTRIBUTES) &&
           verifier.VerifyVector(attributes()) &&
           verifier.VerifyVectorOfTables(attributes()) &&
           verifier.EndTable();
  }
};

struct EnumValBuilder {
  typedef EnumVal Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
    fbb_.AddOffset(EnumVal::VT_NAME, name);
  }
  void add_value(int64_t value) {
    fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0);
  }
  void add_union_type(::flatbuffers::Offset<reflection::Type> union_type) {
    fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type);
  }
  void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
    fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation);
  }
  void add_attributes(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes) {
    fbb_.AddOffset(EnumVal::VT_ATTRIBUTES, attributes);
  }
  explicit EnumValBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<EnumVal> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<EnumVal>(end);
    fbb_.Required(o, EnumVal::VT_NAME);
    return o;
  }
};

inline ::flatbuffers::Offset<EnumVal> CreateEnumVal(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    ::flatbuffers::Offset<::flatbuffers::String> name = 0,
    int64_t value = 0,
    ::flatbuffers::Offset<reflection::Type> union_type = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0) {
  EnumValBuilder builder_(_fbb);
  builder_.add_value(value);
  builder_.add_attributes(attributes);
  builder_.add_documentation(documentation);
  builder_.add_union_type(union_type);
  builder_.add_name(name);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<EnumVal> CreateEnumValDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    const char *name = nullptr,
    int64_t value = 0,
    ::flatbuffers::Offset<reflection::Type> union_type = 0,
    const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr,
    std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr) {
  auto name__ = name ? _fbb.CreateString(name) : 0;
  auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
  auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
  return reflection::CreateEnumVal(
      _fbb,
      name__,
      value,
      union_type,
      documentation__,
      attributes__);
}

struct Enum FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef EnumBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_NAME = 4,
    VT_VALUES = 6,
    VT_IS_UNION = 8,
    VT_UNDERLYING_TYPE = 10,
    VT_ATTRIBUTES = 12,
    VT_DOCUMENTATION = 14,
    VT_DECLARATION_FILE = 16
  };
  const ::flatbuffers::String *name() const {
    return GetPointer<const ::flatbuffers::String *>(VT_NAME);
  }
  bool KeyCompareLessThan(const Enum * const o) const {
    return *name() < *o->name();
  }
  int KeyCompareWithValue(const char *_name) const {
    return strcmp(name()->c_str(), _name);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::EnumVal>> *values() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::EnumVal>> *>(VT_VALUES);
  }
  bool is_union() const {
    return GetField<uint8_t>(VT_IS_UNION, 0) != 0;
  }
  const reflection::Type *underlying_type() const {
    return GetPointer<const reflection::Type *>(VT_UNDERLYING_TYPE);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *>(VT_DOCUMENTATION);
  }
  /// File that this Enum is declared in.
  const ::flatbuffers::String *declaration_file() const {
    return GetPointer<const ::flatbuffers::String *>(VT_DECLARATION_FILE);
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_NAME) &&
           verifier.VerifyString(name()) &&
           VerifyOffsetRequired(verifier, VT_VALUES) &&
           verifier.VerifyVector(values()) &&
           verifier.VerifyVectorOfTables(values()) &&
           VerifyField<uint8_t>(verifier, VT_IS_UNION, 1) &&
           VerifyOffsetRequired(verifier, VT_UNDERLYING_TYPE) &&
           verifier.VerifyTable(underlying_type()) &&
           VerifyOffset(verifier, VT_ATTRIBUTES) &&
           verifier.VerifyVector(attributes()) &&
           verifier.VerifyVectorOfTables(attributes()) &&
           VerifyOffset(verifier, VT_DOCUMENTATION) &&
           verifier.VerifyVector(documentation()) &&
           verifier.VerifyVectorOfStrings(documentation()) &&
           VerifyOffset(verifier, VT_DECLARATION_FILE) &&
           verifier.VerifyString(declaration_file()) &&
           verifier.EndTable();
  }
};

struct EnumBuilder {
  typedef Enum Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
    fbb_.AddOffset(Enum::VT_NAME, name);
  }
  void add_values(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::EnumVal>>> values) {
    fbb_.AddOffset(Enum::VT_VALUES, values);
  }
  void add_is_union(bool is_union) {
    fbb_.AddElement<uint8_t>(Enum::VT_IS_UNION, static_cast<uint8_t>(is_union), 0);
  }
  void add_underlying_type(::flatbuffers::Offset<reflection::Type> underlying_type) {
    fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type);
  }
  void add_attributes(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes) {
    fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes);
  }
  void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
    fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation);
  }
  void add_declaration_file(::flatbuffers::Offset<::flatbuffers::String> declaration_file) {
    fbb_.AddOffset(Enum::VT_DECLARATION_FILE, declaration_file);
  }
  explicit EnumBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<Enum> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<Enum>(end);
    fbb_.Required(o, Enum::VT_NAME);
    fbb_.Required(o, Enum::VT_VALUES);
    fbb_.Required(o, Enum::VT_UNDERLYING_TYPE);
    return o;
  }
};

inline ::flatbuffers::Offset<Enum> CreateEnum(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    ::flatbuffers::Offset<::flatbuffers::String> name = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::EnumVal>>> values = 0,
    bool is_union = false,
    ::flatbuffers::Offset<reflection::Type> underlying_type = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0,
    ::flatbuffers::Offset<::flatbuffers::String> declaration_file = 0) {
  EnumBuilder builder_(_fbb);
  builder_.add_declaration_file(declaration_file);
  builder_.add_documentation(documentation);
  builder_.add_attributes(attributes);
  builder_.add_underlying_type(underlying_type);
  builder_.add_values(values);
  builder_.add_name(name);
  builder_.add_is_union(is_union);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<Enum> CreateEnumDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    const char *name = nullptr,
    std::vector<::flatbuffers::Offset<reflection::EnumVal>> *values = nullptr,
    bool is_union = false,
    ::flatbuffers::Offset<reflection::Type> underlying_type = 0,
    std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
    const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr,
    const char *declaration_file = nullptr) {
  auto name__ = name ? _fbb.CreateString(name) : 0;
  auto values__ = values ? _fbb.CreateVectorOfSortedTables<reflection::EnumVal>(values) : 0;
  auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
  auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
  auto declaration_file__ = declaration_file ? _fbb.CreateString(declaration_file) : 0;
  return reflection::CreateEnum(
      _fbb,
      name__,
      values__,
      is_union,
      underlying_type,
      attributes__,
      documentation__,
      declaration_file__);
}

struct Field FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef FieldBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_NAME = 4,
    VT_TYPE = 6,
    VT_ID = 8,
    VT_OFFSET = 10,
    VT_DEFAULT_INTEGER = 12,
    VT_DEFAULT_REAL = 14,
    VT_DEPRECATED = 16,
    VT_REQUIRED = 18,
    VT_KEY = 20,
    VT_ATTRIBUTES = 22,
    VT_DOCUMENTATION = 24,
    VT_OPTIONAL = 26,
    VT_PADDING = 28,
    VT_OFFSET64 = 30
  };
  const ::flatbuffers::String *name() const {
    return GetPointer<const ::flatbuffers::String *>(VT_NAME);
  }
  bool KeyCompareLessThan(const Field * const o) const {
    return *name() < *o->name();
  }
  int KeyCompareWithValue(const char *_name) const {
    return strcmp(name()->c_str(), _name);
  }
  const reflection::Type *type() const {
    return GetPointer<const reflection::Type *>(VT_TYPE);
  }
  uint16_t id() const {
    return GetField<uint16_t>(VT_ID, 0);
  }
  uint16_t offset() const {
    return GetField<uint16_t>(VT_OFFSET, 0);
  }
  int64_t default_integer() const {
    return GetField<int64_t>(VT_DEFAULT_INTEGER, 0);
  }
  double default_real() const {
    return GetField<double>(VT_DEFAULT_REAL, 0.0);
  }
  bool deprecated() const {
    return GetField<uint8_t>(VT_DEPRECATED, 0) != 0;
  }
  bool required() const {
    return GetField<uint8_t>(VT_REQUIRED, 0) != 0;
  }
  bool key() const {
    return GetField<uint8_t>(VT_KEY, 0) != 0;
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *>(VT_DOCUMENTATION);
  }
  bool optional() const {
    return GetField<uint8_t>(VT_OPTIONAL, 0) != 0;
  }
  /// Number of padding octets to always add after this field. Structs only.
  uint16_t padding() const {
    return GetField<uint16_t>(VT_PADDING, 0);
  }
  /// If the field uses 64-bit offsets.
  bool offset64() const {
    return GetField<uint8_t>(VT_OFFSET64, 0) != 0;
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_NAME) &&
           verifier.VerifyString(name()) &&
           VerifyOffsetRequired(verifier, VT_TYPE) &&
           verifier.VerifyTable(type()) &&
           VerifyField<uint16_t>(verifier, VT_ID, 2) &&
           VerifyField<uint16_t>(verifier, VT_OFFSET, 2) &&
           VerifyField<int64_t>(verifier, VT_DEFAULT_INTEGER, 8) &&
           VerifyField<double>(verifier, VT_DEFAULT_REAL, 8) &&
           VerifyField<uint8_t>(verifier, VT_DEPRECATED, 1) &&
           VerifyField<uint8_t>(verifier, VT_REQUIRED, 1) &&
           VerifyField<uint8_t>(verifier, VT_KEY, 1) &&
           VerifyOffset(verifier, VT_ATTRIBUTES) &&
           verifier.VerifyVector(attributes()) &&
           verifier.VerifyVectorOfTables(attributes()) &&
           VerifyOffset(verifier, VT_DOCUMENTATION) &&
           verifier.VerifyVector(documentation()) &&
           verifier.VerifyVectorOfStrings(documentation()) &&
           VerifyField<uint8_t>(verifier, VT_OPTIONAL, 1) &&
           VerifyField<uint16_t>(verifier, VT_PADDING, 2) &&
           VerifyField<uint8_t>(verifier, VT_OFFSET64, 1) &&
           verifier.EndTable();
  }
};

struct FieldBuilder {
  typedef Field Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
    fbb_.AddOffset(Field::VT_NAME, name);
  }
  void add_type(::flatbuffers::Offset<reflection::Type> type) {
    fbb_.AddOffset(Field::VT_TYPE, type);
  }
  void add_id(uint16_t id) {
    fbb_.AddElement<uint16_t>(Field::VT_ID, id, 0);
  }
  void add_offset(uint16_t offset) {
    fbb_.AddElement<uint16_t>(Field::VT_OFFSET, offset, 0);
  }
  void add_default_integer(int64_t default_integer) {
    fbb_.AddElement<int64_t>(Field::VT_DEFAULT_INTEGER, default_integer, 0);
  }
  void add_default_real(double default_real) {
    fbb_.AddElement<double>(Field::VT_DEFAULT_REAL, default_real, 0.0);
  }
  void add_deprecated(bool deprecated) {
    fbb_.AddElement<uint8_t>(Field::VT_DEPRECATED, static_cast<uint8_t>(deprecated), 0);
  }
  void add_required(bool required) {
    fbb_.AddElement<uint8_t>(Field::VT_REQUIRED, static_cast<uint8_t>(required), 0);
  }
  void add_key(bool key) {
    fbb_.AddElement<uint8_t>(Field::VT_KEY, static_cast<uint8_t>(key), 0);
  }
  void add_attributes(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes) {
    fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes);
  }
  void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
    fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation);
  }
  void add_optional(bool optional) {
    fbb_.AddElement<uint8_t>(Field::VT_OPTIONAL, static_cast<uint8_t>(optional), 0);
  }
  void add_padding(uint16_t padding) {
    fbb_.AddElement<uint16_t>(Field::VT_PADDING, padding, 0);
  }
  void add_offset64(bool offset64) {
    fbb_.AddElement<uint8_t>(Field::VT_OFFSET64, static_cast<uint8_t>(offset64), 0);
  }
  explicit FieldBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<Field> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<Field>(end);
    fbb_.Required(o, Field::VT_NAME);
    fbb_.Required(o, Field::VT_TYPE);
    return o;
  }
};

inline ::flatbuffers::Offset<Field> CreateField(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    ::flatbuffers::Offset<::flatbuffers::String> name = 0,
    ::flatbuffers::Offset<reflection::Type> type = 0,
    uint16_t id = 0,
    uint16_t offset = 0,
    int64_t default_integer = 0,
    double default_real = 0.0,
    bool deprecated = false,
    bool required = false,
    bool key = false,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0,
    bool optional = false,
    uint16_t padding = 0,
    bool offset64 = false) {
  FieldBuilder builder_(_fbb);
  builder_.add_default_real(default_real);
  builder_.add_default_integer(default_integer);
  builder_.add_documentation(documentation);
  builder_.add_attributes(attributes);
  builder_.add_type(type);
  builder_.add_name(name);
  builder_.add_padding(padding);
  builder_.add_offset(offset);
  builder_.add_id(id);
  builder_.add_offset64(offset64);
  builder_.add_optional(optional);
  builder_.add_key(key);
  builder_.add_required(required);
  builder_.add_deprecated(deprecated);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<Field> CreateFieldDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    const char *name = nullptr,
    ::flatbuffers::Offset<reflection::Type> type = 0,
    uint16_t id = 0,
    uint16_t offset = 0,
    int64_t default_integer = 0,
    double default_real = 0.0,
    bool deprecated = false,
    bool required = false,
    bool key = false,
    std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
    const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr,
    bool optional = false,
    uint16_t padding = 0,
    bool offset64 = false) {
  auto name__ = name ? _fbb.CreateString(name) : 0;
  auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
  auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
  return reflection::CreateField(
      _fbb,
      name__,
      type,
      id,
      offset,
      default_integer,
      default_real,
      deprecated,
      required,
      key,
      attributes__,
      documentation__,
      optional,
      padding,
      offset64);
}

struct Object FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef ObjectBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_NAME = 4,
    VT_FIELDS = 6,
    VT_IS_STRUCT = 8,
    VT_MINALIGN = 10,
    VT_BYTESIZE = 12,
    VT_ATTRIBUTES = 14,
    VT_DOCUMENTATION = 16,
    VT_DECLARATION_FILE = 18
  };
  const ::flatbuffers::String *name() const {
    return GetPointer<const ::flatbuffers::String *>(VT_NAME);
  }
  bool KeyCompareLessThan(const Object * const o) const {
    return *name() < *o->name();
  }
  int KeyCompareWithValue(const char *_name) const {
    return strcmp(name()->c_str(), _name);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::Field>> *fields() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::Field>> *>(VT_FIELDS);
  }
  bool is_struct() const {
    return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0;
  }
  int32_t minalign() const {
    return GetField<int32_t>(VT_MINALIGN, 0);
  }
  int32_t bytesize() const {
    return GetField<int32_t>(VT_BYTESIZE, 0);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *>(VT_DOCUMENTATION);
  }
  /// File that this Object is declared in.
  const ::flatbuffers::String *declaration_file() const {
    return GetPointer<const ::flatbuffers::String *>(VT_DECLARATION_FILE);
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_NAME) &&
           verifier.VerifyString(name()) &&
           VerifyOffsetRequired(verifier, VT_FIELDS) &&
           verifier.VerifyVector(fields()) &&
           verifier.VerifyVectorOfTables(fields()) &&
           VerifyField<uint8_t>(verifier, VT_IS_STRUCT, 1) &&
           VerifyField<int32_t>(verifier, VT_MINALIGN, 4) &&
           VerifyField<int32_t>(verifier, VT_BYTESIZE, 4) &&
           VerifyOffset(verifier, VT_ATTRIBUTES) &&
           verifier.VerifyVector(attributes()) &&
           verifier.VerifyVectorOfTables(attributes()) &&
           VerifyOffset(verifier, VT_DOCUMENTATION) &&
           verifier.VerifyVector(documentation()) &&
           verifier.VerifyVectorOfStrings(documentation()) &&
           VerifyOffset(verifier, VT_DECLARATION_FILE) &&
           verifier.VerifyString(declaration_file()) &&
           verifier.EndTable();
  }
};

struct ObjectBuilder {
  typedef Object Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
    fbb_.AddOffset(Object::VT_NAME, name);
  }
  void add_fields(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::Field>>> fields) {
    fbb_.AddOffset(Object::VT_FIELDS, fields);
  }
  void add_is_struct(bool is_struct) {
    fbb_.AddElement<uint8_t>(Object::VT_IS_STRUCT, static_cast<uint8_t>(is_struct), 0);
  }
  void add_minalign(int32_t minalign) {
    fbb_.AddElement<int32_t>(Object::VT_MINALIGN, minalign, 0);
  }
  void add_bytesize(int32_t bytesize) {
    fbb_.AddElement<int32_t>(Object::VT_BYTESIZE, bytesize, 0);
  }
  void add_attributes(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes) {
    fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes);
  }
  void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
    fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation);
  }
  void add_declaration_file(::flatbuffers::Offset<::flatbuffers::String> declaration_file) {
    fbb_.AddOffset(Object::VT_DECLARATION_FILE, declaration_file);
  }
  explicit ObjectBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<Object> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<Object>(end);
    fbb_.Required(o, Object::VT_NAME);
    fbb_.Required(o, Object::VT_FIELDS);
    return o;
  }
};

inline ::flatbuffers::Offset<Object> CreateObject(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    ::flatbuffers::Offset<::flatbuffers::String> name = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::Field>>> fields = 0,
    bool is_struct = false,
    int32_t minalign = 0,
    int32_t bytesize = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0,
    ::flatbuffers::Offset<::flatbuffers::String> declaration_file = 0) {
  ObjectBuilder builder_(_fbb);
  builder_.add_declaration_file(declaration_file);
  builder_.add_documentation(documentation);
  builder_.add_attributes(attributes);
  builder_.add_bytesize(bytesize);
  builder_.add_minalign(minalign);
  builder_.add_fields(fields);
  builder_.add_name(name);
  builder_.add_is_struct(is_struct);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<Object> CreateObjectDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    const char *name = nullptr,
    std::vector<::flatbuffers::Offset<reflection::Field>> *fields = nullptr,
    bool is_struct = false,
    int32_t minalign = 0,
    int32_t bytesize = 0,
    std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
    const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr,
    const char *declaration_file = nullptr) {
  auto name__ = name ? _fbb.CreateString(name) : 0;
  auto fields__ = fields ? _fbb.CreateVectorOfSortedTables<reflection::Field>(fields) : 0;
  auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
  auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
  auto declaration_file__ = declaration_file ? _fbb.CreateString(declaration_file) : 0;
  return reflection::CreateObject(
      _fbb,
      name__,
      fields__,
      is_struct,
      minalign,
      bytesize,
      attributes__,
      documentation__,
      declaration_file__);
}

struct RPCCall FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef RPCCallBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_NAME = 4,
    VT_REQUEST = 6,
    VT_RESPONSE = 8,
    VT_ATTRIBUTES = 10,
    VT_DOCUMENTATION = 12
  };
  const ::flatbuffers::String *name() const {
    return GetPointer<const ::flatbuffers::String *>(VT_NAME);
  }
  bool KeyCompareLessThan(const RPCCall * const o) const {
    return *name() < *o->name();
  }
  int KeyCompareWithValue(const char *_name) const {
    return strcmp(name()->c_str(), _name);
  }
  const reflection::Object *request() const {
    return GetPointer<const reflection::Object *>(VT_REQUEST);
  }
  const reflection::Object *response() const {
    return GetPointer<const reflection::Object *>(VT_RESPONSE);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *>(VT_DOCUMENTATION);
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_NAME) &&
           verifier.VerifyString(name()) &&
           VerifyOffsetRequired(verifier, VT_REQUEST) &&
           verifier.VerifyTable(request()) &&
           VerifyOffsetRequired(verifier, VT_RESPONSE) &&
           verifier.VerifyTable(response()) &&
           VerifyOffset(verifier, VT_ATTRIBUTES) &&
           verifier.VerifyVector(attributes()) &&
           verifier.VerifyVectorOfTables(attributes()) &&
           VerifyOffset(verifier, VT_DOCUMENTATION) &&
           verifier.VerifyVector(documentation()) &&
           verifier.VerifyVectorOfStrings(documentation()) &&
           verifier.EndTable();
  }
};

struct RPCCallBuilder {
  typedef RPCCall Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
    fbb_.AddOffset(RPCCall::VT_NAME, name);
  }
  void add_request(::flatbuffers::Offset<reflection::Object> request) {
    fbb_.AddOffset(RPCCall::VT_REQUEST, request);
  }
  void add_response(::flatbuffers::Offset<reflection::Object> response) {
    fbb_.AddOffset(RPCCall::VT_RESPONSE, response);
  }
  void add_attributes(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes) {
    fbb_.AddOffset(RPCCall::VT_ATTRIBUTES, attributes);
  }
  void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
    fbb_.AddOffset(RPCCall::VT_DOCUMENTATION, documentation);
  }
  explicit RPCCallBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<RPCCall> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<RPCCall>(end);
    fbb_.Required(o, RPCCall::VT_NAME);
    fbb_.Required(o, RPCCall::VT_REQUEST);
    fbb_.Required(o, RPCCall::VT_RESPONSE);
    return o;
  }
};

inline ::flatbuffers::Offset<RPCCall> CreateRPCCall(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    ::flatbuffers::Offset<::flatbuffers::String> name = 0,
    ::flatbuffers::Offset<reflection::Object> request = 0,
    ::flatbuffers::Offset<reflection::Object> response = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0) {
  RPCCallBuilder builder_(_fbb);
  builder_.add_documentation(documentation);
  builder_.add_attributes(attributes);
  builder_.add_response(response);
  builder_.add_request(request);
  builder_.add_name(name);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<RPCCall> CreateRPCCallDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    const char *name = nullptr,
    ::flatbuffers::Offset<reflection::Object> request = 0,
    ::flatbuffers::Offset<reflection::Object> response = 0,
    std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
    const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr) {
  auto name__ = name ? _fbb.CreateString(name) : 0;
  auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
  auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
  return reflection::CreateRPCCall(
      _fbb,
      name__,
      request,
      response,
      attributes__,
      documentation__);
}

struct Service FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef ServiceBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_NAME = 4,
    VT_CALLS = 6,
    VT_ATTRIBUTES = 8,
    VT_DOCUMENTATION = 10,
    VT_DECLARATION_FILE = 12
  };
  const ::flatbuffers::String *name() const {
    return GetPointer<const ::flatbuffers::String *>(VT_NAME);
  }
  bool KeyCompareLessThan(const Service * const o) const {
    return *name() < *o->name();
  }
  int KeyCompareWithValue(const char *_name) const {
    return strcmp(name()->c_str(), _name);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::RPCCall>> *calls() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::RPCCall>> *>(VT_CALLS);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *>(VT_DOCUMENTATION);
  }
  /// File that this Service is declared in.
  const ::flatbuffers::String *declaration_file() const {
    return GetPointer<const ::flatbuffers::String *>(VT_DECLARATION_FILE);
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_NAME) &&
           verifier.VerifyString(name()) &&
           VerifyOffset(verifier, VT_CALLS) &&
           verifier.VerifyVector(calls()) &&
           verifier.VerifyVectorOfTables(calls()) &&
           VerifyOffset(verifier, VT_ATTRIBUTES) &&
           verifier.VerifyVector(attributes()) &&
           verifier.VerifyVectorOfTables(attributes()) &&
           VerifyOffset(verifier, VT_DOCUMENTATION) &&
           verifier.VerifyVector(documentation()) &&
           verifier.VerifyVectorOfStrings(documentation()) &&
           VerifyOffset(verifier, VT_DECLARATION_FILE) &&
           verifier.VerifyString(declaration_file()) &&
           verifier.EndTable();
  }
};

struct ServiceBuilder {
  typedef Service Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
    fbb_.AddOffset(Service::VT_NAME, name);
  }
  void add_calls(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::RPCCall>>> calls) {
    fbb_.AddOffset(Service::VT_CALLS, calls);
  }
  void add_attributes(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes) {
    fbb_.AddOffset(Service::VT_ATTRIBUTES, attributes);
  }
  void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
    fbb_.AddOffset(Service::VT_DOCUMENTATION, documentation);
  }
  void add_declaration_file(::flatbuffers::Offset<::flatbuffers::String> declaration_file) {
    fbb_.AddOffset(Service::VT_DECLARATION_FILE, declaration_file);
  }
  explicit ServiceBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<Service> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<Service>(end);
    fbb_.Required(o, Service::VT_NAME);
    return o;
  }
};

inline ::flatbuffers::Offset<Service> CreateService(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    ::flatbuffers::Offset<::flatbuffers::String> name = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::RPCCall>>> calls = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0,
    ::flatbuffers::Offset<::flatbuffers::String> declaration_file = 0) {
  ServiceBuilder builder_(_fbb);
  builder_.add_declaration_file(declaration_file);
  builder_.add_documentation(documentation);
  builder_.add_attributes(attributes);
  builder_.add_calls(calls);
  builder_.add_name(name);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<Service> CreateServiceDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    const char *name = nullptr,
    std::vector<::flatbuffers::Offset<reflection::RPCCall>> *calls = nullptr,
    std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
    const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr,
    const char *declaration_file = nullptr) {
  auto name__ = name ? _fbb.CreateString(name) : 0;
  auto calls__ = calls ? _fbb.CreateVectorOfSortedTables<reflection::RPCCall>(calls) : 0;
  auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
  auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
  auto declaration_file__ = declaration_file ? _fbb.CreateString(declaration_file) : 0;
  return reflection::CreateService(
      _fbb,
      name__,
      calls__,
      attributes__,
      documentation__,
      declaration_file__);
}

/// File specific information.
/// Symbols declared within a file may be recovered by iterating over all
/// symbols and examining the `declaration_file` field.
struct SchemaFile FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef SchemaFileBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_FILENAME = 4,
    VT_INCLUDED_FILENAMES = 6
  };
  /// Filename, relative to project root.
  const ::flatbuffers::String *filename() const {
    return GetPointer<const ::flatbuffers::String *>(VT_FILENAME);
  }
  bool KeyCompareLessThan(const SchemaFile * const o) const {
    return *filename() < *o->filename();
  }
  int KeyCompareWithValue(const char *_filename) const {
    return strcmp(filename()->c_str(), _filename);
  }
  /// Names of included files, relative to project root.
  const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *included_filenames() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *>(VT_INCLUDED_FILENAMES);
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_FILENAME) &&
           verifier.VerifyString(filename()) &&
           VerifyOffset(verifier, VT_INCLUDED_FILENAMES) &&
           verifier.VerifyVector(included_filenames()) &&
           verifier.VerifyVectorOfStrings(included_filenames()) &&
           verifier.EndTable();
  }
};

struct SchemaFileBuilder {
  typedef SchemaFile Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_filename(::flatbuffers::Offset<::flatbuffers::String> filename) {
    fbb_.AddOffset(SchemaFile::VT_FILENAME, filename);
  }
  void add_included_filenames(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> included_filenames) {
    fbb_.AddOffset(SchemaFile::VT_INCLUDED_FILENAMES, included_filenames);
  }
  explicit SchemaFileBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<SchemaFile> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<SchemaFile>(end);
    fbb_.Required(o, SchemaFile::VT_FILENAME);
    return o;
  }
};

inline ::flatbuffers::Offset<SchemaFile> CreateSchemaFile(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    ::flatbuffers::Offset<::flatbuffers::String> filename = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> included_filenames = 0) {
  SchemaFileBuilder builder_(_fbb);
  builder_.add_included_filenames(included_filenames);
  builder_.add_filename(filename);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<SchemaFile> CreateSchemaFileDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    const char *filename = nullptr,
    const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *included_filenames = nullptr) {
  auto filename__ = filename ? _fbb.CreateString(filename) : 0;
  auto included_filenames__ = included_filenames ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*included_filenames) : 0;
  return reflection::CreateSchemaFile(
      _fbb,
      filename__,
      included_filenames__);
}

struct Schema FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef SchemaBuilder Builder;
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_OBJECTS = 4,
    VT_ENUMS = 6,
    VT_FILE_IDENT = 8,
    VT_FILE_EXT = 10,
    VT_ROOT_TABLE = 12,
    VT_SERVICES = 14,
    VT_ADVANCED_FEATURES = 16,
    VT_FBS_FILES = 18
  };
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::Object>> *objects() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::Object>> *>(VT_OBJECTS);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::Enum>> *enums() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::Enum>> *>(VT_ENUMS);
  }
  const ::flatbuffers::String *file_ident() const {
    return GetPointer<const ::flatbuffers::String *>(VT_FILE_IDENT);
  }
  const ::flatbuffers::String *file_ext() const {
    return GetPointer<const ::flatbuffers::String *>(VT_FILE_EXT);
  }
  const reflection::Object *root_table() const {
    return GetPointer<const reflection::Object *>(VT_ROOT_TABLE);
  }
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::Service>> *services() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::Service>> *>(VT_SERVICES);
  }
  reflection::AdvancedFeatures advanced_features() const {
    return static_cast<reflection::AdvancedFeatures>(GetField<uint64_t>(VT_ADVANCED_FEATURES, 0));
  }
  /// All the files used in this compilation. Files are relative to where
  /// flatc was invoked.
  const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::SchemaFile>> *fbs_files() const {
    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::SchemaFile>> *>(VT_FBS_FILES);
  }
  bool Verify(::flatbuffers::Verifier &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyOffsetRequired(verifier, VT_OBJECTS) &&
           verifier.VerifyVector(objects()) &&
           verifier.VerifyVectorOfTables(objects()) &&
           VerifyOffsetRequired(verifier, VT_ENUMS) &&
           verifier.VerifyVector(enums()) &&
           verifier.VerifyVectorOfTables(enums()) &&
           VerifyOffset(verifier, VT_FILE_IDENT) &&
           verifier.VerifyString(file_ident()) &&
           VerifyOffset(verifier, VT_FILE_EXT) &&
           verifier.VerifyString(file_ext()) &&
           VerifyOffset(verifier, VT_ROOT_TABLE) &&
           verifier.VerifyTable(root_table()) &&
           VerifyOffset(verifier, VT_SERVICES) &&
           verifier.VerifyVector(services()) &&
           verifier.VerifyVectorOfTables(services()) &&
           VerifyField<uint64_t>(verifier, VT_ADVANCED_FEATURES, 8) &&
           VerifyOffset(verifier, VT_FBS_FILES) &&
           verifier.VerifyVector(fbs_files()) &&
           verifier.VerifyVectorOfTables(fbs_files()) &&
           verifier.EndTable();
  }
};

struct SchemaBuilder {
  typedef Schema Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_objects(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::Object>>> objects) {
    fbb_.AddOffset(Schema::VT_OBJECTS, objects);
  }
  void add_enums(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::Enum>>> enums) {
    fbb_.AddOffset(Schema::VT_ENUMS, enums);
  }
  void add_file_ident(::flatbuffers::Offset<::flatbuffers::String> file_ident) {
    fbb_.AddOffset(Schema::VT_FILE_IDENT, file_ident);
  }
  void add_file_ext(::flatbuffers::Offset<::flatbuffers::String> file_ext) {
    fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext);
  }
  void add_root_table(::flatbuffers::Offset<reflection::Object> root_table) {
    fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table);
  }
  void add_services(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::Service>>> services) {
    fbb_.AddOffset(Schema::VT_SERVICES, services);
  }
  void add_advanced_features(reflection::AdvancedFeatures advanced_features) {
    fbb_.AddElement<uint64_t>(Schema::VT_ADVANCED_FEATURES, static_cast<uint64_t>(advanced_features), 0);
  }
  void add_fbs_files(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::SchemaFile>>> fbs_files) {
    fbb_.AddOffset(Schema::VT_FBS_FILES, fbs_files);
  }
  explicit SchemaBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<Schema> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<Schema>(end);
    fbb_.Required(o, Schema::VT_OBJECTS);
    fbb_.Required(o, Schema::VT_ENUMS);
    return o;
  }
};

inline ::flatbuffers::Offset<Schema> CreateSchema(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::Object>>> objects = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::Enum>>> enums = 0,
    ::flatbuffers::Offset<::flatbuffers::String> file_ident = 0,
    ::flatbuffers::Offset<::flatbuffers::String> file_ext = 0,
    ::flatbuffers::Offset<reflection::Object> root_table = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::Service>>> services = 0,
    reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0),
    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::SchemaFile>>> fbs_files = 0) {
  SchemaBuilder builder_(_fbb);
  builder_.add_advanced_features(advanced_features);
  builder_.add_fbs_files(fbs_files);
  builder_.add_services(services);
  builder_.add_root_table(root_table);
  builder_.add_file_ext(file_ext);
  builder_.add_file_ident(file_ident);
  builder_.add_enums(enums);
  builder_.add_objects(objects);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<Schema> CreateSchemaDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    std::vector<::flatbuffers::Offset<reflection::Object>> *objects = nullptr,
    std::vector<::flatbuffers::Offset<reflection::Enum>> *enums = nullptr,
    const char *file_ident = nullptr,
    const char *file_ext = nullptr,
    ::flatbuffers::Offset<reflection::Object> root_table = 0,
    std::vector<::flatbuffers::Offset<reflection::Service>> *services = nullptr,
    reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0),
    std::vector<::flatbuffers::Offset<reflection::SchemaFile>> *fbs_files = nullptr) {
  auto objects__ = objects ? _fbb.CreateVectorOfSortedTables<reflection::Object>(objects) : 0;
  auto enums__ = enums ? _fbb.CreateVectorOfSortedTables<reflection::Enum>(enums) : 0;
  auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0;
  auto file_ext__ = file_ext ? _fbb.CreateString(file_ext) : 0;
  auto services__ = services ? _fbb.CreateVectorOfSortedTables<reflection::Service>(services) : 0;
  auto fbs_files__ = fbs_files ? _fbb.CreateVectorOfSortedTables<reflection::SchemaFile>(fbs_files) : 0;
  return reflection::CreateSchema(
      _fbb,
      objects__,
      enums__,
      file_ident__,
      file_ext__,
      root_table,
      services__,
      advanced_features,
      fbs_files__);
}

inline const reflection::Schema *GetSchema(const void *buf) {
  return ::flatbuffers::GetRoot<reflection::Schema>(buf);
}

inline const reflection::Schema *GetSizePrefixedSchema(const void *buf) {
  return ::flatbuffers::GetSizePrefixedRoot<reflection::Schema>(buf);
}

inline const char *SchemaIdentifier() {
  return "BFBS";
}

inline bool SchemaBufferHasIdentifier(const void *buf) {
  return ::flatbuffers::BufferHasIdentifier(
      buf, SchemaIdentifier());
}

inline bool SizePrefixedSchemaBufferHasIdentifier(const void *buf) {
  return ::flatbuffers::BufferHasIdentifier(
      buf, SchemaIdentifier(), true);
}

inline bool VerifySchemaBuffer(
    ::flatbuffers::Verifier &verifier) {
  return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());
}

inline bool VerifySizePrefixedSchemaBuffer(
    ::flatbuffers::Verifier &verifier) {
  return verifier.VerifySizePrefixedBuffer<reflection::Schema>(SchemaIdentifier());
}

inline const char *SchemaExtension() {
  return "bfbs";
}

inline void FinishSchemaBuffer(
    ::flatbuffers::FlatBufferBuilder &fbb,
    ::flatbuffers::Offset<reflection::Schema> root) {
  fbb.Finish(root, SchemaIdentifier());
}

inline void FinishSizePrefixedSchemaBuffer(
    ::flatbuffers::FlatBufferBuilder &fbb,
    ::flatbuffers::Offset<reflection::Schema> root) {
  fbb.FinishSizePrefixed(root, SchemaIdentifier());
}

}  // namespace reflection

#endif  // FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
