Commit a4b2884e authored by mustiikhalil's avatar mustiikhalil Committed by Wouter van Oortmerssen

Added create function for swift (#5707)

Fixed the create functions and updated the test cases in swift

Removes unneeded code

Updated documentation
parent 04d80f25
...@@ -1699,16 +1699,15 @@ can serialize the monster itself: ...@@ -1699,16 +1699,15 @@ can serialize the monster itself:
</div> </div>
<div class="language-swift"> <div class="language-swift">
~~~{.swift} ~~~{.swift}
let start = Monster.startMonster(builder) let orc = Monster.createMonster(builder,
Monster.add(pos: pos, builder) offsetOfPos: pos,
Monster.add(hp: 300, builder) hp: 300,
Monster.add(name: name, builder) offsetOfName: name,
Monster.add(inventory: inventoryOffset, builder) vectorOfInventory: inventoryOffset,
Monster.add(color: .red, builder) color: .red,
Monster.add(weapons: weaponsOffset, builder) vectorOfWeapons: weaponsOffset,
Monster.add(equippedType: .weapon, builder) equippedType: .weapon,
Monster.add(equipped: axe, builder) offsetOfEquipped: axe)
var orc = Monster.endMonster(builder, start: start)
~~~ ~~~
</div> </div>
...@@ -1776,6 +1775,21 @@ a bit more flexibility. ...@@ -1776,6 +1775,21 @@ a bit more flexibility.
~~~ ~~~
</div> </div>
<div class="language-swift">
~~~{.swift}
let start = Monster.startMonster(builder)
Monster.add(pos: pos, builder)
Monster.add(hp: 300, builder)
Monster.add(name: name, builder)
Monster.addVectorOf(inventory: inventoryOffset, builder)
Monster.add(color: .red, builder)
Monster.addVectorOf(weapons: weaponsOffset, builder)
Monster.add(equippedType: .weapon, builder)
Monster.add(equipped: axe, builder)
var orc = Monster.endMonster(builder, start: start)
~~~
</div>
Before finishing the serialization, let's take a quick look at FlatBuffer Before finishing the serialization, let's take a quick look at FlatBuffer
`union Equipped`. There are two parts to each FlatBuffer `union`. The first, is `union Equipped`. There are two parts to each FlatBuffer `union`. The first, is
a hidden field `_type`, that is generated to hold the type of `table` referred a hidden field `_type`, that is generated to hold the type of `table` referred
......
// THIS IS JUST TO SHOW THE CODE, PLEASE DO IMPORT FLATBUFFERS WITH SPM.. // THIS IS JUST TO SHOW THE CODE, PLEASE DO IMPORT FLATBUFFERS WITH SPM..
import Flatbuffers import Flatbuffers
typealias Monster = MyGame1.Sample.Monster typealias Monster = MyGame.Sample.Monster
typealias Weapon = MyGame1.Sample.Weapon typealias Weapon = MyGame.Sample.Weapon
typealias Color = MyGame1.Sample.Color typealias Color = MyGame.Sample.Color
typealias Vec3 = MyGame1.Sample.Vec3 typealias Vec3 = MyGame.Sample.Vec3
func main() { func main() {
let expectedDMG: [Int16] = [3, 5] let expectedDMG: [Int16] = [3, 5]
...@@ -30,16 +30,16 @@ func main() { ...@@ -30,16 +30,16 @@ func main() {
let weaponsOffset = builder.createVector(ofOffsets: [sword, axe]) let weaponsOffset = builder.createVector(ofOffsets: [sword, axe])
let pos = builder.create(struct: MyGame.Sample.createVec3(x: 1, y: 2, z: 3), type: Vec3.self) let pos = builder.create(struct: MyGame.Sample.createVec3(x: 1, y: 2, z: 3), type: Vec3.self)
let start = Monster.startMonster(builder)
Monster.add(pos: pos, builder) let orc = Monster.createMonster(builder,
Monster.add(hp: 300, builder) offsetOfPos: pos,
Monster.add(name: name, builder) hp: 300,
Monster.add(inventory: inventoryOffset, builder) offsetOfName: name,
Monster.add(color: .red, builder) vectorOfInventory: inventoryOffset,
Monster.add(weapons: weaponsOffset, builder) color: .red,
Monster.add(equippedType: .weapon, builder) vectorOfWeapons: weaponsOffset,
Monster.add(equipped: axe, builder) equippedType: .weapon,
var orc = Monster.endMonster(builder, start: start) offsetOfEquipped: axe)
builder.finish(offset: orc) builder.finish(offset: orc)
var buf = builder.sizedByteArray var buf = builder.sizedByteArray
...@@ -48,7 +48,7 @@ func main() { ...@@ -48,7 +48,7 @@ func main() {
assert(monster.mana == 150) assert(monster.mana == 150)
assert(monster.hp == 300) assert(monster.hp == 300)
assert(monster.name == "Orc") assert(monster.name == "Orc")
assert(monster.color == MyGame1.Sample.Color.red) assert(monster.color == MyGame.Sample.Color.red)
assert(monster.pos != nil) assert(monster.pos != nil)
for i in 0..<monster.inventoryCount { for i in 0..<monster.inventoryCount {
assert(i == monster.inventory(at: i)) assert(i == monster.inventory(at: i))
......
...@@ -213,14 +213,16 @@ class SwiftGenerator : public BaseGenerator { ...@@ -213,14 +213,16 @@ class SwiftGenerator : public BaseGenerator {
void GenTableWriter(const StructDef &struct_def) { void GenTableWriter(const StructDef &struct_def) {
flatbuffers::FieldDef *key_field = nullptr; flatbuffers::FieldDef *key_field = nullptr;
std::vector<std::string> require_fields;
std::string create_func_body;
std::string create_func_header;
auto should_generate_create = struct_def.fields.vec.size() != 0;
code_.SetValue("NUMBEROFFIELDS", NumToString(struct_def.fields.vec.size())); code_.SetValue("NUMBEROFFIELDS", NumToString(struct_def.fields.vec.size()));
code_ += code_ +=
"\tpublic static func start{{STRUCTNAME}}(_ fbb: FlatBufferBuilder) -> " "\tpublic static func start{{STRUCTNAME}}(_ fbb: FlatBufferBuilder) -> "
"UOffset { fbb.startTable(with: {{NUMBEROFFIELDS}}) }"; "UOffset { fbb.startTable(with: {{NUMBEROFFIELDS}}) }";
std::vector<std::string> require_fields;
for (auto it = struct_def.fields.vec.begin(); for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
auto &field = **it; auto &field = **it;
...@@ -230,7 +232,8 @@ class SwiftGenerator : public BaseGenerator { ...@@ -230,7 +232,8 @@ class SwiftGenerator : public BaseGenerator {
require_fields.push_back(NumToString(field.value.offset)); require_fields.push_back(NumToString(field.value.offset));
GenTableWriterFields( GenTableWriterFields(
field, static_cast<int>(it - struct_def.fields.vec.begin())); field, &create_func_body, &create_func_header,
static_cast<int>(it - struct_def.fields.vec.begin()));
} }
code_ += code_ +=
"\tpublic static func end{{STRUCTNAME}}(_ fbb: FlatBufferBuilder, " "\tpublic static func end{{STRUCTNAME}}(_ fbb: FlatBufferBuilder, "
...@@ -246,6 +249,19 @@ class SwiftGenerator : public BaseGenerator { ...@@ -246,6 +249,19 @@ class SwiftGenerator : public BaseGenerator {
} }
code_ += "; return end }"; code_ += "; return end }";
code_ +=
"\tpublic static func create{{STRUCTNAME}}(_ fbb: FlatBufferBuilder\\";
if (should_generate_create)
code_ += ",\n" +
create_func_header.substr(0, create_func_header.size() - 2) +
"\\";
code_ += ") -> Offset<UOffset> {";
code_ += "\t\tlet start = {{STRUCTNAME}}.start{{STRUCTNAME}}(fbb)";
if (should_generate_create)
code_ += create_func_body.substr(0, create_func_body.size() - 1);
code_ += "\t\treturn {{STRUCTNAME}}.end{{STRUCTNAME}}(fbb, start: start)";
code_ += "\t}";
std::string spacing = "\t\t"; std::string spacing = "\t\t";
if (key_field != nullptr && !struct_def.fixed && struct_def.has_key) { if (key_field != nullptr && !struct_def.fixed && struct_def.has_key) {
...@@ -268,8 +284,11 @@ class SwiftGenerator : public BaseGenerator { ...@@ -268,8 +284,11 @@ class SwiftGenerator : public BaseGenerator {
} }
} }
void GenTableWriterFields(const FieldDef &field, const int position) { void GenTableWriterFields(const FieldDef &field, std::string *create_body,
std::string *create_header, const int position) {
std::string builder_string = ", _ fbb: FlatBufferBuilder) { fbb.add("; std::string builder_string = ", _ fbb: FlatBufferBuilder) { fbb.add(";
auto &create_func_body = *create_body;
auto &create_func_header = *create_header;
auto name = Name(field); auto name = Name(field);
auto type = GenType(field.value.type); auto type = GenType(field.value.type);
code_.SetValue("VALUENAME", name); code_.SetValue("VALUENAME", name);
...@@ -279,30 +298,48 @@ class SwiftGenerator : public BaseGenerator { ...@@ -279,30 +298,48 @@ class SwiftGenerator : public BaseGenerator {
std::string check_if_vector = std::string check_if_vector =
(field.value.type.base_type == BASE_TYPE_VECTOR || (field.value.type.base_type == BASE_TYPE_VECTOR ||
field.value.type.base_type == BASE_TYPE_ARRAY) field.value.type.base_type == BASE_TYPE_ARRAY)
? "VectorOf" ? "VectorOf("
: ""; : "(";
code_ += std::string body = "add" + check_if_vector + name + ": ";
"\tpublic static func add" + check_if_vector + "({{VALUENAME}}: \\"; code_ += "\tpublic static func " + body + "\\";
create_func_body += "\t\t{{STRUCTNAME}}." + body + name + ", fbb)\n";
if (IsScalar(field.value.type.base_type) && if (IsScalar(field.value.type.base_type) &&
!IsBool(field.value.type.base_type)) { !IsBool(field.value.type.base_type)) {
auto default_value = IsEnum(field.value.type) ? GenEnumDefaultValue(field)
: field.value.constant;
auto is_enum = IsEnum(field.value.type) ? ".rawValue" : ""; auto is_enum = IsEnum(field.value.type) ? ".rawValue" : "";
code_ += "{{VALUETYPE}}" + builder_string + "element: {{VALUENAME}}" + code_ += "{{VALUETYPE}}" + builder_string + "element: {{VALUENAME}}" +
is_enum + ", def: {{CONSTANT}}, at: {{OFFSET}}) }"; is_enum + ", def: {{CONSTANT}}, at: {{OFFSET}}) }";
create_func_header +=
"\t\t" + name + ": " + type + " = " + default_value + ",\n";
return; return;
} }
if (IsBool(field.value.type.base_type)) { if (IsBool(field.value.type.base_type)) {
std::string default_value =
"0" == field.value.constant ? "false" : "true";
code_.SetValue("VALUETYPE", "Bool"); code_.SetValue("VALUETYPE", "Bool");
code_.SetValue("CONSTANT", code_.SetValue("CONSTANT", default_value);
"0" == field.value.constant ? "false" : "true");
code_ += "{{VALUETYPE}}" + builder_string + code_ += "{{VALUETYPE}}" + builder_string +
"condition: {{VALUENAME}}, def: {{CONSTANT}}, at: {{OFFSET}}) }"; "condition: {{VALUENAME}}, def: {{CONSTANT}}, at: {{OFFSET}}) }";
create_func_header +=
"\t\t" + name + ": " + type + " = " + default_value + ",\n";
return; return;
} }
auto offset_type = field.value.type.base_type == BASE_TYPE_STRING auto offset_type = field.value.type.base_type == BASE_TYPE_STRING
? "Offset<String>" ? "Offset<String>"
: "Offset<UOffset>"; : "Offset<UOffset>";
auto camel_case_name =
(field.value.type.base_type == BASE_TYPE_VECTOR ||
field.value.type.base_type == BASE_TYPE_ARRAY
? "vectorOf"
: "offsetOf") +
MakeCamel(name, true);
create_func_header += "\t\t" + camel_case_name + " " + name + ": " +
offset_type + " = Offset(),\n";
auto reader_type = auto reader_type =
IsStruct(field.value.type) && field.value.type.struct_def->fixed IsStruct(field.value.type) && field.value.type.struct_def->fixed
? "structOffset: {{OFFSET}}) }" ? "structOffset: {{OFFSET}}) }"
...@@ -444,7 +481,7 @@ class SwiftGenerator : public BaseGenerator { ...@@ -444,7 +481,7 @@ class SwiftGenerator : public BaseGenerator {
if (IsEnum(vectortype)) { if (IsEnum(vectortype)) {
code_.SetValue("BASEVALUE", GenTypeBasic(vectortype, false)); code_.SetValue("BASEVALUE", GenTypeBasic(vectortype, false));
code_ += "return o == 0 ? " + GenEnumDefaultValue(field) + code_ += "return o == 0 ? {{VALUETYPE}}" + GenEnumDefaultValue(field) +
" : {{VALUETYPE}}(rawValue: {{ACCESS}}.directRead(of: " " : {{VALUETYPE}}(rawValue: {{ACCESS}}.directRead(of: "
"{{BASEVALUE}}.self, offset: {{ACCESS}}.vector(at: o) + " "{{BASEVALUE}}.self, offset: {{ACCESS}}.vector(at: o) + "
"index * {{SIZE}})) }"; "index * {{SIZE}})) }";
...@@ -634,7 +671,7 @@ class SwiftGenerator : public BaseGenerator { ...@@ -634,7 +671,7 @@ class SwiftGenerator : public BaseGenerator {
name = ev.name; name = ev.name;
} }
std::transform(name.begin(), name.end(), name.begin(), LowerCase); std::transform(name.begin(), name.end(), name.begin(), LowerCase);
return "{{VALUETYPE}}." + name; return "." + name;
} }
std::string GenEnumConstructor(const std::string &at) { std::string GenEnumConstructor(const std::string &at) {
......
...@@ -88,11 +88,7 @@ final class FlatBuffersUnionTests: XCTestCase { ...@@ -88,11 +88,7 @@ final class FlatBuffersUnionTests: XCTestCase {
] ]
let types = fb.createVector(characterType) let types = fb.createVector(characterType)
let characterVector = fb.createVector(ofOffsets: characters) let characterVector = fb.createVector(ofOffsets: characters)
let end = Movie.createMovie(fb, vectorOfCharactersType: types, vectorOfCharacters: characterVector)
let movieStart = Movie.startMovie(fb)
Movie.addVectorOf(charactersType: types, fb)
Movie.addVectorOf(characters: characterVector, fb)
let end = Movie.endMovie(fb, start: movieStart)
Movie.finish(fb, end: end) Movie.finish(fb, end: end)
let movie = Movie.getRootAsMovie(bb: fb.buffer) let movie = Movie.getRootAsMovie(bb: fb.buffer)
......
...@@ -56,6 +56,12 @@ public struct Attacker: FlatBufferObject { ...@@ -56,6 +56,12 @@ public struct Attacker: FlatBufferObject {
public static func startAttacker(_ fbb: FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) } public static func startAttacker(_ fbb: FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) }
public static func add(swordAttackDamage: Int32, _ fbb: FlatBufferBuilder) { fbb.add(element: swordAttackDamage, def: 0, at: 0) } public static func add(swordAttackDamage: Int32, _ fbb: FlatBufferBuilder) { fbb.add(element: swordAttackDamage, def: 0, at: 0) }
public static func endAttacker(_ fbb: FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end } public static func endAttacker(_ fbb: FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end }
public static func createAttacker(_ fbb: FlatBufferBuilder,
swordAttackDamage: Int32 = 0) -> Offset<UOffset> {
let start = Attacker.startAttacker(fbb)
Attacker.add(swordAttackDamage: swordAttackDamage, fbb)
return Attacker.endAttacker(fbb, start: start)
}
} }
public struct Movie: FlatBufferObject { public struct Movie: FlatBufferObject {
...@@ -66,7 +72,7 @@ public struct Movie: FlatBufferObject { ...@@ -66,7 +72,7 @@ public struct Movie: FlatBufferObject {
private init(_ t: Table) { _accessor = t } private init(_ t: Table) { _accessor = t }
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) } public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
public var mainCharacterType: Character { let o = _accessor.offset(4); return o == 0 ? Character.none : Character(rawValue: _accessor.readBuffer(of: UInt8.self, at: o)) ?? Character.none } public var mainCharacterType: Character { let o = _accessor.offset(4); return o == 0 ? .none : Character(rawValue: _accessor.readBuffer(of: UInt8.self, at: o)) ?? .none }
public func mainCharacter<T: FlatBufferObject>(type: T.Type) -> T? { let o = _accessor.offset(6); return o == 0 ? nil : _accessor.union(o) } public func mainCharacter<T: FlatBufferObject>(type: T.Type) -> T? { let o = _accessor.offset(6); return o == 0 ? nil : _accessor.union(o) }
public var charactersTypeCount: Int32 { let o = _accessor.offset(8); return o == 0 ? 0 : _accessor.vector(count: o) } public var charactersTypeCount: Int32 { let o = _accessor.offset(8); return o == 0 ? 0 : _accessor.vector(count: o) }
public func charactersType(at index: Int32) -> Character? { let o = _accessor.offset(8); return o == 0 ? Character.none : Character(rawValue: _accessor.directRead(of: UInt8.self, offset: _accessor.vector(at: o) + index * 1)) } public func charactersType(at index: Int32) -> Character? { let o = _accessor.offset(8); return o == 0 ? Character.none : Character(rawValue: _accessor.directRead(of: UInt8.self, offset: _accessor.vector(at: o) + index * 1)) }
...@@ -78,5 +84,17 @@ public struct Movie: FlatBufferObject { ...@@ -78,5 +84,17 @@ public struct Movie: FlatBufferObject {
public static func addVectorOf(charactersType: Offset<UOffset>, _ fbb: FlatBufferBuilder) { fbb.add(offset: charactersType, at: 2) } public static func addVectorOf(charactersType: Offset<UOffset>, _ fbb: FlatBufferBuilder) { fbb.add(offset: charactersType, at: 2) }
public static func addVectorOf(characters: Offset<UOffset>, _ fbb: FlatBufferBuilder) { fbb.add(offset: characters, at: 3) } public static func addVectorOf(characters: Offset<UOffset>, _ fbb: FlatBufferBuilder) { fbb.add(offset: characters, at: 3) }
public static func endMovie(_ fbb: FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end } public static func endMovie(_ fbb: FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end }
public static func createMovie(_ fbb: FlatBufferBuilder,
mainCharacterType: Character = .none,
offsetOfMainCharacter mainCharacter: Offset<UOffset> = Offset(),
vectorOfCharactersType charactersType: Offset<UOffset> = Offset(),
vectorOfCharacters characters: Offset<UOffset> = Offset()) -> Offset<UOffset> {
let start = Movie.startMovie(fbb)
Movie.add(mainCharacterType: mainCharacterType, fbb)
Movie.add(mainCharacter: mainCharacter, fbb)
Movie.addVectorOf(charactersType: charactersType, fbb)
Movie.addVectorOf(characters: characters, fbb)
return Movie.endMovie(fbb, start: start)
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment