Parsing from proto should keep field ID. (fixes #7645) (#7655)

* Parsing from proto should keep field ID. (fixes #7645)

* Fix failed tests

* Fix windows warning

* Improve attribute generation in proto to fbs

* Check if id is used twice. fix Some clang-format problems

* Test if fake id can solve the test problem

* Validate proto file in proto -> fbs generation.

* Fix error messages

* Ignore id in union

* Add keep proto id for legacy and check gap flag have been added. Reserved id will be checked.

* Add needed flags

* unit tests

* fix fromat problem. fix comments and error messages.

* clear

* More unit tests

* Fix windows build

* Fix include problems

* Fake commit to invoke rebuild

* Fix buzel build

* Fix some issues

* Fix comments, fix return value and sort for android NDK

* Fix return type

* Break down big function

* Place todo

---------

Co-authored-by: Derek Bailey <derekbailey@google.com>
This commit is contained in:
Saman
2023-02-02 03:17:35 +08:00
committed by GitHub
parent 08ebd202e2
commit f838017860
25 changed files with 1154 additions and 177 deletions

View File

@@ -920,8 +920,11 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
if (struct_def.fixed) {
if (IsIncompleteStruct(type) ||
(IsArray(type) && IsIncompleteStruct(type.VectorType()))) {
std::string type_name = IsArray(type) ? type.VectorType().struct_def->name : type.struct_def->name;
return Error(std::string("Incomplete type in struct is not allowed, type name: ") + type_name);
std::string type_name = IsArray(type) ? type.VectorType().struct_def->name
: type.struct_def->name;
return Error(
std::string("Incomplete type in struct is not allowed, type name: ") +
type_name);
}
auto valid = IsScalar(type.base_type) || IsStruct(type);
@@ -2289,12 +2292,8 @@ template<typename T> void EnumDef::ChangeEnumValue(EnumVal *ev, T new_value) {
}
namespace EnumHelper {
template<BaseType E> struct EnumValType {
typedef int64_t type;
};
template<> struct EnumValType<BASE_TYPE_ULONG> {
typedef uint64_t type;
};
template<BaseType E> struct EnumValType { typedef int64_t type; };
template<> struct EnumValType<BASE_TYPE_ULONG> { typedef uint64_t type; };
} // namespace EnumHelper
struct EnumValBuilder {
@@ -2698,6 +2697,7 @@ CheckedError Parser::ParseDecl(const char *filename) {
for (voffset_t i = 0; i < static_cast<voffset_t>(fields.size()); i++) {
auto &field = *fields[i];
const auto &id_str = field.attributes.Lookup("id")->constant;
// Metadata values have a dynamic type, they can be `float`, 'int', or
// 'string`.
// The FieldIndexToOffset(i) expects the voffset_t so `id` is limited by
@@ -2921,8 +2921,40 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
ECHECK(ParseProtoOption());
EXPECT(';');
} else if (IsIdent("reserved")) { // Skip these.
/**
* Reserved proto ids can be comma seperated (e.g. 1,2,4,5;)
* or range based (e.g. 9 to 11;)
* or combination of them (e.g. 1,2,9 to 11,4,5;)
* It will be ended by a semicolon.
*/
NEXT();
while (!Is(';')) { NEXT(); } // A variety of formats, just skip.
bool range = false;
voffset_t from = 0;
while (!Is(';')) {
if (token_ == kTokenIntegerConstant) {
voffset_t attribute = 0;
bool done = StringToNumber(attribute_.c_str(), &attribute);
if (!done)
return Error("Protobuf has non positive number in reserved ids");
if (range) {
for (voffset_t id = from + 1; id <= attribute; id++)
struct_def->reserved_ids.push_back(id);
range = false;
} else {
struct_def->reserved_ids.push_back(attribute);
}
from = attribute;
}
if (attribute_ == "to") range = true;
NEXT();
} // A variety of formats, just skip.
NEXT();
} else if (IsIdent("map")) {
ECHECK(ParseProtoMapField(struct_def));
@@ -2980,11 +3012,13 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
}
std::string name = attribute_;
EXPECT(kTokenIdentifier);
std::string proto_field_id;
if (!oneof) {
// Parse the field id. Since we're just translating schemas, not
// any kind of binary compatibility, we can safely ignore these, and
// assign our own.
EXPECT('=');
proto_field_id = attribute_;
EXPECT(kTokenIntegerConstant);
}
FieldDef *field = nullptr;
@@ -2995,6 +3029,11 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
}
if (!field) ECHECK(AddField(*struct_def, name, type, &field));
field->doc_comment = field_comment;
if (!proto_field_id.empty() || oneof) {
auto val = new Value();
val->constant = proto_field_id;
field->attributes.Add("id", val);
}
if (!IsScalar(type.base_type) && required) {
field->presence = FieldDef::kRequired;
}
@@ -3072,6 +3111,7 @@ CheckedError Parser::ParseProtoMapField(StructDef *struct_def) {
auto field_name = attribute_;
NEXT();
EXPECT('=');
std::string proto_field_id = attribute_;
EXPECT(kTokenIntegerConstant);
EXPECT(';');
@@ -3091,6 +3131,11 @@ CheckedError Parser::ParseProtoMapField(StructDef *struct_def) {
field_type.struct_def = entry_table;
FieldDef *field;
ECHECK(AddField(*struct_def, field_name, field_type, &field));
if (!proto_field_id.empty()) {
auto val = new Value();
val->constant = proto_field_id;
field->attributes.Add("id", val);
}
return NoError();
}