Add advance feature indicators to reflection (#6546)

* Add advance feature indicators to reflection

* deserialize too

* model advanced features as bitflags

* use uint64_t instead of AdvancedFeatures

* git clang format

* initialize advanced_features_

* remove whitespace

Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
Casper
2021-04-27 10:10:59 -04:00
committed by GitHub
parent c87179e73e
commit 16836ff95a
5 changed files with 88 additions and 15 deletions

View File

@@ -780,6 +780,7 @@ class Parser : public ParserState {
root_struct_def_(nullptr), root_struct_def_(nullptr),
opts(options), opts(options),
uses_flexbuffers_(false), uses_flexbuffers_(false),
advanced_features_(0),
source_(nullptr), source_(nullptr),
anonymous_counter_(0), anonymous_counter_(0),
parse_depth_counter_(0) { parse_depth_counter_(0) {
@@ -1011,6 +1012,8 @@ class Parser : public ParserState {
IDLOptions opts; IDLOptions opts;
bool uses_flexbuffers_; bool uses_flexbuffers_;
uint64_t advanced_features_;
private: private:
const char *source_; const char *source_;

View File

@@ -114,6 +114,44 @@ inline const char *EnumNameBaseType(BaseType e) {
return EnumNamesBaseType()[index]; return EnumNamesBaseType()[index];
} }
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 { struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef TypeBuilder Builder; typedef TypeBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
@@ -1063,7 +1101,8 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_FILE_IDENT = 8, VT_FILE_IDENT = 8,
VT_FILE_EXT = 10, VT_FILE_EXT = 10,
VT_ROOT_TABLE = 12, VT_ROOT_TABLE = 12,
VT_SERVICES = 14 VT_SERVICES = 14,
VT_ADVANCED_FEATURES = 16
}; };
const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects() const { const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *>(VT_OBJECTS); return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *>(VT_OBJECTS);
@@ -1083,6 +1122,9 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *services() const { const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *services() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *>(VT_SERVICES); 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));
}
bool Verify(flatbuffers::Verifier &verifier) const { bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) && return VerifyTableStart(verifier) &&
VerifyOffsetRequired(verifier, VT_OBJECTS) && VerifyOffsetRequired(verifier, VT_OBJECTS) &&
@@ -1100,6 +1142,7 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyOffset(verifier, VT_SERVICES) && VerifyOffset(verifier, VT_SERVICES) &&
verifier.VerifyVector(services()) && verifier.VerifyVector(services()) &&
verifier.VerifyVectorOfTables(services()) && verifier.VerifyVectorOfTables(services()) &&
VerifyField<uint64_t>(verifier, VT_ADVANCED_FEATURES) &&
verifier.EndTable(); verifier.EndTable();
} }
}; };
@@ -1126,6 +1169,9 @@ struct SchemaBuilder {
void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services) { void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services) {
fbb_.AddOffset(Schema::VT_SERVICES, 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);
}
explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb) explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) { : fbb_(_fbb) {
start_ = fbb_.StartTable(); start_ = fbb_.StartTable();
@@ -1146,8 +1192,10 @@ inline flatbuffers::Offset<Schema> CreateSchema(
flatbuffers::Offset<flatbuffers::String> file_ident = 0, flatbuffers::Offset<flatbuffers::String> file_ident = 0,
flatbuffers::Offset<flatbuffers::String> file_ext = 0, flatbuffers::Offset<flatbuffers::String> file_ext = 0,
flatbuffers::Offset<reflection::Object> root_table = 0, flatbuffers::Offset<reflection::Object> root_table = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services = 0) { flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services = 0,
reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0)) {
SchemaBuilder builder_(_fbb); SchemaBuilder builder_(_fbb);
builder_.add_advanced_features(advanced_features);
builder_.add_services(services); builder_.add_services(services);
builder_.add_root_table(root_table); builder_.add_root_table(root_table);
builder_.add_file_ext(file_ext); builder_.add_file_ext(file_ext);
@@ -1164,7 +1212,8 @@ inline flatbuffers::Offset<Schema> CreateSchemaDirect(
const char *file_ident = nullptr, const char *file_ident = nullptr,
const char *file_ext = nullptr, const char *file_ext = nullptr,
flatbuffers::Offset<reflection::Object> root_table = 0, flatbuffers::Offset<reflection::Object> root_table = 0,
std::vector<flatbuffers::Offset<reflection::Service>> *services = nullptr) { std::vector<flatbuffers::Offset<reflection::Service>> *services = nullptr,
reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0)) {
auto objects__ = objects ? _fbb.CreateVectorOfSortedTables<reflection::Object>(objects) : 0; auto objects__ = objects ? _fbb.CreateVectorOfSortedTables<reflection::Object>(objects) : 0;
auto enums__ = enums ? _fbb.CreateVectorOfSortedTables<reflection::Enum>(enums) : 0; auto enums__ = enums ? _fbb.CreateVectorOfSortedTables<reflection::Enum>(enums) : 0;
auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0; auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0;
@@ -1177,7 +1226,8 @@ inline flatbuffers::Offset<Schema> CreateSchemaDirect(
file_ident__, file_ident__,
file_ext__, file_ext__,
root_table, root_table,
services__); services__,
advanced_features);
} }
inline const reflection::Schema *GetSchema(const void *buf) { inline const reflection::Schema *GetSchema(const void *buf) {

View File

@@ -102,6 +102,14 @@ table Service {
documentation:[string]; documentation:[string];
} }
// New schema language features that are not supported by old code generators.
enum AdvancedFeatures : ulong (bit_flags) {
AdvancedArrayFeatures,
AdvancedUnionFeatures,
OptionalScalars,
DefaultVectorsAndStrings,
}
table Schema { table Schema {
objects:[Object] (required); // Sorted. objects:[Object] (required); // Sorted.
enums:[Enum] (required); // Sorted. enums:[Enum] (required); // Sorted.
@@ -109,6 +117,7 @@ table Schema {
file_ext:string; file_ext:string;
root_table:Object; root_table:Object;
services:[Service]; // Sorted. services:[Service]; // Sorted.
advanced_features:AdvancedFeatures;
} }
root_type Schema; root_type Schema;

View File

@@ -765,10 +765,13 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
if (!struct_def.fixed && IsArray(type)) if (!struct_def.fixed && IsArray(type))
return Error("fixed-length array in table must be wrapped in struct"); return Error("fixed-length array in table must be wrapped in struct");
if (IsArray(type) && !SupportsAdvancedArrayFeatures()) { if (IsArray(type)) {
return Error( advanced_features_ |= reflection::AdvancedArrayFeatures;
"Arrays are not yet supported in all " if (!SupportsAdvancedArrayFeatures()) {
"the specified programming languages."); return Error(
"Arrays are not yet supported in all "
"the specified programming languages.");
}
} }
FieldDef *typefield = nullptr; FieldDef *typefield = nullptr;
@@ -778,6 +781,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
type.enum_def->underlying_type, &typefield)); type.enum_def->underlying_type, &typefield));
} else if (IsVector(type) && type.element == BASE_TYPE_UNION) { } else if (IsVector(type) && type.element == BASE_TYPE_UNION) {
advanced_features_ |= reflection::AdvancedUnionFeatures;
// Only cpp, js and ts supports the union vector feature so far. // Only cpp, js and ts supports the union vector feature so far.
if (!SupportsAdvancedUnionFeatures()) { if (!SupportsAdvancedUnionFeatures()) {
return Error( return Error(
@@ -802,11 +806,16 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
return Error( return Error(
"default values are not supported for struct fields, table fields, " "default values are not supported for struct fields, table fields, "
"or in structs."); "or in structs.");
if ((IsString(type) || IsVector(type)) && field->value.constant != "0" && if (IsString(type) || IsVector(type)) {
field->value.constant != "null" && !SupportsDefaultVectorsAndStrings()) advanced_features_ |= reflection::DefaultVectorsAndStrings;
return Error( if (field->value.constant != "0" && field->value.constant != "null" &&
"Default values for strings and vectors are not supported in one of " !SupportsDefaultVectorsAndStrings()) {
"the specified programming languages"); return Error(
"Default values for strings and vectors are not supported in one "
"of the specified programming languages");
}
}
if (IsVector(type) && field->value.constant != "0" && if (IsVector(type) && field->value.constant != "0" &&
field->value.constant != "[]") { field->value.constant != "[]") {
return Error("The only supported default for vectors is `[]`."); return Error("The only supported default for vectors is `[]`.");
@@ -891,6 +900,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
} }
if (field->IsScalarOptional()) { if (field->IsScalarOptional()) {
advanced_features_ |= reflection::OptionalScalars;
if (type.enum_def && type.enum_def->Lookup("null")) { if (type.enum_def && type.enum_def->Lookup("null")) {
FLATBUFFERS_ASSERT(IsInteger(type.base_type)); FLATBUFFERS_ASSERT(IsInteger(type.base_type));
return Error( return Error(
@@ -3498,7 +3508,8 @@ void Parser::Serialize() {
auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets); auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets);
auto schema_offset = reflection::CreateSchema( auto schema_offset = reflection::CreateSchema(
builder_, objs__, enum__, fiid__, fext__, builder_, objs__, enum__, fiid__, fext__,
(root_struct_def_ ? root_struct_def_->serialized_location : 0), serv__); (root_struct_def_ ? root_struct_def_->serialized_location : 0), serv__,
static_cast<reflection::AdvancedFeatures>(advanced_features_));
if (opts.size_prefixed) { if (opts.size_prefixed) {
builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier()); builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier());
} else { } else {
@@ -3915,7 +3926,7 @@ bool Parser::Deserialize(const reflection::Schema *schema) {
} }
} }
} }
advanced_features_ = schema->advanced_features();
return true; return true;
} }

Binary file not shown.