mirror of
https://github.com/google/flatbuffers.git
synced 2026-07-01 23:03:57 +00:00
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:
@@ -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_;
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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.
Reference in New Issue
Block a user