// 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 == 25,
             "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);
  }
  template<typename StringType>
  int KeyCompareWithValue(const StringType& _key) const {
    if (key()->c_str() < _key) return -1;
    if (_key < key()->c_str()) return 1;
    return 0;
  }
  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);
  }
  template<typename StringType>
  int KeyCompareWithValue(const StringType& _name) const {
    if (name()->c_str() < _name) return -1;
    if (_name < name()->c_str()) return 1;
    return 0;
  }
  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);
  }
  template<typename StringType>
  int KeyCompareWithValue(const StringType& _name) const {
    if (name()->c_str() < _name) return -1;
    if (_name < name()->c_str()) return 1;
    return 0;
  }
  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);
  }
  template<typename StringType>
  int KeyCompareWithValue(const StringType& _name) const {
    if (name()->c_str() < _name) return -1;
    if (_name < name()->c_str()) return 1;
    return 0;
  }
  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);
  }
  template<typename StringType>
  int KeyCompareWithValue(const StringType& _name) const {
    if (name()->c_str() < _name) return -1;
    if (_name < name()->c_str()) return 1;
    return 0;
  }
  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);
  }
  template<typename StringType>
  int KeyCompareWithValue(const StringType& _name) const {
    if (name()->c_str() < _name) return -1;
    if (_name < name()->c_str()) return 1;
    return 0;
  }
  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);
  }
  template<typename StringType>
  int KeyCompareWithValue(const StringType& _filename) const {
    if (filename()->c_str() < _filename) return -1;
    if (_filename < filename()->c_str()) return 1;
    return 0;
  }
  /// 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_
