// 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 == 22 &&
              FLATBUFFERS_VERSION_MINOR == 10 &&
              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,
  MaxBaseType = 18
};

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

inline const char * const *EnumNamesBaseType() {
  static const char * const names[20] = {
    "None",
    "UType",
    "Bool",
    "Byte",
    "UByte",
    "Short",
    "UShort",
    "Int",
    "UInt",
    "Long",
    "ULong",
    "Float",
    "Double",
    "String",
    "Vector",
    "Obj",
    "Union",
    "Array",
    "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 *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 *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 *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
  };
  const flatbuffers::String *name() const {
    return GetPointer<const flatbuffers::String *>(VT_NAME);
  }
  bool KeyCompareLessThan(const Field *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);
  }
  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) &&
           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);
  }
  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) {
  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_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) {
  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);
}

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 *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 *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 *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 *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_
