// 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 == 24 &&
              FLATBUFFERS_VERSION_MINOR == 3 &&
              FLATBUFFERS_VERSION_REVISION == 7,
             "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_
