Made user-defined attributes available in the reflection data.
authorWouter van Oortmerssen <wvo@google.com>
Tue, 12 Apr 2016 00:36:56 +0000 (17:36 -0700)
committerWouter van Oortmerssen <wvo@google.com>
Tue, 12 Apr 2016 00:36:56 +0000 (17:36 -0700)
Tested: on Linux.

Bug: 27923233
Change-Id: Ic16675650e4a8e138c163f1e2131a3aad7008ada

include/flatbuffers/idl.h
include/flatbuffers/reflection_generated.h
reflection/reflection.fbs
src/idl_parser.cpp
tests/monster_test.bfbs
tests/namespace_test/namespace_test2_generated.h
tests/test.cpp

index fbc696f..e671c01 100644 (file)
@@ -18,7 +18,6 @@
 #define FLATBUFFERS_IDL_H_
 
 #include <map>
-#include <set>
 #include <stack>
 #include <memory>
 #include <functional>
@@ -113,6 +112,7 @@ inline size_t SizeOf(BaseType t) {
 
 struct StructDef;
 struct EnumDef;
+struct Parser;
 
 // Represents any type in the IDL, which is a combination of the BaseType
 // and additional information for vectors/structs_.
@@ -184,10 +184,8 @@ template<typename T> class SymbolTable {
     return it == dict.end() ? nullptr : it->second;
   }
 
- private:
-  std::map<std::string, T *> dict;      // quick lookup
-
  public:
+  std::map<std::string, T *> dict;      // quick lookup
   std::vector<T *> vec;  // Used to iterate in order of insertion
 };
 
@@ -208,6 +206,11 @@ struct Definition {
   Definition() : generated(false), defined_namespace(nullptr),
                  serialized_location(0), index(-1) {}
 
+  flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
+    reflection::KeyValue>>>
+      SerializeAttributes(FlatBufferBuilder *builder,
+                          const Parser &parser) const;
+
   std::string name;
   std::string file;
   std::vector<std::string> doc_comment;
@@ -223,8 +226,8 @@ struct Definition {
 struct FieldDef : public Definition {
   FieldDef() : deprecated(false), required(false), key(false), padding(0) {}
 
-  Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id)
-                                                                          const;
+  Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
+                                      const Parser &parser) const;
 
   Value value;
   bool deprecated; // Field is allowed to be present in old data, but can't be
@@ -250,7 +253,8 @@ struct StructDef : public Definition {
     if (fields.vec.size()) fields.vec.back()->padding = padding;
   }
 
-  Offset<reflection::Object> Serialize(FlatBufferBuilder *builder) const;
+  Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
+                                       const Parser &parser) const;
 
   SymbolTable<FieldDef> fields;
   bool fixed;       // If it's struct, not a table.
@@ -299,7 +303,8 @@ struct EnumDef : public Definition {
     return nullptr;
   }
 
-  Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder) const;
+  Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
+                                     const Parser &parser) const;
 
   SymbolTable<EnumVal> vals;
   bool is_union;
@@ -406,18 +411,18 @@ class Parser {
       anonymous_counter(0) {
     // Just in case none are declared:
     namespaces_.push_back(new Namespace());
-    known_attributes_.insert("deprecated");
-    known_attributes_.insert("required");
-    known_attributes_.insert("key");
-    known_attributes_.insert("hash");
-    known_attributes_.insert("id");
-    known_attributes_.insert("force_align");
-    known_attributes_.insert("bit_flags");
-    known_attributes_.insert("original_order");
-    known_attributes_.insert("nested_flatbuffer");
-    known_attributes_.insert("csharp_partial");
-    known_attributes_.insert("stream");
-    known_attributes_.insert("idempotent");
+    known_attributes_["deprecated"] = true;
+    known_attributes_["required"] = true;
+    known_attributes_["key"] = true;
+    known_attributes_["hash"] = true;
+    known_attributes_["id"] = true;
+    known_attributes_["force_align"] = true;
+    known_attributes_["bit_flags"] = true;
+    known_attributes_["original_order"] = true;
+    known_attributes_["nested_flatbuffer"] = true;
+    known_attributes_["csharp_partial"] = true;
+    known_attributes_["stream"] = true;
+    known_attributes_["idempotent"] = true;
   }
 
   ~Parser() {
@@ -528,6 +533,8 @@ private:
   std::map<std::string, bool> included_files_;
   std::map<std::string, std::set<std::string>> files_included_per_file_;
 
+  std::map<std::string, bool> known_attributes_;
+
   IDLOptions opts;
 
  private:
@@ -541,8 +548,6 @@ private:
 
   std::vector<std::pair<Value, FieldDef *>> field_stack_;
 
-  std::set<std::string> known_attributes_;
-
   int anonymous_counter;
 };
 
index 86023df..da11249 100644 (file)
@@ -5,14 +5,20 @@
 
 #include "flatbuffers/flatbuffers.h"
 
-
 namespace reflection {
 
 struct Type;
+
+struct KeyValue;
+
 struct EnumVal;
+
 struct Enum;
+
 struct Field;
+
 struct Object;
+
 struct Schema;
 
 enum BaseType {
@@ -32,7 +38,9 @@ enum BaseType {
   String = 13,
   Vector = 14,
   Obj = 15,
-  Union = 16
+  Union = 16,
+  MIN = None,
+  MAX = Union
 };
 
 inline const char **EnumNamesBaseType() {
@@ -40,17 +48,22 @@ inline const char **EnumNamesBaseType() {
   return names;
 }
 
-inline const char *EnumNameBaseType(BaseType e) { return EnumNamesBaseType()[e]; }
+inline const char *EnumNameBaseType(BaseType e) { return EnumNamesBaseType()[static_cast<int>(e)]; }
 
 struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  BaseType base_type() const { return static_cast<BaseType>(GetField<int8_t>(4, 0)); }
-  BaseType element() const { return static_cast<BaseType>(GetField<int8_t>(6, 0)); }
-  int32_t index() const { return GetField<int32_t>(8, -1); }
+  enum {
+    VT_BASE_TYPE = 4,
+    VT_ELEMENT = 6,
+    VT_INDEX = 8
+  };
+  BaseType base_type() const { return static_cast<BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0)); }
+  BaseType element() const { return static_cast<BaseType>(GetField<int8_t>(VT_ELEMENT, 0)); }
+  int32_t index() const { return GetField<int32_t>(VT_INDEX, -1); }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyField<int8_t>(verifier, 4 /* base_type */) &&
-           VerifyField<int8_t>(verifier, 6 /* element */) &&
-           VerifyField<int32_t>(verifier, 8 /* index */) &&
+           VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
+           VerifyField<int8_t>(verifier, VT_ELEMENT) &&
+           VerifyField<int32_t>(verifier, VT_INDEX) &&
            verifier.EndTable();
   }
 };
@@ -58,9 +71,9 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
 struct TypeBuilder {
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_base_type(BaseType base_type) { fbb_.AddElement<int8_t>(4, static_cast<int8_t>(base_type), 0); }
-  void add_element(BaseType element) { fbb_.AddElement<int8_t>(6, static_cast<int8_t>(element), 0); }
-  void add_index(int32_t index) { fbb_.AddElement<int32_t>(8, index, -1); }
+  void add_base_type(BaseType base_type) { fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0); }
+  void add_element(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); }
   TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
   TypeBuilder &operator=(const TypeBuilder &);
   flatbuffers::Offset<Type> Finish() {
@@ -80,18 +93,65 @@ inline flatbuffers::Offset<Type> CreateType(flatbuffers::FlatBufferBuilder &_fbb
   return builder_.Finish();
 }
 
+struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  enum {
+    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 *val) const { return strcmp(key()->c_str(), val); }
+  const flatbuffers::String *value() const { return GetPointer<const flatbuffers::String *>(VT_VALUE); }
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_KEY) &&
+           verifier.Verify(key()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) &&
+           verifier.Verify(value()) &&
+           verifier.EndTable();
+  }
+};
+
+struct KeyValueBuilder {
+  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); }
+  KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
+  KeyValueBuilder &operator=(const KeyValueBuilder &);
+  flatbuffers::Offset<KeyValue> Finish() {
+    auto o = flatbuffers::Offset<KeyValue>(fbb_.EndTable(start_, 2));
+    fbb_.Required(o, KeyValue::VT_KEY);  // 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();
+}
+
 struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(4); }
-  int64_t value() const { return GetField<int64_t>(6, 0); }
+  enum {
+    VT_NAME = 4,
+    VT_VALUE = 6,
+    VT_OBJECT = 8
+  };
+  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 val) const { return value() < val ? -1 : value() > val; }
-  const Object *object() const { return GetPointer<const Object *>(8); }
+  const Object *object() const { return GetPointer<const Object *>(VT_OBJECT); }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 4 /* name */) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
            verifier.Verify(name()) &&
-           VerifyField<int64_t>(verifier, 6 /* value */) &&
-           VerifyField<flatbuffers::uoffset_t>(verifier, 8 /* object */) &&
+           VerifyField<int64_t>(verifier, VT_VALUE) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_OBJECT) &&
            verifier.VerifyTable(object()) &&
            verifier.EndTable();
   }
@@ -100,14 +160,14 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
 struct EnumValBuilder {
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(4, name); }
-  void add_value(int64_t value) { fbb_.AddElement<int64_t>(6, value, 0); }
-  void add_object(flatbuffers::Offset<Object> object) { fbb_.AddOffset(8, object); }
+  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_object(flatbuffers::Offset<Object> object) { fbb_.AddOffset(EnumVal::VT_OBJECT, object); }
   EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
   EnumValBuilder &operator=(const EnumValBuilder &);
   flatbuffers::Offset<EnumVal> Finish() {
     auto o = flatbuffers::Offset<EnumVal>(fbb_.EndTable(start_, 3));
-    fbb_.Required(o, 4);  // name
+    fbb_.Required(o, EnumVal::VT_NAME);  // name
     return o;
   }
 };
@@ -124,22 +184,33 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(flatbuffers::FlatBufferBuilder
 }
 
 struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(4); }
+  enum {
+    VT_NAME = 4,
+    VT_VALUES = 6,
+    VT_IS_UNION = 8,
+    VT_UNDERLYING_TYPE = 10,
+    VT_ATTRIBUTES = 12
+  };
+  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 *val) const { return strcmp(name()->c_str(), val); }
-  const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *values() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *>(6); }
-  uint8_t is_union() const { return GetField<uint8_t>(8, 0); }
-  const Type *underlying_type() const { return GetPointer<const Type *>(10); }
+  const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *values() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *>(VT_VALUES); }
+  bool is_union() const { return GetField<uint8_t>(VT_IS_UNION, 0) != 0; }
+  const Type *underlying_type() const { return GetPointer<const Type *>(VT_UNDERLYING_TYPE); }
+  const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 4 /* name */) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
            verifier.Verify(name()) &&
-           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 6 /* values */) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_VALUES) &&
            verifier.Verify(values()) &&
            verifier.VerifyVectorOfTables(values()) &&
-           VerifyField<uint8_t>(verifier, 8 /* is_union */) &&
-           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 10 /* underlying_type */) &&
+           VerifyField<uint8_t>(verifier, VT_IS_UNION) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_UNDERLYING_TYPE) &&
            verifier.VerifyTable(underlying_type()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
+           verifier.Verify(attributes()) &&
+           verifier.VerifyVectorOfTables(attributes()) &&
            verifier.EndTable();
   }
 };
@@ -147,17 +218,18 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
 struct EnumBuilder {
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(4, name); }
-  void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values) { fbb_.AddOffset(6, values); }
-  void add_is_union(uint8_t is_union) { fbb_.AddElement<uint8_t>(8, is_union, 0); }
-  void add_underlying_type(flatbuffers::Offset<Type> underlying_type) { fbb_.AddOffset(10, underlying_type); }
+  void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Enum::VT_NAME, name); }
+  void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<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<Type> underlying_type) { fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type); }
+  void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes); }
   EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
   EnumBuilder &operator=(const EnumBuilder &);
   flatbuffers::Offset<Enum> Finish() {
-    auto o = flatbuffers::Offset<Enum>(fbb_.EndTable(start_, 4));
-    fbb_.Required(o, 4);  // name
-    fbb_.Required(o, 6);  // values
-    fbb_.Required(o, 10);  // underlying_type
+    auto o = flatbuffers::Offset<Enum>(fbb_.EndTable(start_, 5));
+    fbb_.Required(o, Enum::VT_NAME);  // name
+    fbb_.Required(o, Enum::VT_VALUES);  // values
+    fbb_.Required(o, Enum::VT_UNDERLYING_TYPE);  // underlying_type
     return o;
   }
 };
@@ -165,9 +237,11 @@ struct EnumBuilder {
 inline flatbuffers::Offset<Enum> CreateEnum(flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<flatbuffers::String> name = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values = 0,
-   uint8_t is_union = 0,
-   flatbuffers::Offset<Type> underlying_type = 0) {
+   bool is_union = false,
+   flatbuffers::Offset<Type> underlying_type = 0,
+   flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
   EnumBuilder builder_(_fbb);
+  builder_.add_attributes(attributes);
   builder_.add_underlying_type(underlying_type);
   builder_.add_values(values);
   builder_.add_name(name);
@@ -176,30 +250,46 @@ inline flatbuffers::Offset<Enum> CreateEnum(flatbuffers::FlatBufferBuilder &_fbb
 }
 
 struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(4); }
+  enum {
+    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
+  };
+  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 *val) const { return strcmp(name()->c_str(), val); }
-  const Type *type() const { return GetPointer<const Type *>(6); }
-  uint16_t id() const { return GetField<uint16_t>(8, 0); }
-  uint16_t offset() const { return GetField<uint16_t>(10, 0); }
-  int64_t default_integer() const { return GetField<int64_t>(12, 0); }
-  double default_real() const { return GetField<double>(14, 0.0); }
-  uint8_t deprecated() const { return GetField<uint8_t>(16, 0); }
-  uint8_t required() const { return GetField<uint8_t>(18, 0); }
-  uint8_t key() const { return GetField<uint8_t>(20, 0); }
+  const Type *type() const { return GetPointer<const 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<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 4 /* name */) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
            verifier.Verify(name()) &&
-           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 6 /* type */) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_TYPE) &&
            verifier.VerifyTable(type()) &&
-           VerifyField<uint16_t>(verifier, 8 /* id */) &&
-           VerifyField<uint16_t>(verifier, 10 /* offset */) &&
-           VerifyField<int64_t>(verifier, 12 /* default_integer */) &&
-           VerifyField<double>(verifier, 14 /* default_real */) &&
-           VerifyField<uint8_t>(verifier, 16 /* deprecated */) &&
-           VerifyField<uint8_t>(verifier, 18 /* required */) &&
-           VerifyField<uint8_t>(verifier, 20 /* key */) &&
+           VerifyField<uint16_t>(verifier, VT_ID) &&
+           VerifyField<uint16_t>(verifier, VT_OFFSET) &&
+           VerifyField<int64_t>(verifier, VT_DEFAULT_INTEGER) &&
+           VerifyField<double>(verifier, VT_DEFAULT_REAL) &&
+           VerifyField<uint8_t>(verifier, VT_DEPRECATED) &&
+           VerifyField<uint8_t>(verifier, VT_REQUIRED) &&
+           VerifyField<uint8_t>(verifier, VT_KEY) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
+           verifier.Verify(attributes()) &&
+           verifier.VerifyVectorOfTables(attributes()) &&
            verifier.EndTable();
   }
 };
@@ -207,21 +297,22 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
 struct FieldBuilder {
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(4, name); }
-  void add_type(flatbuffers::Offset<Type> type) { fbb_.AddOffset(6, type); }
-  void add_id(uint16_t id) { fbb_.AddElement<uint16_t>(8, id, 0); }
-  void add_offset(uint16_t offset) { fbb_.AddElement<uint16_t>(10, offset, 0); }
-  void add_default_integer(int64_t default_integer) { fbb_.AddElement<int64_t>(12, default_integer, 0); }
-  void add_default_real(double default_real) { fbb_.AddElement<double>(14, default_real, 0.0); }
-  void add_deprecated(uint8_t deprecated) { fbb_.AddElement<uint8_t>(16, deprecated, 0); }
-  void add_required(uint8_t required) { fbb_.AddElement<uint8_t>(18, required, 0); }
-  void add_key(uint8_t key) { fbb_.AddElement<uint8_t>(20, key, 0); }
+  void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Field::VT_NAME, name); }
+  void add_type(flatbuffers::Offset<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<KeyValue>>> attributes) { fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes); }
   FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
   FieldBuilder &operator=(const FieldBuilder &);
   flatbuffers::Offset<Field> Finish() {
-    auto o = flatbuffers::Offset<Field>(fbb_.EndTable(start_, 9));
-    fbb_.Required(o, 4);  // name
-    fbb_.Required(o, 6);  // type
+    auto o = flatbuffers::Offset<Field>(fbb_.EndTable(start_, 10));
+    fbb_.Required(o, Field::VT_NAME);  // name
+    fbb_.Required(o, Field::VT_TYPE);  // type
     return o;
   }
 };
@@ -233,12 +324,14 @@ inline flatbuffers::Offset<Field> CreateField(flatbuffers::FlatBufferBuilder &_f
    uint16_t offset = 0,
    int64_t default_integer = 0,
    double default_real = 0.0,
-   uint8_t deprecated = 0,
-   uint8_t required = 0,
-   uint8_t key = 0) {
+   bool deprecated = false,
+   bool required = false,
+   bool key = false,
+   flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
   FieldBuilder builder_(_fbb);
   builder_.add_default_real(default_real);
   builder_.add_default_integer(default_integer);
+  builder_.add_attributes(attributes);
   builder_.add_type(type);
   builder_.add_name(name);
   builder_.add_offset(offset);
@@ -250,23 +343,35 @@ inline flatbuffers::Offset<Field> CreateField(flatbuffers::FlatBufferBuilder &_f
 }
 
 struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(4); }
+  enum {
+    VT_NAME = 4,
+    VT_FIELDS = 6,
+    VT_IS_STRUCT = 8,
+    VT_MINALIGN = 10,
+    VT_BYTESIZE = 12,
+    VT_ATTRIBUTES = 14
+  };
+  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 *val) const { return strcmp(name()->c_str(), val); }
-  const flatbuffers::Vector<flatbuffers::Offset<Field>> *fields() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Field>> *>(6); }
-  uint8_t is_struct() const { return GetField<uint8_t>(8, 0); }
-  int32_t minalign() const { return GetField<int32_t>(10, 0); }
-  int32_t bytesize() const { return GetField<int32_t>(12, 0); }
+  const flatbuffers::Vector<flatbuffers::Offset<Field>> *fields() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<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<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 4 /* name */) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
            verifier.Verify(name()) &&
-           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 6 /* fields */) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_FIELDS) &&
            verifier.Verify(fields()) &&
            verifier.VerifyVectorOfTables(fields()) &&
-           VerifyField<uint8_t>(verifier, 8 /* is_struct */) &&
-           VerifyField<int32_t>(verifier, 10 /* minalign */) &&
-           VerifyField<int32_t>(verifier, 12 /* bytesize */) &&
+           VerifyField<uint8_t>(verifier, VT_IS_STRUCT) &&
+           VerifyField<int32_t>(verifier, VT_MINALIGN) &&
+           VerifyField<int32_t>(verifier, VT_BYTESIZE) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
+           verifier.Verify(attributes()) &&
+           verifier.VerifyVectorOfTables(attributes()) &&
            verifier.EndTable();
   }
 };
@@ -274,17 +379,18 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
 struct ObjectBuilder {
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(4, name); }
-  void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields) { fbb_.AddOffset(6, fields); }
-  void add_is_struct(uint8_t is_struct) { fbb_.AddElement<uint8_t>(8, is_struct, 0); }
-  void add_minalign(int32_t minalign) { fbb_.AddElement<int32_t>(10, minalign, 0); }
-  void add_bytesize(int32_t bytesize) { fbb_.AddElement<int32_t>(12, bytesize, 0); }
+  void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Object::VT_NAME, name); }
+  void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<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<KeyValue>>> attributes) { fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes); }
   ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
   ObjectBuilder &operator=(const ObjectBuilder &);
   flatbuffers::Offset<Object> Finish() {
-    auto o = flatbuffers::Offset<Object>(fbb_.EndTable(start_, 5));
-    fbb_.Required(o, 4);  // name
-    fbb_.Required(o, 6);  // fields
+    auto o = flatbuffers::Offset<Object>(fbb_.EndTable(start_, 6));
+    fbb_.Required(o, Object::VT_NAME);  // name
+    fbb_.Required(o, Object::VT_FIELDS);  // fields
     return o;
   }
 };
@@ -292,10 +398,12 @@ struct ObjectBuilder {
 inline flatbuffers::Offset<Object> CreateObject(flatbuffers::FlatBufferBuilder &_fbb,
    flatbuffers::Offset<flatbuffers::String> name = 0,
    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields = 0,
-   uint8_t is_struct = 0,
+   bool is_struct = false,
    int32_t minalign = 0,
-   int32_t bytesize = 0) {
+   int32_t bytesize = 0,
+   flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
   ObjectBuilder builder_(_fbb);
+  builder_.add_attributes(attributes);
   builder_.add_bytesize(bytesize);
   builder_.add_minalign(minalign);
   builder_.add_fields(fields);
@@ -305,24 +413,31 @@ inline flatbuffers::Offset<Object> CreateObject(flatbuffers::FlatBufferBuilder &
 }
 
 struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(4); }
-  const flatbuffers::Vector<flatbuffers::Offset<Enum>> *enums() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Enum>> *>(6); }
-  const flatbuffers::String *file_ident() const { return GetPointer<const flatbuffers::String *>(8); }
-  const flatbuffers::String *file_ext() const { return GetPointer<const flatbuffers::String *>(10); }
-  const Object *root_table() const { return GetPointer<const Object *>(12); }
+  enum {
+    VT_OBJECTS = 4,
+    VT_ENUMS = 6,
+    VT_FILE_IDENT = 8,
+    VT_FILE_EXT = 10,
+    VT_ROOT_TABLE = 12
+  };
+  const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(VT_OBJECTS); }
+  const flatbuffers::Vector<flatbuffers::Offset<Enum>> *enums() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<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 Object *root_table() const { return GetPointer<const Object *>(VT_ROOT_TABLE); }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 4 /* objects */) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_OBJECTS) &&
            verifier.Verify(objects()) &&
            verifier.VerifyVectorOfTables(objects()) &&
-           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 6 /* enums */) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_ENUMS) &&
            verifier.Verify(enums()) &&
            verifier.VerifyVectorOfTables(enums()) &&
-           VerifyField<flatbuffers::uoffset_t>(verifier, 8 /* file_ident */) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_FILE_IDENT) &&
            verifier.Verify(file_ident()) &&
-           VerifyField<flatbuffers::uoffset_t>(verifier, 10 /* file_ext */) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_FILE_EXT) &&
            verifier.Verify(file_ext()) &&
-           VerifyField<flatbuffers::uoffset_t>(verifier, 12 /* root_table */) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_ROOT_TABLE) &&
            verifier.VerifyTable(root_table()) &&
            verifier.EndTable();
   }
@@ -331,17 +446,17 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
 struct SchemaBuilder {
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects) { fbb_.AddOffset(4, objects); }
-  void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums) { fbb_.AddOffset(6, enums); }
-  void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) { fbb_.AddOffset(8, file_ident); }
-  void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext) { fbb_.AddOffset(10, file_ext); }
-  void add_root_table(flatbuffers::Offset<Object> root_table) { fbb_.AddOffset(12, root_table); }
+  void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects) { fbb_.AddOffset(Schema::VT_OBJECTS, objects); }
+  void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<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<Object> root_table) { fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table); }
   SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
   SchemaBuilder &operator=(const SchemaBuilder &);
   flatbuffers::Offset<Schema> Finish() {
     auto o = flatbuffers::Offset<Schema>(fbb_.EndTable(start_, 5));
-    fbb_.Required(o, 4);  // objects
-    fbb_.Required(o, 6);  // enums
+    fbb_.Required(o, Schema::VT_OBJECTS);  // objects
+    fbb_.Required(o, Schema::VT_ENUMS);  // enums
     return o;
   }
 };
index 77305f6..57f234c 100644 (file)
@@ -34,6 +34,11 @@ table Type {
                      // from an enum, index into "enums" below.
 }
 
+table KeyValue {
+    key:string (required, key);
+    value:string;
+}
+
 table EnumVal {
     name:string (required);
     value:long (key);
@@ -45,6 +50,7 @@ table Enum {
     values:[EnumVal] (required);  // In order of their values.
     is_union:bool = false;
     underlying_type:Type (required);
+    attributes:[KeyValue];
 }
 
 table Field {
@@ -57,6 +63,7 @@ table Field {
     deprecated:bool = false;
     required:bool = false;
     key:bool = false;
+    attributes:[KeyValue];
 }
 
 table Object {  // Used for both tables and structs.
@@ -65,6 +72,7 @@ table Object {  // Used for both tables and structs.
     is_struct:bool = false;
     minalign:int;
     bytesize:int;  // For structs.
+    attributes:[KeyValue];
 }
 
 table Schema {
index 1df44ad..e0eaa5d 100644 (file)
@@ -1784,7 +1784,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
       auto name = attribute_;
       EXPECT(kTokenStringConstant);
       EXPECT(';');
-      known_attributes_.insert(name);
+      known_attributes_[name] = false;
     } else if (token_ == kTokenService) {
       ECHECK(ParseService());
     } else {
@@ -1853,13 +1853,13 @@ void Parser::Serialize() {
   AssignIndices(enums_.vec);
   std::vector<Offset<reflection::Object>> object_offsets;
   for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) {
-    auto offset = (*it)->Serialize(&builder_);
+    auto offset = (*it)->Serialize(&builder_, *this);
     object_offsets.push_back(offset);
     (*it)->serialized_location = offset.o;
   }
   std::vector<Offset<reflection::Enum>> enum_offsets;
   for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) {
-    auto offset = (*it)->Serialize(&builder_);
+    auto offset = (*it)->Serialize(&builder_, *this);
     enum_offsets.push_back(offset);
     (*it)->serialized_location = offset.o;
   }
@@ -1875,13 +1875,13 @@ void Parser::Serialize() {
   builder_.Finish(schema_offset, reflection::SchemaIdentifier());
 }
 
-Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder)
-                                                                         const {
+Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder,
+                                                const Parser &parser) const {
   std::vector<Offset<reflection::Field>> field_offsets;
   for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) {
     field_offsets.push_back(
       (*it)->Serialize(builder,
-                       static_cast<uint16_t>(it - fields.vec.begin())));
+                       static_cast<uint16_t>(it - fields.vec.begin()), parser));
   }
   return reflection::CreateObject(*builder,
                                   builder->CreateString(name),
@@ -1889,11 +1889,13 @@ Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder)
                                     &field_offsets),
                                   fixed,
                                   static_cast<int>(minalign),
-                                  static_cast<int>(bytesize));
+                                  static_cast<int>(bytesize),
+                                  SerializeAttributes(builder, parser));
 }
 
 Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
-                                              uint16_t id) const {
+                                              uint16_t id,
+                                              const Parser &parser) const {
   return reflection::CreateField(*builder,
                                  builder->CreateString(name),
                                  value.type.Serialize(builder),
@@ -1907,12 +1909,14 @@ Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
                                    : 0.0,
                                  deprecated,
                                  required,
-                                 key);
+                                 key,
+                                 SerializeAttributes(builder, parser));
   // TODO: value.constant is almost always "0", we could save quite a bit of
   // space by sharing it. Same for common values of value.type.
 }
 
-Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder) const {
+Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder,
+                                            const Parser &parser) const {
   std::vector<Offset<reflection::EnumVal>> enumval_offsets;
   for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) {
     enumval_offsets.push_back((*it)->Serialize(builder));
@@ -1921,7 +1925,8 @@ Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder) const {
                                 builder->CreateString(name),
                                 builder->CreateVector(enumval_offsets),
                                 is_union,
-                                underlying_type.Serialize(builder));
+                                underlying_type.Serialize(builder),
+                                SerializeAttributes(builder, parser));
 }
 
 Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const
@@ -1942,4 +1947,26 @@ Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
                                              (enum_def ? enum_def->index : -1));
 }
 
+flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
+  reflection::KeyValue>>>
+    Definition::SerializeAttributes(FlatBufferBuilder *builder,
+                                    const Parser &parser) const {
+  std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs;
+  for (auto kv : attributes.dict) {
+    auto it = parser.known_attributes_.find(kv.first);
+    assert(it != parser.known_attributes_.end());
+    if (!it->second) {  // Custom attribute.
+      attrs.push_back(
+          reflection::CreateKeyValue(*builder, builder->CreateString(kv.first),
+                                     builder->CreateString(
+                                         kv.second->constant)));
+    }
+  }
+  if (attrs.size()) {
+    return builder->CreateVectorOfSortedTables(&attrs);
+  } else {
+    return 0;
+  }
+}
+
 }  // namespace flatbuffers
index e5f51fa..db12328 100644 (file)
Binary files a/tests/monster_test.bfbs and b/tests/monster_test.bfbs differ
index 1831454..d0cc5fa 100644 (file)
@@ -8,16 +8,6 @@
 #include "namespace_test1_generated.h"
 
 namespace NamespaceA {
-namespace NamespaceB {
-
-struct TableInNestedNS;
-
-struct StructInNestedNS;
-
-}  // namespace NamespaceB
-}  // namespace NamespaceA
-
-namespace NamespaceA {
 
 struct TableInFirstNS;
 
index 42c7647..4c3aa54 100644 (file)
@@ -322,6 +322,10 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
   TEST_EQ_STR(hp_field.name()->c_str(), "hp");
   TEST_EQ(hp_field.id(), 2);
   TEST_EQ(hp_field.type()->base_type(), reflection::Short);
+  auto friendly_field_ptr = fields->LookupByKey("friendly");
+  TEST_NOTNULL(friendly_field_ptr);
+  TEST_NOTNULL(friendly_field_ptr->attributes());
+  TEST_NOTNULL(friendly_field_ptr->attributes()->LookupByKey("priority"));
 
   // Now use it to dynamically access a buffer.
   auto &root = *flatbuffers::GetAnyRoot(flatbuf);