[Swift] FlatBuffers createMonster method doesn't treat struct properly (#5992)

* [Swift] FlatBuffers createMonster method doesn't treat struct properly

This PR fixed a issue where a struct is not treated properly when use
create inside.

A example would be the pos inside Monster. The createMonster method
takes an Offset for pos. However, FlatBuffersBuilder.add(struct:)
doesn't really take Offset argument. That means we don't really add a
struct at all for Monster.

It will show up as the pos never set.

This doesn't show up in FlatBuffersMonsterWriterTests.swift because it
implements its own createMonster method, which happens do the dance
properly (i.e. first call create(struct) and then immediately call
add:).

This PR modified the `add(pos:)` interface such that it takes the
UnsafeMutableRawPointer directly, calling `create(struct:)` under the hood.

I can add unit tests once the direction of this PR approved.

* Fix object api pack method codegen.

* Add unit tests that uses Monster.createMonster method to serialize.

* Updated sample_binary.swift
This commit is contained in:
Liu Liu
2020-06-28 02:36:55 -07:00
committed by GitHub
parent 4995e15273
commit e810635eaa
5 changed files with 68 additions and 34 deletions

View File

@@ -485,7 +485,7 @@ class SwiftGenerator : public BaseGenerator {
void GenTableWriterFields(const FieldDef &field,
std::vector<std::string> *create_body,
std::vector<std::string> *create_header) {
std::string builder_string = ", _ fbb: inout FlatBufferBuilder) { fbb.add(";
std::string builder_string = ", _ fbb: inout FlatBufferBuilder) { ";
auto &create_func_body = *create_body;
auto &create_func_header = *create_header;
auto name = Name(field);
@@ -509,7 +509,7 @@ class SwiftGenerator : public BaseGenerator {
auto default_value = IsEnum(field.value.type) ? GenEnumDefaultValue(field)
: field.value.constant;
auto is_enum = IsEnum(field.value.type) ? ".rawValue" : "";
code_ += "{{VALUETYPE}}" + builder_string + "element: {{VALUENAME}}" +
code_ += "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{VALUENAME}}" +
is_enum +
", def: {{CONSTANT}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
create_func_header.push_back("" + name + ": " + type + " = " +
@@ -523,12 +523,22 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("VALUETYPE", "Bool");
code_.SetValue("CONSTANT", default_value);
code_ += "{{VALUETYPE}}" + builder_string +
"element: {{VALUENAME}}, def: {{CONSTANT}}, at: "
"fbb.add(element: {{VALUENAME}}, def: {{CONSTANT}}, at: "
"{{TABLEOFFSET}}.{{OFFSET}}.p) }";
create_func_header.push_back(name + ": " + type + " = " + default_value);
return;
}
if (IsStruct(field.value.type)) {
auto struct_type = "UnsafeMutableRawPointer?";
auto camel_case_name = "structOf" + MakeCamel(name, true);
create_func_header.push_back(camel_case_name + " " + name + ": " + struct_type + " = nil");
auto create_struct = "guard let {{VALUENAME}} = {{VALUENAME}} else { return }; fbb.create(struct: {{VALUENAME}}, type: {{VALUETYPE}}.self); ";
auto reader_type = "fbb.add(structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
code_ += struct_type + builder_string + create_struct + reader_type;
return;
}
auto offset_type = field.value.type.base_type == BASE_TYPE_STRING
? "Offset<String>"
: "Offset<UOffset>";
@@ -544,7 +554,7 @@ class SwiftGenerator : public BaseGenerator {
IsStruct(field.value.type) && field.value.type.struct_def->fixed
? "structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"
: "offset: {{VALUENAME}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
code_ += offset_type + builder_string + reader_type;
code_ += offset_type + builder_string + "fbb.add(" + reader_type;
}
void GenTableReaderFields(const FieldDef &field) {
@@ -869,16 +879,17 @@ class SwiftGenerator : public BaseGenerator {
case BASE_TYPE_STRUCT: {
if (field.value.type.struct_def &&
field.value.type.struct_def->fixed) {
std::string struct_builder =
type + ".pack(&builder, obj: &obj." + name + ")";
unpack_body.push_back("{{STRUCTNAME}}." + body + struct_builder +
builder);
// This is a Struct (IsStruct), not a table. We create UnsafeMutableRawPointer in this case.
std::string code;
GenerateStructArgs(*field.value.type.struct_def, &code, "", "", "$0", true);
code = code.substr(0, code.size() - 2);
code_ += "let __" + name + " = obj." + name + ".map { create" + field.value.type.struct_def->name + "(" + code + ") }";
} else {
unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
builder);
code_ += "let __" + name + " = " + type +
".pack(&builder, obj: &obj." + name + ")";
}
unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
builder);
break;
}
case BASE_TYPE_STRING: {