Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add advance feature indicators to reflection #6546

Merged
merged 8 commits into from
Apr 27, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/flatbuffers/idl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,8 @@ class Parser : public ParserState {
IDLOptions opts;
bool uses_flexbuffers_;

std::set<reflection::AdvancedFeature> advanced_features_;
CasperN marked this conversation as resolved.
Show resolved Hide resolved

private:
const char *source_;

Expand Down
56 changes: 52 additions & 4 deletions include/flatbuffers/reflection_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,40 @@ inline const char *EnumNameBaseType(BaseType e) {
return EnumNamesBaseType()[index];
}

enum AdvancedFeature {
AdvancedArrayFeatures = 0,
AdvancedUnionFeatures = 1,
OptionalScalars = 2,
DefaultVectorsAndStrings = 3
};

inline const AdvancedFeature (&EnumValuesAdvancedFeature())[4] {
static const AdvancedFeature values[] = {
AdvancedArrayFeatures,
AdvancedUnionFeatures,
OptionalScalars,
DefaultVectorsAndStrings
};
return values;
}

inline const char * const *EnumNamesAdvancedFeature() {
static const char * const names[5] = {
"AdvancedArrayFeatures",
"AdvancedUnionFeatures",
"OptionalScalars",
"DefaultVectorsAndStrings",
nullptr
};
return names;
}

inline const char *EnumNameAdvancedFeature(AdvancedFeature e) {
if (flatbuffers::IsOutRange(e, AdvancedArrayFeatures, DefaultVectorsAndStrings)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesAdvancedFeature()[index];
}

struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef TypeBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
Expand Down Expand Up @@ -1063,7 +1097,8 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_FILE_IDENT = 8,
VT_FILE_EXT = 10,
VT_ROOT_TABLE = 12,
VT_SERVICES = 14
VT_SERVICES = 14,
VT_ADVANCED_FEATURES = 16
};
const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *>(VT_OBJECTS);
Expand All @@ -1083,6 +1118,9 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *services() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *>(VT_SERVICES);
}
const flatbuffers::Vector<uint32_t> *advanced_features() const {
return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_ADVANCED_FEATURES);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffsetRequired(verifier, VT_OBJECTS) &&
Expand All @@ -1100,6 +1138,8 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyOffset(verifier, VT_SERVICES) &&
verifier.VerifyVector(services()) &&
verifier.VerifyVectorOfTables(services()) &&
VerifyOffset(verifier, VT_ADVANCED_FEATURES) &&
verifier.VerifyVector(advanced_features()) &&
verifier.EndTable();
}
};
Expand All @@ -1126,6 +1166,9 @@ struct SchemaBuilder {
void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services) {
fbb_.AddOffset(Schema::VT_SERVICES, services);
}
void add_advanced_features(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> advanced_features) {
fbb_.AddOffset(Schema::VT_ADVANCED_FEATURES, advanced_features);
}
explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
Expand All @@ -1146,8 +1189,10 @@ inline flatbuffers::Offset<Schema> CreateSchema(
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) {
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services = 0,
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> advanced_features = 0) {
SchemaBuilder builder_(_fbb);
builder_.add_advanced_features(advanced_features);
builder_.add_services(services);
builder_.add_root_table(root_table);
builder_.add_file_ext(file_ext);
Expand All @@ -1164,20 +1209,23 @@ inline flatbuffers::Offset<Schema> CreateSchemaDirect(
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) {
std::vector<flatbuffers::Offset<reflection::Service>> *services = nullptr,
const std::vector<uint32_t> *advanced_features = 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 advanced_features__ = advanced_features ? _fbb.CreateVector<uint32_t>(*advanced_features) : 0;
return reflection::CreateSchema(
_fbb,
objects__,
enums__,
file_ident__,
file_ext__,
root_table,
services__);
services__,
advanced_features__);
}

inline const reflection::Schema *GetSchema(const void *buf) {
Expand Down
9 changes: 9 additions & 0 deletions reflection/reflection.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,22 @@ table Service {
documentation:[string];
}

// New schema language features that are not supported by old code generators.
enum AdvancedFeature : uint {
CasperN marked this conversation as resolved.
Show resolved Hide resolved
AdvancedArrayFeatures,
AdvancedUnionFeatures,
OptionalScalars,
DefaultVectorsAndStrings,
}

table Schema {
objects:[Object] (required); // Sorted.
enums:[Enum] (required); // Sorted.
file_ident:string;
file_ext:string;
root_table:Object;
services:[Service]; // Sorted.
advanced_features:[AdvancedFeature];
CasperN marked this conversation as resolved.
Show resolved Hide resolved
}

root_type Schema;
Expand Down
Binary file modified samples/monster.bfbs
Binary file not shown.
42 changes: 32 additions & 10 deletions src/idl_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,10 +765,13 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
if (!struct_def.fixed && IsArray(type))
return Error("fixed-length array in table must be wrapped in struct");

if (IsArray(type) && !SupportsAdvancedArrayFeatures()) {
return Error(
"Arrays are not yet supported in all "
"the specified programming languages.");
if (IsArray(type)) {
advanced_features_.insert(reflection::AdvancedArrayFeatures);
if (!SupportsAdvancedArrayFeatures()) {
return Error(
"Arrays are not yet supported in all "
"the specified programming languages.");
}
}

FieldDef *typefield = nullptr;
Expand All @@ -778,6 +781,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
type.enum_def->underlying_type, &typefield));
} else if (IsVector(type) && type.element == BASE_TYPE_UNION) {
advanced_features_.insert(reflection::AdvancedUnionFeatures);
// Only cpp, js and ts supports the union vector feature so far.
if (!SupportsAdvancedUnionFeatures()) {
return Error(
Expand All @@ -802,11 +806,16 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
return Error(
"default values are not supported for struct fields, table fields, "
"or in structs.");
if ((IsString(type) || IsVector(type)) && field->value.constant != "0" &&
field->value.constant != "null" && !SupportsDefaultVectorsAndStrings())
return Error(
"Default values for strings and vectors are not supported in one of "
"the specified programming languages");
if (IsString(type) || IsVector(type)) {
advanced_features_.insert(reflection::DefaultVectorsAndStrings);
if (field->value.constant != "0" && field->value.constant != "null" &&
!SupportsDefaultVectorsAndStrings()) {
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" &&
field->value.constant != "[]") {
return Error("The only supported default for vectors is `[]`.");
Expand Down Expand Up @@ -891,6 +900,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
}

if (field->IsScalarOptional()) {
advanced_features_.insert(reflection::OptionalScalars);
if (type.enum_def && type.enum_def->Lookup("null")) {
FLATBUFFERS_ASSERT(IsInteger(type.base_type));
return Error(
Expand Down Expand Up @@ -3483,14 +3493,20 @@ void Parser::Serialize() {
service_offsets.push_back(offset);
(*it)->serialized_location = offset.o;
}
std::vector<uint32_t> advanced_features(
advanced_features_.begin(), advanced_features_.end()
);
Offset<Vector<uint32_t>> afts__ = builder_.CreateVector(advanced_features);
auto objs__ = builder_.CreateVectorOfSortedTables(&object_offsets);
auto enum__ = builder_.CreateVectorOfSortedTables(&enum_offsets);
auto fiid__ = builder_.CreateString(file_identifier_);
auto fext__ = builder_.CreateString(file_extension_);
auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets);
auto schema_offset = reflection::CreateSchema(
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__,
afts__
);
if (opts.size_prefixed) {
builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier());
} else {
Expand Down Expand Up @@ -3907,6 +3923,12 @@ bool Parser::Deserialize(const reflection::Schema *schema) {
}
}
}
if (schema->advanced_features()) {
for (auto it = schema->advanced_features()->begin();
it != schema->advanced_features()->end(); it++) {
advanced_features_.insert(static_cast<reflection::AdvancedFeature>(*it));
}
}

return true;
}
Expand Down
Binary file modified tests/arrays_test.bfbs
Binary file not shown.
Binary file modified tests/monster_test.bfbs
Binary file not shown.
Loading