// 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 == 2 &&
              FLATBUFFERS_VERSION_MINOR == 0 &&
              FLATBUFFERS_VERSION_REVISION == 7,
             "Non-compatible flatbuffers version included");

namespace reflection {

struct Type;
struct TypeBuilder;

struct KeyValue;
struct KeyValueBuilder;

struct EnumVal;
struct EnumValBuilder;

struct Enum;
struct EnumBuilder;

struct Field;
struct FieldBuilder;

struct Object;
struct ObjectBuilder;

struct RPCCall;
struct RPCCallBuilder;

struct Service;
struct ServiceBuilder;

struct SchemaFile;
struct SchemaFileBuilder;

struct Schema;
struct SchemaBuilder;

enum BaseType {
  None = 0,
  UType = 1,
  Bool = 2,
  Byte = 3,
  UByte = 4,
  Short = 5,
  UShort = 6,
  Int = 7,
  UInt = 8,
  Long = 9,
  ULong = 10,
  Float = 11,
  Double = 12,
  String = 13,
  Vector = 14,
  Obj = 15,
  Union = 16,
  Array = 17,
  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
  };
  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);
  }
  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()) &&
           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);
  }
  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) {
  EnumValBuilder builder_(_fbb);
  builder_.add_value(value);
  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) {
  auto name__ = name ? _fbb.CreateString(name) : 0;
  auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
  return reflection::CreateEnumVal(
      _fbb,
      name__,
      value,
      union_type,
      documentation__);
}

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_
