From 4e79d129cb9018fdf6584cc1fef6a8d2db41715e Mon Sep 17 00:00:00 2001 From: mustiikhalil Date: Fri, 18 Dec 2020 01:55:32 +0300 Subject: [PATCH] [Swift] Rebuild the way swift handles structs from scratch (#6326) * Rebuild the way swift handles structs from scratch * Updates docs, and sample binary * Replaces InMemory to Mutable * Migrates docs from inmemory * use inline for some functions * Renamed Mutable objects * Updates documentation --- docs/source/SwiftUsage.md | 9 +- docs/source/Tutorial.md | 64 ++- samples/monster_generated.swift | 200 ++++++++ samples/sample_binary.swift | 12 +- src/idl_gen_swift.cpp | 539 ++++++++++++--------- swift/FlatBuffers.podspec | 2 +- swift/README.md | 2 +- swift/Sources/FlatBuffers/ByteBuffer.swift | 51 +- swift/Sources/FlatBuffers/FlatBufferBuilder.swift | 129 ++--- swift/Sources/FlatBuffers/FlatBufferObject.swift | 13 +- swift/Sources/FlatBuffers/Table.swift | 8 +- .../{NativeTable.swift => UnionObject.swift} | 4 +- .../FlatBuffers.Benchmarks.swift/main.swift | 20 +- tests/FlatBuffers.Test.Swift/SwiftTest.sh | 2 +- .../FlatBuffersMonsterWriterTests.swift | 30 +- .../FlatBuffersStructsTests.swift | 27 +- .../FlatBuffersUnionTests.swift | 30 +- .../MutatingBool_generated.swift | 20 +- .../XCTestManifests.swift | 12 +- .../monster_test_generated.swift | 441 ++++++++++------- .../union_vector_generated.swift | 152 +++--- 21 files changed, 1049 insertions(+), 718 deletions(-) create mode 100644 samples/monster_generated.swift rename swift/Sources/FlatBuffers/{NativeTable.swift => UnionObject.swift} (97%) diff --git a/docs/source/SwiftUsage.md b/docs/source/SwiftUsage.md index d5640f6..1c438f2 100644 --- a/docs/source/SwiftUsage.md +++ b/docs/source/SwiftUsage.md @@ -64,7 +64,8 @@ Now you can access values like this: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift} let hp = monster.hp - let pos = monster.pos + let pos = monster.pos // uses native swift structs + let pos = monster.mutablePos // uses flatbuffers structs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -76,8 +77,10 @@ In some cases it's necessary to modify values in an existing FlatBuffer in place if !monster.mutate(hp: 10) { fatalError("couldn't mutate") } - // mutate a struct field - let vec = monster.pos.mutate(z: 4) + // mutate a struct field using flatbuffers struct + // DONT use monster.pos to mutate since swift copy on write + // will not mutate the value in the buffer + let vec = monster.mutablePos.mutate(z: 4) // This mutation will fail because the mana field is not available in // the buffer. It should be set when creating the buffer. diff --git a/docs/source/Tutorial.md b/docs/source/Tutorial.md index f3f03f5..0d531a3 100644 --- a/docs/source/Tutorial.md +++ b/docs/source/Tutorial.md @@ -544,10 +544,10 @@ The first step is to import/include the library, generated files, etc. import Flatbuffers // typealiases for convenience - typealias Monster = MyGame1.Sample.Monster - typealias Weapon = MyGame1.Sample.Weapon - typealias Color = MyGame1.Sample.Color - typealias Vec3 = MyGame1.Sample.Vec3 + typealias Monster = MyGame1_Sample_Monster + typealias Weapon = MyGame1_Sample_Weapon + typealias Color = MyGame1_Sample_Color + typealias Vec3 = MyGame1_Sample_Vec3 ~~~ @@ -1420,9 +1420,20 @@ for the `path` field above:
~~~{.swift} // - Monster.startVectorOfvec3(2, in: &fbb) - MyGame_Example_Vec3.createVec3(builder: &fbb, x: 1, y: 2, z: 3) - MyGame_Example_Vec3.createVec3(builder: &fbb, x: 4, y: 5, z: 6) + let points = fbb.createVector(ofStructs: [ + Vec3(x: 1, y: 2, z: 3), + Vec3(x: 4, y: 5, z: 6) + ]) + + // OR + var vec3 = [ + Vec3(x: 1, y: 2, z: 3), + Vec3(x: 4, y: 5, z: 6) + ] + Monster.startVectorOfVec3(2, in: &fbb) + for i in obj { + _ = create(struct: i) + } let points = fbb.endVectorOfStructs(count: size) ~~~
@@ -1702,17 +1713,16 @@ can serialize the monster itself:
~~~{.swift} - let start = Monster.startMonster(&builder) - let posStruct = MyGame_Example_Vec3.createVec3(builder: &builder, x: 1, y: 2, z: 3) - 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) + let orc = Monster.createMonster( + fbb: &builder, + pos: Vec3(x: 1, y: 2, z: 3), + hp: 300, + name: name, + inventory: inventoryOffset, + color: .red, + weapons: weaponsOffset, + equippedType: .weapon, + equipped: axe) ~~~
@@ -1780,6 +1790,21 @@ a bit more flexibility. ~~~ +
+~~~{.swift} + let start = Monster.startMonster(&builder) + Monster.add(pos: Vec3(x: 1, y: 2, z: 3), &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) +~~~ +
+ 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 a hidden field `_type` that is generated to hold the type of `table` referred @@ -3239,7 +3264,8 @@ mutators like so: ~~~{.swift} let monster = Monster.getRootAsMonster(bb: ByteBuffer(bytes: buf)) monster.mutate(hp: 10) // mutates a value in a table - monster.pos.mutate(z: 4) // mutates a value in a struct + /// to mutate structs in swift you have to use the mutable accessors + monster.mutablePos.mutate(z: 4) // mutates a value in a struct monster.mutate(inventory: 6, at index: 0) // mutates a value in an Scalar array ~~~ diff --git a/samples/monster_generated.swift b/samples/monster_generated.swift new file mode 100644 index 0000000..4400c5a --- /dev/null +++ b/samples/monster_generated.swift @@ -0,0 +1,200 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// swiftlint:disable all +// swiftformat:disable all + +import FlatBuffers + +public enum MyGame_Sample_Color: Int8, Enum { + public typealias T = Int8 + public static var byteSize: Int { return MemoryLayout.size } + public var value: Int8 { return self.rawValue } + case red = 0 + case green = 1 + case blue = 2 + + + public static var max: MyGame_Sample_Color { return .blue } + public static var min: MyGame_Sample_Color { return .red } +} + +public enum MyGame_Sample_Equipment: UInt8, Enum { + public typealias T = UInt8 + public static var byteSize: Int { return MemoryLayout.size } + public var value: UInt8 { return self.rawValue } + case none_ = 0 + case weapon = 1 + + + public static var max: MyGame_Sample_Equipment { return .weapon } + public static var min: MyGame_Sample_Equipment { return .none_ } +} + +public struct MyGame_Sample_Vec3: NativeStruct { + + static func validateVersion() { FlatBuffersVersion_1_12_0() } + + private var _x: Float32 + private var _y: Float32 + private var _z: Float32 + + public init(x: Float32, y: Float32, z: Float32) { + _x = x + _y = y + _z = z + } + + public init() { + _x = 0.0 + _y = 0.0 + _z = 0.0 + } + + public var x: Float32 { _x } + public var y: Float32 { _y } + public var z: Float32 { _z } +} + +public struct MyGame_Sample_Vec3_Mutable: FlatBufferObject { + + static func validateVersion() { FlatBuffersVersion_1_12_0() } + public var __buffer: ByteBuffer! { return _accessor.bb } + private var _accessor: Struct + + public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) } + + public var x: Float32 { return _accessor.readBuffer(of: Float32.self, at: 0) } + @discardableResult public func mutate(x: Float32) -> Bool { return _accessor.mutate(x, index: 0) } + public var y: Float32 { return _accessor.readBuffer(of: Float32.self, at: 4) } + @discardableResult public func mutate(y: Float32) -> Bool { return _accessor.mutate(y, index: 4) } + public var z: Float32 { return _accessor.readBuffer(of: Float32.self, at: 8) } + @discardableResult public func mutate(z: Float32) -> Bool { return _accessor.mutate(z, index: 8) } +} + +public struct MyGame_Sample_Monster: FlatBufferObject { + + static func validateVersion() { FlatBuffersVersion_1_12_0() } + public var __buffer: ByteBuffer! { return _accessor.bb } + private var _accessor: Table + + public static func getRootAsMonster(bb: ByteBuffer) -> MyGame_Sample_Monster { return MyGame_Sample_Monster(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) } + + private init(_ t: Table) { _accessor = t } + public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) } + + private enum VTOFFSET: VOffset { + case pos = 4 + case mana = 6 + case hp = 8 + case name = 10 + case inventory = 14 + case color = 16 + case weapons = 18 + case equippedType = 20 + case equipped = 22 + case path = 24 + var v: Int32 { Int32(self.rawValue) } + var p: VOffset { self.rawValue } + } + + public var pos: MyGame_Sample_Vec3? { let o = _accessor.offset(VTOFFSET.pos.v); return o == 0 ? nil : _accessor.readBuffer(of: MyGame_Sample_Vec3.self, at: o) } + public var mutablePos: MyGame_Sample_Vec3_Mutable? { let o = _accessor.offset(VTOFFSET.pos.v); return o == 0 ? nil : MyGame_Sample_Vec3_Mutable(_accessor.bb, o: o + _accessor.postion) } + public var mana: Int16 { let o = _accessor.offset(VTOFFSET.mana.v); return o == 0 ? 150 : _accessor.readBuffer(of: Int16.self, at: o) } + @discardableResult public func mutate(mana: Int16) -> Bool {let o = _accessor.offset(VTOFFSET.mana.v); return _accessor.mutate(mana, index: o) } + public var hp: Int16 { let o = _accessor.offset(VTOFFSET.hp.v); return o == 0 ? 100 : _accessor.readBuffer(of: Int16.self, at: o) } + @discardableResult public func mutate(hp: Int16) -> Bool {let o = _accessor.offset(VTOFFSET.hp.v); return _accessor.mutate(hp, index: o) } + public var name: String? { let o = _accessor.offset(VTOFFSET.name.v); return o == 0 ? nil : _accessor.string(at: o) } + public var nameSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.name.v) } + public var inventoryCount: Int32 { let o = _accessor.offset(VTOFFSET.inventory.v); return o == 0 ? 0 : _accessor.vector(count: o) } + public func inventory(at index: Int32) -> UInt8 { let o = _accessor.offset(VTOFFSET.inventory.v); return o == 0 ? 0 : _accessor.directRead(of: UInt8.self, offset: _accessor.vector(at: o) + index * 1) } + public var inventory: [UInt8] { return _accessor.getVector(at: VTOFFSET.inventory.v) ?? [] } + public func mutate(inventory: UInt8, at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.inventory.v); return _accessor.directMutate(inventory, index: _accessor.vector(at: o) + index * 1) } + public var color: MyGame_Sample_Color { let o = _accessor.offset(VTOFFSET.color.v); return o == 0 ? .blue : MyGame_Sample_Color(rawValue: _accessor.readBuffer(of: Int8.self, at: o)) ?? .blue } + @discardableResult public func mutate(color: MyGame_Sample_Color) -> Bool {let o = _accessor.offset(VTOFFSET.color.v); return _accessor.mutate(color.rawValue, index: o) } + public var weaponsCount: Int32 { let o = _accessor.offset(VTOFFSET.weapons.v); return o == 0 ? 0 : _accessor.vector(count: o) } + public func weapons(at index: Int32) -> MyGame_Sample_Weapon? { let o = _accessor.offset(VTOFFSET.weapons.v); return o == 0 ? nil : MyGame_Sample_Weapon(_accessor.bb, o: _accessor.indirect(_accessor.vector(at: o) + index * 4)) } + public var equippedType: MyGame_Sample_Equipment { let o = _accessor.offset(VTOFFSET.equippedType.v); return o == 0 ? .none_ : MyGame_Sample_Equipment(rawValue: _accessor.readBuffer(of: UInt8.self, at: o)) ?? .none_ } + public func equipped(type: T.Type) -> T? { let o = _accessor.offset(VTOFFSET.equipped.v); return o == 0 ? nil : _accessor.union(o) } + public var pathCount: Int32 { let o = _accessor.offset(VTOFFSET.path.v); return o == 0 ? 0 : _accessor.vector(count: o) } + public func path(at index: Int32) -> MyGame_Sample_Vec3? { let o = _accessor.offset(VTOFFSET.path.v); return o == 0 ? nil : _accessor.directRead(of: MyGame_Sample_Vec3.self, offset: _accessor.vector(at: o) + index * 12) } + public func mutablePath(at index: Int32) -> MyGame_Sample_Vec3_Mutable? { let o = _accessor.offset(VTOFFSET.path.v); return o == 0 ? nil : MyGame_Sample_Vec3_Mutable(_accessor.bb, o: _accessor.vector(at: o) + index * 12) } + public static func startMonster(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 11) } + public static func add(pos: MyGame_Sample_Vec3?, _ fbb: inout FlatBufferBuilder) { guard let pos = pos else { return }; fbb.create(struct: pos, position: VTOFFSET.pos.p) } + public static func add(mana: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: mana, def: 150, at: VTOFFSET.mana.p) } + public static func add(hp: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: hp, def: 100, at: VTOFFSET.hp.p) } + public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VTOFFSET.name.p) } + public static func addVectorOf(inventory: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: inventory, at: VTOFFSET.inventory.p) } + public static func add(color: MyGame_Sample_Color, _ fbb: inout FlatBufferBuilder) { fbb.add(element: color.rawValue, def: 2, at: VTOFFSET.color.p) } + public static func addVectorOf(weapons: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: weapons, at: VTOFFSET.weapons.p) } + public static func add(equippedType: MyGame_Sample_Equipment, _ fbb: inout FlatBufferBuilder) { fbb.add(element: equippedType.rawValue, def: 0, at: VTOFFSET.equippedType.p) } + public static func add(equipped: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: equipped, at: VTOFFSET.equipped.p) } + public static func addVectorOf(path: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: path, at: VTOFFSET.path.p) } + public static func startVectorOfPath(_ size: Int, in builder: inout FlatBufferBuilder) { + builder.startVector(size * MemoryLayout.size, elementSize: MemoryLayout.alignment) + } + public static func endMonster(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end } + public static func createMonster( + _ fbb: inout FlatBufferBuilder, + pos: MyGame_Sample_Vec3? = nil, + mana: Int16 = 150, + hp: Int16 = 100, + offsetOfName name: Offset = Offset(), + vectorOfInventory inventory: Offset = Offset(), + color: MyGame_Sample_Color = .blue, + vectorOfWeapons weapons: Offset = Offset(), + equippedType: MyGame_Sample_Equipment = .none_, + offsetOfEquipped equipped: Offset = Offset(), + vectorOfPath path: Offset = Offset() + ) -> Offset { + let __start = MyGame_Sample_Monster.startMonster(&fbb) + MyGame_Sample_Monster.add(pos: pos, &fbb) + MyGame_Sample_Monster.add(mana: mana, &fbb) + MyGame_Sample_Monster.add(hp: hp, &fbb) + MyGame_Sample_Monster.add(name: name, &fbb) + MyGame_Sample_Monster.addVectorOf(inventory: inventory, &fbb) + MyGame_Sample_Monster.add(color: color, &fbb) + MyGame_Sample_Monster.addVectorOf(weapons: weapons, &fbb) + MyGame_Sample_Monster.add(equippedType: equippedType, &fbb) + MyGame_Sample_Monster.add(equipped: equipped, &fbb) + MyGame_Sample_Monster.addVectorOf(path: path, &fbb) + return MyGame_Sample_Monster.endMonster(&fbb, start: __start) + } +} + +public struct MyGame_Sample_Weapon: FlatBufferObject { + + static func validateVersion() { FlatBuffersVersion_1_12_0() } + public var __buffer: ByteBuffer! { return _accessor.bb } + private var _accessor: Table + + public static func getRootAsWeapon(bb: ByteBuffer) -> MyGame_Sample_Weapon { return MyGame_Sample_Weapon(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) } + + private init(_ t: Table) { _accessor = t } + public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) } + + private enum VTOFFSET: VOffset { + case name = 4 + case damage = 6 + var v: Int32 { Int32(self.rawValue) } + var p: VOffset { self.rawValue } + } + + public var name: String? { let o = _accessor.offset(VTOFFSET.name.v); return o == 0 ? nil : _accessor.string(at: o) } + public var nameSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.name.v) } + public var damage: Int16 { let o = _accessor.offset(VTOFFSET.damage.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int16.self, at: o) } + @discardableResult public func mutate(damage: Int16) -> Bool {let o = _accessor.offset(VTOFFSET.damage.v); return _accessor.mutate(damage, index: o) } + public static func startWeapon(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 2) } + public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VTOFFSET.name.p) } + public static func add(damage: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: damage, def: 0, at: VTOFFSET.damage.p) } + public static func endWeapon(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end } + public static func createWeapon( + _ fbb: inout FlatBufferBuilder, + offsetOfName name: Offset = Offset(), + damage: Int16 = 0 + ) -> Offset { + let __start = MyGame_Sample_Weapon.startWeapon(&fbb) + MyGame_Sample_Weapon.add(name: name, &fbb) + MyGame_Sample_Weapon.add(damage: damage, &fbb) + return MyGame_Sample_Weapon.endWeapon(&fbb, start: __start) + } +} + diff --git a/samples/sample_binary.swift b/samples/sample_binary.swift index 46ab99b..88d2578 100644 --- a/samples/sample_binary.swift +++ b/samples/sample_binary.swift @@ -16,10 +16,10 @@ import FlatBuffers -typealias Monster = MyGame.Sample.Monster -typealias Weapon = MyGame.Sample.Weapon -typealias Color = MyGame.Sample.Color -typealias Vec3 = MyGame.Sample.Vec3 +typealias Monster = MyGame_Sample_Monster +typealias Weapon = MyGame_Sample_Weapon +typealias Color = MyGame_Sample_Color +typealias Vec3 = MyGame_Sample_Vec3 func main() { let expectedDMG: [Int16] = [3, 5] @@ -43,11 +43,10 @@ func main() { let inventoryOffset = builder.createVector(inventory) let weaponsOffset = builder.createVector(ofOffsets: [sword, axe]) - let pos = MyGame.Sample.createVec3(x: 1, y: 2, z: 3) let orc = Monster.createMonster( &builder, - structOfPos: pos, + structOfPos: MyGame_Sample_Vec3(x: 1, y: 2, z: 3), hp: 300, offsetOfName: name, vectorOfInventory: inventoryOffset, @@ -65,6 +64,7 @@ func main() { assert(monster.name == "Orc") assert(monster.color == MyGame.Sample.Color.red) assert(monster.pos != nil) + assert(monster.mutablePos != nil) for i in 0.. base_constructor; + std::vector main_constructor; + + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + + if (!constructor.empty()) constructor += ", "; + + auto name = Name(field); + auto type = GenType(field.value.type); + code_.SetValue("VALUENAME", name); + if (IsEnum(field.value.type)) { + code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false)); + } + code_.SetValue("VALUETYPE", type); + GenComment(field.doc_comment); + std::string valueType = + IsEnum(field.value.type) ? "{{BASEVALUE}}" : "{{VALUETYPE}}"; + code_ += "private var _{{VALUENAME}}: " + valueType; + auto accessing_value = IsEnum(field.value.type) ? ".value" : ""; + auto base_value = + IsStruct(field.value.type) ? (type + "()") : field.value.constant; + + main_constructor.push_back("_" + name + " = " + name + accessing_value); + base_constructor.push_back("_" + name + " = " + base_value); + + if (field.padding) { GenPadding(field, &padding_id); } + constructor += name + ": " + type; + } + code_ += ""; + BuildObjectConstructor(main_constructor, constructor); + BuildObjectConstructor(base_constructor, ""); + + if (parser_.opts.generate_object_based_api) + GenerateObjectAPIStructConstructor(struct_def); + + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + auto name = Name(field); + auto type = GenType(field.value.type); + code_.SetValue("VALUENAME", name); + code_.SetValue("VALUETYPE", type); + GenComment(field.doc_comment); + if (!IsEnum(field.value.type)) { + code_ += GenReaderMainBody() + "_{{VALUENAME}} }"; + } else if (IsEnum(field.value.type)) { + code_ += + GenReaderMainBody() + "{{VALUETYPE}}(rawValue: _{{VALUENAME}})! }"; + } + } + Outdent(); + code_ += "}\n"; + } + + void GenMutableStructReader(const StructDef &struct_def) { + GenObjectHeader(struct_def); + + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + auto offset = NumToString(field.value.offset); + auto name = Name(field); + auto type = GenType(field.value.type); + code_.SetValue("VALUENAME", name); + if (IsEnum(field.value.type)) { + code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false)); + } + code_.SetValue("VALUETYPE", type); + code_.SetValue("OFFSET", offset); + if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type)) { + code_ += + GenReaderMainBody() + "return " + GenReader("VALUETYPE") + " }"; + } else if (IsEnum(field.value.type)) { + code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false)); + code_ += GenReaderMainBody() + "return " + + GenEnumConstructor("{{OFFSET}}") + "?? " + + GenEnumDefaultValue(field) + " }"; + } else if (IsStruct(field.value.type)) { + code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable()); + code_ += GenReaderMainBody() + "return " + + GenConstructor("{{ACCESS}}.postion + {{OFFSET}}"); + } + if (parser_.opts.mutable_buffer && !IsStruct(field.value.type)) + code_ += GenMutate("{{OFFSET}}", "", IsEnum(field.value.type)); + } + + if (parser_.opts.generate_object_based_api) { + GenerateObjectAPIExtensionHeader(NameWrappedInNameSpace(struct_def)); + code_ += "return builder.create(struct: obj)"; + Outdent(); + code_ += "}"; + } + Outdent(); + code_ += "}\n"; + } + // Generates the create function for swift void GenStructWriter(const StructDef &struct_def) { auto is_private_access = struct_def.attributes.Lookup("private"); @@ -208,7 +316,6 @@ class SwiftGenerator : public BaseGenerator { code_ += "builder.createStructOf(size: {{STRUCTNAME}}.size, alignment: " "{{STRUCTNAME}}.alignment)"; - GenerateStructBody(struct_def, ""); code_ += "return builder.endStruct()"; Outdent(); code_ += "}\n"; @@ -216,27 +323,6 @@ class SwiftGenerator : public BaseGenerator { code_ += "}\n"; } - void GenerateStructBody(const StructDef &struct_def, - const std::string &nameprefix, int offset = 0) { - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (field.deprecated) continue; - auto name = nameprefix + Name(field); - const auto &field_type = field.value.type; - auto type = GenTypeBasic(field_type, false); - if (IsStruct(field.value.type)) { - GenerateStructBody(*field_type.struct_def, (nameprefix + field.name), - static_cast(field.value.offset)); - } else { - auto off = NumToString(offset + field.value.offset); - code_ += "builder.reverseAdd(v: " + name + - (field_type.enum_def ? ".rawValue" : "") + - ", postion: " + off + ")"; - } - } - } - void GenerateStructArgs(const StructDef &struct_def, std::string *code_ptr, const std::string &nameprefix, const std::string &object_name, @@ -275,51 +361,7 @@ class SwiftGenerator : public BaseGenerator { } } - void GenObjectHeader(const StructDef &struct_def) { - GenComment(struct_def.doc_comment); - code_.SetValue("SHORT_STRUCTNAME", Name(struct_def)); - code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def)); - code_.SetValue("PROTOCOL", - struct_def.fixed ? "Readable" : "FlatBufferObject"); - code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table"); - code_ += "{{ACCESS_TYPE}} struct {{STRUCTNAME}}: {{PROTOCOL}}\\"; - if (!struct_def.fixed && parser_.opts.generate_object_based_api) - code_ += ", ObjectAPI\\"; - code_ += " {\n"; - Indent(); - code_ += ValidateFunc(); - code_ += - "{{ACCESS_TYPE}} var __buffer: ByteBuffer! { return {{ACCESS}}.bb }"; - code_ += "private var {{ACCESS}}: {{OBJECTTYPE}}\n"; - if (struct_def.fixed) { - code_.SetValue("BYTESIZE", NumToString(struct_def.bytesize)); - code_.SetValue("MINALIGN", NumToString(struct_def.minalign)); - code_ += "{{ACCESS_TYPE}} static var size = {{BYTESIZE}}"; - code_ += "{{ACCESS_TYPE}} static var alignment = {{MINALIGN}}"; - } else { - if (parser_.file_identifier_.length()) { - code_.SetValue("FILENAME", parser_.file_identifier_); - code_ += - "{{ACCESS_TYPE}} static func finish(_ fbb: inout " - "FlatBufferBuilder, end: " - "Offset, prefix: Bool = false) { fbb.finish(offset: end, " - "fileId: " - "\"{{FILENAME}}\", addPrefix: prefix) }"; - } - code_ += - "{{ACCESS_TYPE}} static func getRootAs{{SHORT_STRUCTNAME}}(bb: " - "ByteBuffer) -> " - "{{STRUCTNAME}} { return {{STRUCTNAME}}(Table(bb: bb, position: " - "Int32(bb.read(def: UOffset.self, position: bb.reader)) + " - "Int32(bb.reader))) }\n"; - code_ += "private init(_ t: Table) { {{ACCESS}} = t }"; - } - code_ += - "{{ACCESS_TYPE}} init(_ bb: ByteBuffer, o: Int32) { {{ACCESS}} = " - "{{OBJECTTYPE}}(bb: " - "bb, position: o) }"; - code_ += ""; - } + // MARK: - Table Generator // Generates the reader for swift void GenTable(const StructDef &struct_def) { @@ -358,51 +400,46 @@ class SwiftGenerator : public BaseGenerator { } } - void GenerateObjectAPIExtensionHeader() { - code_ += "\n"; - code_ += "{{ACCESS_TYPE}} mutating func unpack() -> " + - ObjectAPIName("{{STRUCTNAME}}") + " {"; - Indent(); - code_ += "return " + ObjectAPIName("{{STRUCTNAME}}") + "(&self)"; - Outdent(); - code_ += "}"; + void GenObjectHeader(const StructDef &struct_def) { + GenComment(struct_def.doc_comment); + + code_.SetValue("SHORT_STRUCTNAME", Name(struct_def)); + code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def)); + code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table"); + code_.SetValue("MUTABLE", struct_def.fixed ? Mutable() : ""); code_ += - "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, " - "obj: " - "inout " + - ObjectAPIName("{{STRUCTNAME}}") + "?) -> Offset {"; + "{{ACCESS_TYPE}} struct {{STRUCTNAME}}{{MUTABLE}}: FlatBufferObject\\"; + if (!struct_def.fixed && parser_.opts.generate_object_based_api) + code_ += ", ObjectAPI\\"; + code_ += " {\n"; Indent(); - code_ += "guard var obj = obj else { return Offset() }"; - code_ += "return pack(&builder, obj: &obj)"; - Outdent(); - code_ += "}"; - code_ += ""; + code_ += ValidateFunc(); code_ += - "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, " - "obj: " - "inout " + - ObjectAPIName("{{STRUCTNAME}}") + ") -> Offset {"; - Indent(); - } - - void GenerateObjectAPIStructExtension(const StructDef &struct_def) { - GenerateObjectAPIExtensionHeader(); - std::string code; - GenerateStructArgs(struct_def, &code, "", "", "obj", true); - code_ += "return create{{SHORT_STRUCTNAME}}(builder: &builder, \\"; - code_ += code.substr(0, code.size() - 2) + "\\"; - code_ += ")"; - Outdent(); - code_ += "}"; - } - - void GenTableReader(const StructDef &struct_def) { - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (field.deprecated) continue; - GenTableReaderFields(field); + "{{ACCESS_TYPE}} var __buffer: ByteBuffer! { return {{ACCESS}}.bb }"; + code_ += "private var {{ACCESS}}: {{OBJECTTYPE}}\n"; + if (!struct_def.fixed) { + if (parser_.file_identifier_.length()) { + code_.SetValue("FILENAME", parser_.file_identifier_); + code_ += + "{{ACCESS_TYPE}} static func finish(_ fbb: inout " + "FlatBufferBuilder, end: " + "Offset, prefix: Bool = false) { fbb.finish(offset: end, " + "fileId: " + "\"{{FILENAME}}\", addPrefix: prefix) }"; + } + code_ += + "{{ACCESS_TYPE}} static func getRootAs{{SHORT_STRUCTNAME}}(bb: " + "ByteBuffer) -> " + "{{STRUCTNAME}} { return {{STRUCTNAME}}(Table(bb: bb, position: " + "Int32(bb.read(def: UOffset.self, position: bb.reader)) + " + "Int32(bb.reader))) }\n"; + code_ += "private init(_ t: Table) { {{ACCESS}} = t }"; } + code_ += + "{{ACCESS_TYPE}} init(_ bb: ByteBuffer, o: Int32) { {{ACCESS}} = " + "{{OBJECTTYPE}}(bb: " + "bb, position: o) }"; + code_ += ""; } void GenTableWriter(const StructDef &struct_def) { @@ -426,8 +463,7 @@ class SwiftGenerator : public BaseGenerator { if (field.required) require_fields.push_back(NumToString(field.value.offset)); - GenTableWriterFields(field, &create_func_body, &create_func_header, - should_generate_create); + GenTableWriterFields(field, &create_func_body, &create_func_header); } code_ += "{{ACCESS_TYPE}} static func end{{SHORT_STRUCTNAME}}(_ fbb: inout " @@ -495,24 +531,21 @@ class SwiftGenerator : public BaseGenerator { void GenTableWriterFields(const FieldDef &field, std::vector *create_body, - std::vector *create_header, - bool &contains_structs) { + std::vector *create_header) { std::string builder_string = ", _ fbb: inout FlatBufferBuilder) { "; auto &create_func_body = *create_body; auto &create_func_header = *create_header; auto name = Name(field); auto type = GenType(field.value.type); - bool opt_scalar = field.optional && IsScalar(field.value.type.base_type); + auto opt_scalar = field.optional && IsScalar(field.value.type.base_type); auto nullable_type = opt_scalar ? type + "?" : type; code_.SetValue("VALUENAME", name); code_.SetValue("VALUETYPE", nullable_type); code_.SetValue("OFFSET", name); code_.SetValue("CONSTANT", field.value.constant); std::string check_if_vector = - (IsVector(field.value.type) || - IsArray(field.value.type)) - ? "VectorOf(" - : "("; + (IsVector(field.value.type) || IsArray(field.value.type)) ? "VectorOf(" + : "("; auto body = "add" + check_if_vector + name + ": "; code_ += "{{ACCESS_TYPE}} static func " + body + "\\"; @@ -556,24 +589,20 @@ class SwiftGenerator : public BaseGenerator { } if (IsStruct(field.value.type)) { - contains_structs = false; - auto struct_type = "Offset?"; - auto camel_case_name = "structOf" + MakeCamel(name, true); - auto reader_type = - "fbb.add(structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"; - auto create_struct = "guard {{VALUENAME}} != nil else { return }; "; - code_ += struct_type + builder_string + create_struct + reader_type; + auto create_struct = + "guard let pos = pos else { return };" + " fbb.create(struct: pos, position: {{TABLEOFFSET}}.{{OFFSET}}.p) }"; + code_ += type + "?" + builder_string + create_struct; + /// Optional hard coded since structs are always optional + create_func_header.push_back(name + ": " + type + "? = nil"); return; } - auto offset_type = IsString(field.value.type) - ? "Offset" - : "Offset"; + auto offset_type = + IsString(field.value.type) ? "Offset" : "Offset"; auto camel_case_name = - (IsVector(field.value.type) || - IsArray(field.value.type) - ? "vectorOf" - : "offsetOf") + + (IsVector(field.value.type) || IsArray(field.value.type) ? "vectorOf" + : "offsetOf") + MakeCamel(name, true); create_func_header.push_back(camel_case_name + " " + name + ": " + offset_type + " = Offset()"); @@ -587,22 +616,29 @@ class SwiftGenerator : public BaseGenerator { if ((vectortype.base_type == BASE_TYPE_STRUCT && field.value.type.struct_def->fixed) && - (IsVector(field.value.type) || - IsArray(field.value.type))) { + (IsVector(field.value.type) || IsArray(field.value.type))) { auto field_name = NameWrappedInNameSpace(*vectortype.struct_def); code_ += "public static func startVectorOf" + MakeCamel(name, true) + "(_ size: Int, in builder: inout " "FlatBufferBuilder) {"; Indent(); - code_ += "builder.startVectorOfStructs(count: size, size: " + field_name + - ".size, " - "alignment: " + - field_name + ".alignment)"; + code_ += "builder.startVector(size * MemoryLayout<" + field_name + + ">.size, elementSize: MemoryLayout<" + field_name + + ">.alignment)"; Outdent(); code_ += "}"; } } + void GenTableReader(const StructDef &struct_def) { + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + GenTableReaderFields(field); + } + } + void GenTableReaderFields(const FieldDef &field) { auto offset = NumToString(field.value.offset); auto name = Name(field); @@ -655,6 +691,11 @@ class SwiftGenerator : public BaseGenerator { code_.SetValue("VALUETYPE", GenType(field.value.type)); code_.SetValue("CONSTANT", "nil"); code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader + + "{{ACCESS}}.readBuffer(of: {{VALUETYPE}}.self, at: o) }"; + code_.SetValue("VALUENAME", "mutable" + MakeCamel(name)); + code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable()); + code_.SetValue("CONSTANT", "nil"); + code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader + GenConstructor("o + {{ACCESS}}.postion"); return; } @@ -705,6 +746,7 @@ class SwiftGenerator : public BaseGenerator { : "nil"); auto nullable = IsScalar(vectortype.base_type) == true ? "" : "?"; nullable = IsEnum(vectortype) == true ? "?" : nullable; + if (vectortype.base_type != BASE_TYPE_UNION) { code_ += GenArrayMainBody(nullable) + GenOffset() + "\\"; } else { @@ -733,9 +775,17 @@ class SwiftGenerator : public BaseGenerator { if (parser_.opts.mutable_buffer) code_ += GenMutateArray(); return; } + if (vectortype.base_type == BASE_TYPE_STRUCT && field.value.type.struct_def->fixed) { - code_ += GenConstructor("{{ACCESS}}.vector(at: o) + index * {{SIZE}}"); + code_ += + "{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: " + "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }"; + code_.SetValue("VALUENAME", "mutable" + MakeCamel(Name(field))); + code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable()); + code_ += GenArrayMainBody(nullable) + GenOffset() + const_string + + GenConstructor("{{ACCESS}}.vector(at: o) + index * {{SIZE}}"); + return; } @@ -788,44 +838,6 @@ class SwiftGenerator : public BaseGenerator { "{{ACCESS}}.vector(at: o), key: key, fbb: {{ACCESS}}.bb) }"; } - // Generates the reader for swift - void GenStructReader(const StructDef &struct_def) { - auto is_private_access = struct_def.attributes.Lookup("private"); - code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public"); - - GenObjectHeader(struct_def); - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (field.deprecated) continue; - auto offset = NumToString(field.value.offset); - auto name = Name(field); - auto type = GenType(field.value.type); - code_.SetValue("VALUENAME", name); - code_.SetValue("VALUETYPE", type); - code_.SetValue("OFFSET", offset); - GenComment(field.doc_comment); - if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type)) { - code_ += - GenReaderMainBody() + "return " + GenReader("VALUETYPE") + " }"; - if (parser_.opts.mutable_buffer) code_ += GenMutate("{{OFFSET}}", ""); - } else if (IsEnum(field.value.type)) { - code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false)); - code_ += GenReaderMainBody() + "return " + - GenEnumConstructor("{{OFFSET}}") + "?? " + - GenEnumDefaultValue(field) + " }"; - } else if (IsStruct(field.value.type)) { - code_.SetValue("VALUETYPE", GenType(field.value.type)); - code_ += GenReaderMainBody() + "return " + - GenConstructor("{{ACCESS}}.postion + {{OFFSET}}"); - } - } - if (parser_.opts.generate_object_based_api) - GenerateObjectAPIStructExtension(struct_def); - Outdent(); - code_ += "}\n"; - } - void GenEnum(const EnumDef &enum_def) { if (enum_def.generated) return; auto is_private_access = enum_def.attributes.Lookup("private"); @@ -859,8 +871,8 @@ class SwiftGenerator : public BaseGenerator { code_ += "{{ACCESS_TYPE}} struct {{ENUM_NAME}}Union {"; Indent(); code_ += "{{ACCESS_TYPE}} var type: {{ENUM_NAME}}"; - code_ += "{{ACCESS_TYPE}} var value: NativeTable?"; - code_ += "{{ACCESS_TYPE}} init(_ v: NativeTable?, type: {{ENUM_NAME}}) {"; + code_ += "{{ACCESS_TYPE}} var value: UnionObject?"; + code_ += "{{ACCESS_TYPE}} init(_ v: UnionObject?, type: {{ENUM_NAME}}) {"; Indent(); code_ += "self.type = type"; code_ += "self.value = v"; @@ -878,9 +890,61 @@ class SwiftGenerator : public BaseGenerator { } } + // MARK: - Object API + + void GenerateObjectAPIExtensionHeader(std::string name) { + code_ += "\n"; + code_ += "{{ACCESS_TYPE}} mutating func unpack() -> " + name + " {"; + Indent(); + code_ += "return " + name + "(&self)"; + Outdent(); + code_ += "}"; + code_ += + "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, " + "obj: " + "inout " + + name + "?) -> Offset {"; + Indent(); + code_ += "guard var obj = obj else { return Offset() }"; + code_ += "return pack(&builder, obj: &obj)"; + Outdent(); + code_ += "}"; + code_ += ""; + code_ += + "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, " + "obj: " + "inout " + + name + ") -> Offset {"; + Indent(); + } + + void GenerateObjectAPIStructConstructor(const StructDef &struct_def) { + code_ += + "{{ACCESS_TYPE}} init(_ _t: inout {{STRUCTNAME}}" + Mutable() + ") {"; + Indent(); + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + + auto name = Name(field); + auto type = GenType(field.value.type); + code_.SetValue("VALUENAME", name); + if (IsStruct(field.value.type)) { + code_ += "var _v = _t.{{VALUENAME}}"; + code_ += "_{{VALUENAME}} = _v.unpack()"; + continue; + } + std::string is_enum = IsEnum(field.value.type) ? ".value" : ""; + code_ += "_{{VALUENAME}} = _t.{{VALUENAME}}" + is_enum; + } + Outdent(); + code_ += "}\n"; + } + void GenObjectAPI(const StructDef &struct_def) { code_ += "{{ACCESS_TYPE}} class " + ObjectAPIName("{{STRUCTNAME}}") + - ": NativeTable {\n"; + ": UnionObject {\n"; std::vector buffer_constructor; std::vector base_constructor; Indent(); @@ -892,10 +956,9 @@ class SwiftGenerator : public BaseGenerator { base_constructor); } code_ += ""; - BuildObjectAPIConstructor( - buffer_constructor, - "_ _t: inout " + NameWrappedInNameSpace(struct_def)); - BuildObjectAPIConstructor(base_constructor); + BuildObjectConstructor(buffer_constructor, + "_ _t: inout " + NameWrappedInNameSpace(struct_def)); + BuildObjectConstructor(base_constructor); if (!struct_def.fixed) code_ += "{{ACCESS_TYPE}} func serialize() -> ByteBuffer { return " @@ -906,7 +969,7 @@ class SwiftGenerator : public BaseGenerator { } void GenerateObjectAPITableExtension(const StructDef &struct_def) { - GenerateObjectAPIExtensionHeader(); + GenerateObjectAPIExtensionHeader(ObjectAPIName("{{STRUCTNAME}}")); std::vector unpack_body; std::string builder = ", &builder)"; for (auto it = struct_def.fields.vec.begin(); @@ -916,8 +979,7 @@ class SwiftGenerator : public BaseGenerator { auto name = Name(field); auto type = GenType(field.value.type); std::string check_if_vector = - (IsVector(field.value.type) || - IsArray(field.value.type)) + (IsVector(field.value.type) || IsArray(field.value.type)) ? "VectorOf(" : "("; std::string body = "add" + check_if_vector + name + ": "; @@ -944,16 +1006,13 @@ class SwiftGenerator : public BaseGenerator { if (field.value.type.struct_def && field.value.type.struct_def->fixed) { // This is a Struct (IsStruct), not a table. We create - // UnsafeMutableRawPointer in this case. + // a native swift object in this case. std::string code; GenerateStructArgs(*field.value.type.struct_def, &code, "", "", "$0", true); code = code.substr(0, code.size() - 2); - unpack_body.push_back( - "{{STRUCTNAME}}." + body + "obj." + name + ".map { " + - NameWrappedInNameSpace(*field.value.type.struct_def) + - ".create" + Name(*field.value.type.struct_def) + - "(builder: &builder, " + code + ") }" + builder); + unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." + name + + builder); } else { code_ += "let __" + name + " = " + type + ".pack(&builder, obj: &obj." + name + ")"; @@ -1032,13 +1091,10 @@ class SwiftGenerator : public BaseGenerator { code_ += "for i in obj." + name + " {"; Indent(); code_ += "guard let _o = i else { continue }"; - code_ += NameWrappedInNameSpace(*field.value.type.struct_def) + - ".create" + Name(*field.value.type.struct_def) + - "(builder: &builder, " + code + ")"; + code_ += "builder.create(struct: _o)"; Outdent(); code_ += "}"; - code_ += "let __" + name + - " = builder.endVectorOfStructs(count: obj." + name + + code_ += "let __" + name + " = builder.endVector(len: obj." + name + ".count)"; } break; @@ -1071,8 +1127,8 @@ class SwiftGenerator : public BaseGenerator { code_ += ""; } - void BuildObjectAPIConstructor(const std::vector &body, - const std::string &header = "") { + void BuildObjectConstructor(const std::vector &body, + const std::string &header = "") { code_.SetValue("HEADER", header); code_ += "{{ACCESS_TYPE}} init({{HEADER}}) {"; Indent(); @@ -1095,7 +1151,6 @@ class SwiftGenerator : public BaseGenerator { case BASE_TYPE_STRUCT: { type = GenType(field.value.type, true); code_.SetValue("VALUETYPE", type); - buffer_constructor.push_back("var __" + name + " = _t." + name); auto optional = (field.value.type.struct_def && field.value.type.struct_def->fixed); std::string question_mark = @@ -1103,10 +1158,16 @@ class SwiftGenerator : public BaseGenerator { code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + question_mark; - buffer_constructor.push_back("" + name + " = __" + name + - (field.required ? "!" : question_mark) + - ".unpack()"); base_constructor.push_back("" + name + " = " + type + "()"); + + if (field.value.type.struct_def->fixed) { + buffer_constructor.push_back("" + name + " = _t." + name); + } else { + buffer_constructor.push_back("var __" + name + " = _t." + name); + buffer_constructor.push_back("" + name + " = __" + name + + (field.required ? "!" : question_mark) + + ".unpack()"); + } break; } case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); @@ -1176,10 +1237,15 @@ class SwiftGenerator : public BaseGenerator { case BASE_TYPE_STRUCT: { code_.SetValue("VALUETYPE", GenType(vectortype, true)); code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}?]"; - buffer_constructor.push_back(indentation + "var __v_ = _t." + name + - "(at: index)"); - buffer_constructor.push_back(indentation + name + - ".append(__v_?.unpack())"); + if (!vectortype.struct_def->fixed) { + buffer_constructor.push_back(indentation + "var __v_ = _t." + name + + "(at: index)"); + buffer_constructor.push_back(indentation + name + + ".append(__v_?.unpack())"); + } else { + buffer_constructor.push_back(indentation + name + ".append(_t." + + name + "(at: index))"); + } break; } case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); @@ -1193,9 +1259,9 @@ class SwiftGenerator : public BaseGenerator { } case BASE_TYPE_UTYPE: break; default: { - code_.SetValue("VALUETYPE", (IsString(vectortype) - ? "String?" - : GenType(vectortype))); + code_.SetValue( + "VALUETYPE", + (IsString(vectortype) ? "String?" : GenType(vectortype))); code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}]"; if (IsEnum(vectortype) && vectortype.base_type != BASE_TYPE_UNION) { @@ -1223,7 +1289,7 @@ class SwiftGenerator : public BaseGenerator { auto field = **it; auto ev_name = Name(field); auto type = GenType(field.union_type); - + auto is_struct = IsStruct(field.union_type) ? type + Mutable() : type; if (field.union_type.base_type == BASE_TYPE_NONE || IsString(field.union_type)) { continue; @@ -1231,7 +1297,7 @@ class SwiftGenerator : public BaseGenerator { code_ += "case ." + ev_name + ":"; Indent(); code_ += "var __obj = value as? " + GenType(field.union_type, true); - code_ += "return " + type + ".pack(&builder, obj: &__obj)"; + code_ += "return " + is_struct + ".pack(&builder, obj: &__obj)"; Outdent(); } code_ += "default: return Offset()"; @@ -1258,15 +1324,17 @@ class SwiftGenerator : public BaseGenerator { IsString(field.union_type)) { continue; } + auto type = IsStruct(field.union_type) + ? GenType(field.union_type) + Mutable() + : GenType(field.union_type); buffer_constructor.push_back(indentation + "case ." + ev_name + ":"); buffer_constructor.push_back( - indentation + " var _v = _t." + name + (is_vector ? "" : "(") + - vector_reader + (is_vector ? ", " : "") + - "type: " + GenType(field.union_type) + ".self)"); + indentation + " var _v = _t." + name + (is_vector ? "" : "(") + + vector_reader + (is_vector ? ", " : "") + "type: " + type + ".self)"); auto constructor = field_name + "Union(_v?.unpack(), type: ." + ev_name + ")"; buffer_constructor.push_back( - indentation + " " + name + + indentation + " " + name + (is_vector ? ".append(" + constructor + ")" : " = " + constructor)); } buffer_constructor.push_back(indentation + "default: break"); @@ -1330,6 +1398,19 @@ class SwiftGenerator : public BaseGenerator { code_ += "}"; } + inline void GenPadding(const FieldDef &field, int *id) { + if (field.padding) { + for (int i = 0; i < 4; i++) { + if (static_cast(field.padding) & (1 << i)) { + auto bits = (1 << i) * 8; + code_ += "private let padding" + NumToString((*id)++) + "__: UInt" + + NumToString(bits) + " = 0"; + } + } + FLATBUFFERS_ASSERT(!(field.padding & ~0xF)); + } + } + void GenComment(const std::vector &dc) { if (dc.begin() == dc.end()) { // Don't output empty comment blocks with 0 lines of comment content. @@ -1411,7 +1492,7 @@ class SwiftGenerator : public BaseGenerator { case BASE_TYPE_VECTOR: return GenType(type.VectorType()); case BASE_TYPE_STRUCT: { auto &struct_ = *type.struct_def; - if (should_consider_suffix) { + if (should_consider_suffix && !struct_.fixed) { return WrapInNameSpace(struct_.defined_namespace, ObjectAPIName(Name(struct_))); } @@ -1463,6 +1544,8 @@ class SwiftGenerator : public BaseGenerator { return keywords_.find(name) == keywords_.end() ? name : name + "_"; } + std::string Mutable() const { return "_Mutable"; } + std::string Name(const EnumVal &ev) const { auto name = ev.name; if (isupper(name.front())) { diff --git a/swift/FlatBuffers.podspec b/swift/FlatBuffers.podspec index b106b4c..5fdcb37 100644 --- a/swift/FlatBuffers.podspec +++ b/swift/FlatBuffers.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FlatBuffers' - s.version = '0.8.1' + s.version = '1.0.0' s.summary = 'FlatBuffers: Memory Efficient Serialization Library' s.description = "FlatBuffers is a cross platform serialization library architected for diff --git a/swift/README.md b/swift/README.md index c3060fd..1b90ab6 100644 --- a/swift/README.md +++ b/swift/README.md @@ -10,7 +10,7 @@ and Cocoapods 1- To report any error please use the main repository. -2- `0.6.0` deprecates `add(condition:bool)` for `add(element:bool)`. You can download the [binary here](https://github.com/google/flatbuffers/actions) and select the latest push to master +2- `1.0.0` deprecates `MyGame_Example_Vec3.createVec3(builder: &fbb, x: 10, test2: .blue)` for `MyGame_Example_Vec3(x: 10, test2: .blue)`. This uses Swift native structs instead of workarounds that which leads to a huge performance increase when serializing structs. You can download the [binary here](https://github.com/google/flatbuffers/actions) and select the latest push to master ### Contribute diff --git a/swift/Sources/FlatBuffers/ByteBuffer.swift b/swift/Sources/FlatBuffers/ByteBuffer.swift index 7df41a7..17c1a87 100644 --- a/swift/Sources/FlatBuffers/ByteBuffer.swift +++ b/swift/Sources/FlatBuffers/ByteBuffer.swift @@ -187,7 +187,7 @@ public struct ByteBuffer { _writerSize = _writerSize &+ (MemoryLayout.size &* padding) } - ///Adds an array of type Scalar to the buffer memory + /// Adds an array of type Scalar to the buffer memory /// - Parameter elements: An array of Scalars @usableFromInline mutating func push(elements: [T]) { @@ -198,41 +198,16 @@ public struct ByteBuffer { } } - /// A custom type of structs that are padded according to the flatbuffer padding, + /// Adds an object of type NativeStruct into the buffer /// - Parameters: - /// - value: Pointer to the object in memory - /// - size: Size of Value being written to the buffer - @available( - *, - deprecated, - message: "0.9.0 will be removing the following method. Regenerate the code") - @usableFromInline - mutating func push(struct value: UnsafeMutableRawPointer, size: Int) { - ensureSpace(size: size) - memcpy(_storage.memory.advanced(by: writerIndex &- size), value, size) - defer { value.deallocate() } - _writerSize = _writerSize &+ size - } - - /// Prepares the buffer to receive a struct of certian size. - /// The alignment of the memory is already handled since we already called preAlign - /// - Parameter size: size of the struct - @usableFromInline - mutating func prepareBufferToReceiveStruct(of size: Int) { + /// - value: Object that will be written to the buffer + /// - size: size to subtract from the WriterIndex + @inline(__always) + mutating func push(struct value: T, size: Int) { ensureSpace(size: size) - _writerSize = _writerSize &+ size - } - - /// Reverse the input direction to the buffer, since `FlatBuffers` uses a back to front, following method will take current `writerIndex` - /// and writes front to back into the buffer, respecting the padding & the alignment - /// - Parameters: - /// - value: value of type Scalar - /// - position: position relative to the `writerIndex` - /// - len: length of the value in terms of bytes - @usableFromInline - mutating func reversePush(value: T, position: Int, len: Int) { var v = value - memcpy(_storage.memory.advanced(by: writerIndex &+ position), &v, len) + memcpy(_storage.memory.advanced(by: writerIndex &- size), &v, size) + _writerSize = _writerSize &+ size } /// Adds an object of type Scalar into the buffer @@ -266,7 +241,7 @@ public struct ByteBuffer { /// - Parameters: /// - bytes: Pointer to the view /// - len: Size of string - @usableFromInline + @inline(__always) mutating internal func push( bytes: UnsafeBufferPointer, len: Int) -> Bool @@ -300,7 +275,7 @@ public struct ByteBuffer { /// Makes sure that buffer has enouch space for each of the objects that will be written into it /// - Parameter size: size of object @discardableResult - @usableFromInline + @inline(__always) mutating func ensureSpace(size: Int) -> Int { if size &+ _writerSize > _storage.capacity { _storage.reallocate(size, writerSize: _writerSize, alignment: alignment) @@ -311,7 +286,7 @@ public struct ByteBuffer { /// pops the written VTable if it's already written into the buffer /// - Parameter size: size of the `VTable` - @usableFromInline + @inline(__always) mutating internal func pop(_ size: Int) { assert((_writerSize &- size) > 0, "New size should NOT be a negative number") memset(_storage.memory.advanced(by: writerIndex), 0, _writerSize &- size) @@ -319,11 +294,13 @@ public struct ByteBuffer { } /// Clears the current size of the buffer + @inline(__always) mutating public func clearSize() { _writerSize = 0 } /// Clears the current instance of the buffer, replacing it with new memory + @inline(__always) mutating public func clear() { _writerSize = 0 alignment = 1 @@ -345,6 +322,7 @@ public struct ByteBuffer { /// - Parameters: /// - index: index of the object to be read from the buffer /// - count: count of bytes in memory + @inline(__always) public func readSlice( index: Int32, count: Int32) -> [T] @@ -362,6 +340,7 @@ public struct ByteBuffer { /// - index: index of the string in the buffer /// - count: length of the string /// - type: Encoding of the string + @inline(__always) public func readString( at index: Int32, count: Int32, diff --git a/swift/Sources/FlatBuffers/FlatBufferBuilder.swift b/swift/Sources/FlatBuffers/FlatBufferBuilder.swift index 71fcab0..64f267b 100644 --- a/swift/Sources/FlatBuffers/FlatBufferBuilder.swift +++ b/swift/Sources/FlatBuffers/FlatBufferBuilder.swift @@ -20,11 +20,11 @@ public struct FlatBufferBuilder { /// Storage for the Vtables used in the buffer are stored in here, so they would be written later in EndTable @usableFromInline internal var _vtableStorage = VTableStorage() + /// Flatbuffer data will be written into + @usableFromInline internal var _bb: ByteBuffer /// Reference Vtables that were already written to the buffer private var _vtables: [UOffset] = [] - /// Flatbuffer data will be written into - private var _bb: ByteBuffer /// A check if the buffer is being written into by a different table private var isNested = false /// Dictonary that stores a map of all the strings that were written to the buffer @@ -227,7 +227,7 @@ public struct FlatBufferBuilder { /// Changes the minimuim alignment of the buffer /// - Parameter size: size of the current alignment - @usableFromInline + @inline(__always) mutating internal func minAlignment(size: Int) { if size > _minAlignment { _minAlignment = size @@ -238,7 +238,7 @@ public struct FlatBufferBuilder { /// - Parameters: /// - bufSize: Current size of the buffer + the offset of the object to be written /// - elementSize: Element size - @usableFromInline + @inline(__always) mutating internal func padding(bufSize: UInt32, elementSize: UInt32) -> UInt32 { ((~bufSize) &+ 1) & (elementSize - 1) } @@ -282,7 +282,7 @@ public struct FlatBufferBuilder { _vtableStorage.add(loc: FieldLoc(offset: offset, position: position)) } - // MARK: - Vectors + // MARK: - Inserting Vectors /// Starts a vector of length and Element size mutating public func startVector(_ len: Int, elementSize: Int) { @@ -296,10 +296,10 @@ public struct FlatBufferBuilder { /// /// The current function will fatalError if startVector is called before serializing the vector /// - Parameter len: Length of the buffer - mutating public func endVector(len: Int) -> UOffset { + mutating public func endVector(len: Int) -> Offset { assert(isNested, "Calling endVector without calling startVector") isNested = false - return push(element: Int32(len)) + return Offset(offset: push(element: Int32(len))) } /// Creates a vector of type Scalar in the buffer @@ -317,7 +317,7 @@ public struct FlatBufferBuilder { let size = size startVector(size, elementSize: MemoryLayout.size) _bb.push(elements: elements) - return Offset(offset: endVector(len: size)) + return endVector(len: size) } /// Creates a vector of type Enums in the buffer @@ -337,7 +337,7 @@ public struct FlatBufferBuilder { for e in elements.reversed() { _bb.push(value: e.value, len: T.byteSize) } - return Offset(offset: endVector(len: size)) + return endVector(len: size) } /// Creates a vector of type Offsets in the buffer @@ -356,7 +356,7 @@ public struct FlatBufferBuilder { for o in offsets.reversed() { push(element: o) } - return Offset(offset: endVector(len: len)) + return endVector(len: len) } /// Creates a vector of Strings @@ -370,99 +370,45 @@ public struct FlatBufferBuilder { return createVector(ofOffsets: offsets) } - /// Creates a vector of Flatbuffer structs. - /// - /// The function takes a Type to know what size it is, and alignment - /// - Parameters: - /// - structs: An array of UnsafeMutableRawPointer - /// - type: Type of the struct being written - /// - returns: Offset of the vector - @available( - *, - deprecated, - message: "0.9.0 will be removing the following method. Regenerate the code") - mutating public func createVector( - structs: [UnsafeMutableRawPointer], - type: T.Type) -> Offset - { - startVector(structs.count &* T.size, elementSize: T.alignment) + /// Creates a vector of `Native swift structs` which were padded to flatbuffers standards + /// - Parameter structs: A vector of structs + /// - Returns: offset of the vector + mutating public func createVector(ofStructs structs: [T]) -> Offset { + startVector(structs.count * MemoryLayout.size, elementSize: MemoryLayout.alignment) for i in structs.reversed() { - create(struct: i, type: T.self) + _ = create(struct: i) } - return Offset(offset: endVector(len: structs.count)) - } - - /// Starts a vector of struct that considers the size and alignment of the struct - /// - Parameters: - /// - count: number of elements to be written - /// - size: size of struct - /// - alignment: alignment of the struct - mutating public func startVectorOfStructs(count: Int, size: Int, alignment: Int) { - startVector(count &* size, elementSize: alignment) - } - - /// Ends the vector of structs and writtens the current offset - /// - Parameter count: number of written elements - /// - Returns: Offset of type UOffset - mutating public func endVectorOfStructs(count: Int) -> Offset { - Offset(offset: endVector(len: count)) + return endVector(len: structs.count) } // MARK: - Inserting Structs - /// Writes a Flatbuffer struct into the buffer + /// Fills the buffer with a native struct that's build and padded according to flatbuffers standards /// - Parameters: - /// - s: Flatbuffer struct - /// - type: Type of the element to be serialized - /// - returns: Offset of the Object - @available( - *, - deprecated, - message: "0.9.0 will be removing the following method. Regenerate the code") + /// - s: `Native swift` struct to insert + /// - position: The predefined position of the object + /// - Returns: offset of written struct @discardableResult - mutating public func create( - struct s: UnsafeMutableRawPointer, - type: T.Type) -> Offset + mutating public func create( + struct s: T, position: VOffset) -> Offset { - let size = T.size - preAlign(len: size, alignment: T.alignment) - _bb.push(struct: s, size: size) - return Offset(offset: _bb.size) - } - - /// prepares the ByteBuffer to receive a struct of size and alignment - /// - Parameters: - /// - size: size of written struct - /// - alignment: alignment of written struct - mutating public func createStructOf(size: Int, alignment: Int) { - preAlign(len: size, alignment: alignment) - _bb.prepareBufferToReceiveStruct(of: size) + let offset = create(struct: s) + _vtableStorage.add(loc: FieldLoc(offset: _bb.size, position: VOffset(position))) + return offset } - /// Adds scalars front to back instead of the default behavior of the normal add + /// Fills the buffer with a native struct that's build and padded according to flatbuffers standards /// - Parameters: - /// - v: element of type Scalar - /// - postion: position relative to the `writerIndex` - mutating public func reverseAdd(v: T, postion: Int) { - _bb.reversePush( - value: v, - position: postion, - len: MemoryLayout.size) - } - - /// Ends the struct and returns the current buffer size - /// - Returns: Offset of type UOffset + /// - s: `Native swift` struct to insert + /// - Returns: offset of written struct @discardableResult - public func endStruct() -> Offset { - Offset(offset: _bb.size) - } - - /// Adds the offset of a struct into the vTable - /// - /// The function fatalErrors if we pass an offset that is out of range - /// - Parameter o: offset - mutating public func add(structOffset o: VOffset) { - _vtableStorage.add(loc: FieldLoc(offset: _bb.size, position: VOffset(o))) + mutating public func create( + struct s: T) -> Offset + { + let size = MemoryLayout.size + preAlign(len: size, alignment: MemoryLayout.alignment) + _bb.push(struct: s, size: size) + return Offset(offset: _bb.size) } // MARK: - Inserting Strings @@ -596,6 +542,7 @@ extension FlatBufferBuilder: CustomDebugStringConvertible { /// Builds a buffer with byte count of fieldloc.size * count of field numbers /// - Parameter count: number of fields to be written + @inline(__always) func start(count: Int) { assert(count >= 0, "number of fields should NOT be negative") let capacity = count &* size @@ -621,6 +568,7 @@ extension FlatBufferBuilder: CustomDebugStringConvertible { /// Ensure that the buffer has enough space instead of recreating the buffer each time. /// - Parameter space: space required for the new vtable + @inline(__always) func ensure(space: Int) { guard space &+ writtenIndex > capacity else { return } memory.deallocate() @@ -631,6 +579,7 @@ extension FlatBufferBuilder: CustomDebugStringConvertible { /// Loads an object of type `FieldLoc` from buffer memory /// - Parameter index: index of element /// - Returns: a FieldLoc at index + @inline(__always) func load(at index: Int) -> FieldLoc { memory.load(fromByteOffset: index, as: FieldLoc.self) } diff --git a/swift/Sources/FlatBuffers/FlatBufferObject.swift b/swift/Sources/FlatBuffers/FlatBufferObject.swift index 7536c40..fb7408b 100644 --- a/swift/Sources/FlatBuffers/FlatBufferObject.swift +++ b/swift/Sources/FlatBuffers/FlatBufferObject.swift @@ -16,6 +16,10 @@ import Foundation +/// NativeStruct is a protocol that indicates if the struct is a native `swift` struct +/// since now we will be serializing native structs into the buffer. +public protocol NativeStruct {} + /// FlatbufferObject structures all the Flatbuffers objects public protocol FlatBufferObject { var __buffer: ByteBuffer! { get } @@ -28,15 +32,6 @@ public protocol ObjectAPI { mutating func unpack() -> T } -/// Readable is structures all the Flatbuffers structs -/// -/// Readable is a procotol that each Flatbuffer struct should confirm to since -/// FlatBufferBuilder would require a Type to both create(struct:) and createVector(structs:) functions -public protocol Readable: FlatBufferObject { - static var size: Int { get } - static var alignment: Int { get } -} - public protocol Enum { associatedtype T: Scalar static var byteSize: Int { get } diff --git a/swift/Sources/FlatBuffers/Table.swift b/swift/Sources/FlatBuffers/Table.swift index 451398c..44bbe38 100644 --- a/swift/Sources/FlatBuffers/Table.swift +++ b/swift/Sources/FlatBuffers/Table.swift @@ -56,9 +56,9 @@ public struct Table { /// Reads from the buffer with respect to the position in the table. /// - Parameters: - /// - type: Type of Scalar that needs to be read from the buffer + /// - type: Type of Element that needs to be read from the buffer /// - o: Offset of the Element - public func readBuffer(of type: T.Type, at o: Int32) -> T { + public func readBuffer(of type: T.Type, at o: Int32) -> T { directRead(of: T.self, offset: o + postion) } @@ -73,9 +73,9 @@ public struct Table { /// offset: __t.vector(at: offset) + index * 1) /// ``` /// - Parameters: - /// - type: Type of Scalar that needs to be read from the buffer + /// - type: Type of Element that needs to be read from the buffer /// - o: Offset of the Element - public func directRead(of type: T.Type, offset o: Int32) -> T { + public func directRead(of type: T.Type, offset o: Int32) -> T { let r = bb.read(def: T.self, position: Int(o)) return r } diff --git a/swift/Sources/FlatBuffers/NativeTable.swift b/swift/Sources/FlatBuffers/UnionObject.swift similarity index 97% rename from swift/Sources/FlatBuffers/NativeTable.swift rename to swift/Sources/FlatBuffers/UnionObject.swift index 5c844c1..fa45e91 100644 --- a/swift/Sources/FlatBuffers/NativeTable.swift +++ b/swift/Sources/FlatBuffers/UnionObject.swift @@ -16,9 +16,9 @@ import Foundation -public protocol NativeTable {} +public protocol UnionObject {} -extension NativeTable { +extension UnionObject { /// Serialize is a helper function that serailizes the data from the Object API to a bytebuffer directly th /// - Parameter type: Type of the Flatbuffer object diff --git a/tests/FlatBuffers.Benchmarks.swift/Sources/FlatBuffers.Benchmarks.swift/main.swift b/tests/FlatBuffers.Benchmarks.swift/Sources/FlatBuffers.Benchmarks.swift/main.swift index fed3f2d..1ec5bb4 100644 --- a/tests/FlatBuffers.Benchmarks.swift/Sources/FlatBuffers.Benchmarks.swift/main.swift +++ b/tests/FlatBuffers.Benchmarks.swift/Sources/FlatBuffers.Benchmarks.swift/main.swift @@ -89,14 +89,11 @@ func benchmarkThreeMillionStructs() { var offsets: [Offset] = [] for _ in 0...size, elementSize: MemoryLayout.alignment) for _ in 0..<5 { - fb.createStructOf(size: 16, alignment: 8) - fb.reverseAdd(v: 2.4, postion: 0) - fb.reverseAdd(v: 2.4, postion: 8) - fb.endStruct() + _ = fb.create(struct: AA(a: 2.4, b: 2.4)) } - let vector = fb.endVectorOfStructs(count: 5) + let vector = fb.endVector(len: 5) let start = fb.startTable(with: 1) fb.add(offset: vector, at: 4) offsets.append(Offset(offset: fb.endTable(at: start))) @@ -108,6 +105,17 @@ func benchmarkThreeMillionStructs() { fb.finish(offset: root) } +@usableFromInline +struct AA: NativeStruct { + public init(a: Double, b: Double) { + self.a = a + self.b = b + } + var a: Double + var b: Double + +} + func benchmark(numberOfRuns runs: Int) { var benchmarks: [Benchmark] = [] let str = (0...99).map { _ -> String in "x" }.joined() diff --git a/tests/FlatBuffers.Test.Swift/SwiftTest.sh b/tests/FlatBuffers.Test.Swift/SwiftTest.sh index 43c82bf..5e2916c 100755 --- a/tests/FlatBuffers.Test.Swift/SwiftTest.sh +++ b/tests/FlatBuffers.Test.Swift/SwiftTest.sh @@ -1,7 +1,7 @@ swift_dir=`pwd` cd .. test_dir=`pwd` -alias fbc='${test_dir}/../debug/flatc' +alias fbc='${test_dir}/../flatc' cd FlatBuffers.GRPC.Swift/Sources/Model fbc --swift --grpc greeter.fbs diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift index f37f2b8..fb49e48 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift @@ -77,7 +77,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase { var fbb = FlatBufferBuilder(initialSize: 1) let name = fbb.create(string: "Barney") let mStart = Monster.startMonster(&fbb) - Monster.add(pos: MyGame_Example_Vec3.createVec3(builder: &fbb, x: 10, test2: .blue), &fbb) + Monster.add(pos: MyGame_Example_Vec3(x: 10, y: 0, z: 0, test1: 0, test2: .blue, test3: .init()), &fbb) Monster.add(name: name, &fbb) let root = Monster.endMonster(&fbb, start: mStart) fbb.finish(offset: root) @@ -136,16 +136,14 @@ class FlatBuffersMonsterWriterTests: XCTestCase { Monster.add(name: fred, &fbb) let mon2 = Monster.endMonster(&fbb, start: mon1Start) - let size = 2 - Monster.startVectorOfTest4(size, in: &fbb) - MyGame_Example_Test.createTest(builder: &fbb, a: 10, b: 20) - MyGame_Example_Test.createTest(builder: &fbb, a: 30, b: 40) - let test4 = fbb.endVectorOfStructs(count: size) + let test4 = fbb.createVector(ofStructs: [ + MyGame_Example_Test(a: 30, b: 40), + MyGame_Example_Test(a: 10, b: 20), + ]) let stringTestVector = fbb.createVector(ofOffsets: [test1, test2]) let mStart = Monster.startMonster(&fbb) - let posStruct = MyGame_Example_Vec3.createVec3(builder: &fbb, x: 1, y: 2, z: 3, test1: 3, test2: .green, test3a: 5, test3b: 6) - Monster.add(pos: posStruct, &fbb) + Monster.add(pos: MyGame_Example_Vec3(x: 1, y: 2, z: 3, test1: 3, test2: .green, test3: .init(a: 5, b: 6)), &fbb) Monster.add(hp: 80, &fbb) Monster.add(name: str, &fbb) Monster.addVectorOf(inventory: inv, &fbb) @@ -190,7 +188,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase { XCTAssertEqual(monster.mutate(inventory: 3, at: 3), true) XCTAssertEqual(monster.mutate(inventory: 4, at: 4), true) - let vec = monster.pos + let vec = monster.mutablePos XCTAssertEqual(vec?.x, 1) XCTAssertTrue(vec?.mutate(x: 55.0) ?? false) XCTAssertTrue(vec?.mutate(test1: 55) ?? false) @@ -228,6 +226,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase { } XCTAssertEqual(sum, 10) XCTAssertEqual(monster.test4Count, 2) + let test0 = monster.test4(at: 0) let test1 = monster.test4(at: 1) var sum0 = 0 @@ -239,6 +238,19 @@ class FlatBuffersMonsterWriterTests: XCTestCase { sum1 = Int(a) + Int(b) } XCTAssertEqual(sum0 + sum1, 100) + + let mutableTest0 = monster.mutableTest4(at: 0) + let mutableTest1 = monster.mutableTest4(at: 1) + var sum2 = 0 + var sum3 = 0 + if let a = mutableTest0?.a, let b = mutableTest0?.b { + sum2 = Int(a) + Int(b) + } + if let a = mutableTest1?.a, let b = mutableTest1?.b { + sum3 = Int(a) + Int(b) + } + XCTAssertEqual(sum2 + sum3, 100) + XCTAssertEqual(monster.testarrayofstringCount, 2) XCTAssertEqual(monster.testarrayofstring(at: 0), "test1") XCTAssertEqual(monster.testarrayofstring(at: 1), "test2") diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersStructsTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersStructsTests.swift index 2c344f0..cdde364 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersStructsTests.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersStructsTests.swift @@ -22,12 +22,12 @@ final class FlatBuffersStructsTests: XCTestCase { func testWritingAndMutatingBools() { var fbb = FlatBufferBuilder() let start = TestMutatingBool.startTestMutatingBool(&fbb) - TestMutatingBool.add(b: createProperty(builder: &fbb), &fbb) + TestMutatingBool.add(b: Property(property: false), &fbb) let root = TestMutatingBool.endTestMutatingBool(&fbb, start: start) fbb.finish(offset: root) let testMutatingBool = TestMutatingBool.getRootAsTestMutatingBool(bb: fbb.sizedBuffer) - let property = testMutatingBool.b + let property = testMutatingBool.mutableB XCTAssertEqual(property?.property, false) property?.mutate(property: false) XCTAssertEqual(property?.property, false) @@ -37,23 +37,8 @@ final class FlatBuffersStructsTests: XCTestCase { } -struct Vec: Readable { - var __buffer: ByteBuffer! { __p.bb } - - static var size = 12 - static var alignment = 4 - private var __p: Struct - init(_ fb: ByteBuffer, o: Int32) { __p = Struct(bb: fb, position: o) } - var x: Float32 { __p.readBuffer(of: Float32.self, at: 0)} - var y: Float32 { __p.readBuffer(of: Float32.self, at: 4)} - var z: Float32 { __p.readBuffer(of: Float32.self, at: 8)} -} - -@discardableResult -func createVecWrite(builder: inout FlatBufferBuilder, x: Float32, y: Float32, z: Float32) -> Offset { - builder.createStructOf(size: Vec.size, alignment: Vec.alignment) - builder.reverseAdd(v: x, postion: 0) - builder.reverseAdd(v: y, postion: 4) - builder.reverseAdd(v: z, postion: 8) - return builder.endStruct() +struct Vec: NativeStruct { + var x: Float32 + var y: Float32 + var z: Float32 } diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersUnionTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersUnionTests.swift index 0802272..e401d4e 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersUnionTests.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersUnionTests.swift @@ -55,13 +55,13 @@ final class FlatBuffersUnionTests: XCTestCase { let inventory: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] let inv = builder.createVector(inventory, size: 10) let weapons = builder.createVector(ofOffsets: [weaponOne, weaponTwo]) - builder.startVectorOfStructs(count: 2, size: Vec.size, alignment: Vec.alignment) - createVecWrite(builder: &builder, x: 1.0, y: 2.0, z: 3.0) - createVecWrite(builder: &builder, x: 4.0, y: 5.0, z: 6.0) - let path = builder.endVectorOfStructs(count: 2) + let path = builder.createVector(ofStructs: [ + Vec(x: 4.0, y: 5.0, z: 6.0), + Vec(x: 1.0, y: 2.0, z: 3.0), + ]) let orc = FinalMonster.createMonster( builder: &builder, - position: createVecWrite(builder: &builder, x: 1.0, y: 2.0, z: 3.0), + position: Vec(x: 1, y: 2, z: 3), hp: 300, name: name, inventory: inv, @@ -71,7 +71,7 @@ final class FlatBuffersUnionTests: XCTestCase { equippedOffset: weaponTwo, path: path) builder.finish(offset: orc) - XCTAssertEqual(builder.sizedByteArray, [32, 0, 0, 0, 0, 0, 26, 0, 36, 0, 36, 0, 0, 0, 34, 0, 28, 0, 0, 0, 24, 0, 23, 0, 16, 0, 15, 0, 8, 0, 4, 0, 26, 0, 0, 0, 44, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 76, 0, 0, 0, 0, 0, 44, 1, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 0, 0, 0, 0, 128, 64, 0, 0, 160, 64, 0, 0, 192, 64, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 0, 0, 52, 0, 0, 0, 28, 0, 0, 0, 10, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 3, 0, 0, 0, 79, 114, 99, 0, 244, 255, 255, 255, 0, 0, 5, 0, 24, 0, 0, 0, 8, 0, 12, 0, 8, 0, 6, 0, 8, 0, 0, 0, 0, 0, 3, 0, 12, 0, 0, 0, 3, 0, 0, 0, 65, 120, 101, 0, 5, 0, 0, 0, 83, 119, 111, 114, 100, 0, 0, 0]) + XCTAssertEqual(builder.sizedByteArray, [32, 0, 0, 0, 0, 0, 26, 0, 48, 0, 36, 0, 0, 0, 34, 0, 28, 0, 0, 0, 24, 0, 23, 0, 16, 0, 15, 0, 8, 0, 4, 0, 26, 0, 0, 0, 44, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 76, 0, 0, 0, 0, 0, 44, 1, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 0, 0, 0, 0, 128, 64, 0, 0, 160, 64, 0, 0, 192, 64, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 0, 0, 52, 0, 0, 0, 28, 0, 0, 0, 10, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 3, 0, 0, 0, 79, 114, 99, 0, 244, 255, 255, 255, 0, 0, 5, 0, 24, 0, 0, 0, 8, 0, 12, 0, 8, 0, 6, 0, 8, 0, 0, 0, 0, 0, 3, 0, 12, 0, 0, 0, 3, 0, 0, 0, 65, 120, 101, 0, 5, 0, 0, 0, 83, 119, 111, 114, 100, 0, 0, 0]) } func testEnumVector() { @@ -101,9 +101,9 @@ final class FlatBuffersUnionTests: XCTestCase { let characterType: [Character] = [.belle, .mulan, .bookfan] let characters = [ - BookReader.createBookReader(builder: &fb, booksRead: 7), + fb.create(struct: BookReader(booksRead: 7)), attack, - BookReader.createBookReader(builder: &fb, booksRead: 2), + fb.create(struct: BookReader(booksRead: 2)), ] let types = fb.createVector(characterType) let characterVector = fb.createVector(ofOffsets: characters) @@ -118,22 +118,22 @@ final class FlatBuffersUnionTests: XCTestCase { XCTAssertEqual(movie.charactersType(at: i), characterType[Int(i)]) } - XCTAssertEqual(movie.characters(at: 0, type: BookReader.self)?.booksRead, 7) + XCTAssertEqual(movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, 7) XCTAssertEqual(movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage, swordDmg) - XCTAssertEqual(movie.characters(at: 2, type: BookReader.self)?.booksRead, 2) + XCTAssertEqual(movie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead, 2) var objc: MovieT? = movie.unpack() XCTAssertEqual(movie.charactersTypeCount, Int32(objc?.characters.count ?? 0)) - XCTAssertEqual(movie.characters(at: 0, type: BookReader.self)?.booksRead, (objc?.characters[0]?.value as? BookReaderT)?.booksRead) + XCTAssertEqual(movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, (objc?.characters[0]?.value as? BookReader)?.booksRead) fb.clear() let newMovie = Movie.pack(&fb, obj: &objc) fb.finish(offset: newMovie) let packedMovie = Movie.getRootAsMovie(bb: fb.buffer) - XCTAssertEqual(packedMovie.characters(at: 0, type: BookReader.self)?.booksRead, movie.characters(at: 0, type: BookReader.self)?.booksRead) + XCTAssertEqual(packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead) XCTAssertEqual(packedMovie.characters(at: 1, type: Attacker.self)?.swordAttackDamage, movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage) - XCTAssertEqual(packedMovie.characters(at: 2, type: BookReader.self)?.booksRead, movie.characters(at: 2, type: BookReader.self)?.booksRead) + XCTAssertEqual(packedMovie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead, movie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead) } } @@ -179,7 +179,7 @@ struct FinalMonster { @inlinable static func createMonster( builder: inout FlatBufferBuilder, - position: Offset, + position: Vec, hp: Int16, name: Offset, inventory: Offset, @@ -190,7 +190,7 @@ struct FinalMonster { path: Offset) -> Offset { let start = builder.startTable(with: 11) - builder.add(structOffset: 4) + builder.create(struct: position, position: 4) builder.add(element: hp, def: 100, at: 8) builder.add(offset: name, at: 10) builder.add(offset: inventory, at: 14) diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/MutatingBool_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/MutatingBool_generated.swift index d51f3d9..7fc9ed2 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/MutatingBool_generated.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/MutatingBool_generated.swift @@ -2,7 +2,14 @@ import FlatBuffers -public struct Property: Readable { +public struct Property: NativeStruct { + + static func validateVersion() { FlatBuffersVersion_1_12_0() } + + public var property: Bool +} + +public struct Property_Mutable: FlatBufferObject { static func validateVersion() { FlatBuffersVersion_1_12_0() } public var __buffer: ByteBuffer! { return _accessor.bb } @@ -16,12 +23,6 @@ public struct Property: Readable { @discardableResult public func mutate(property: Bool) -> Bool { return _accessor.mutate(property, index: 0) } } -public func createProperty(builder: inout FlatBufferBuilder, property: Bool = false) -> Offset { - builder.createStructOf(size: Property.size, alignment: Property.alignment) - builder.reverseAdd(v: property, postion: 0) - return builder.endStruct() -} - public struct TestMutatingBool: FlatBufferObject { static func validateVersion() { FlatBuffersVersion_1_12_0() } @@ -39,9 +40,10 @@ public struct TestMutatingBool: FlatBufferObject { var p: VOffset { self.rawValue } } - public var b: Property? { let o = _accessor.offset(VTOFFSET.b.v); return o == 0 ? nil : Property(_accessor.bb, o: o + _accessor.postion) } + public var b: Property? { let o = _accessor.offset(VTOFFSET.b.v); return o == 0 ? nil : _accessor.readBuffer(of: Property.self, at: o) } + public var mutableB: Property_Mutable? { let o = _accessor.offset(VTOFFSET.b.v); return o == 0 ? nil : Property_Mutable(_accessor.bb, o: o + _accessor.postion) } public static func startTestMutatingBool(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) } - public static func add(b: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(structOffset: VTOFFSET.b.p) } + public static func add(b: Property?, _ fbb: inout FlatBufferBuilder) { guard let b = b else { return }; _ = fbb.create(struct: b, position: VTOFFSET.b.p) } public static func endTestMutatingBool(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end } } diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift index 8459ee5..e869acb 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift @@ -35,17 +35,11 @@ extension FlatBuffersMonsterWriterTests { ("testCreateMonster", testCreateMonster), ("testCreateMonsterPrefixed", testCreateMonsterPrefixed), ("testCreateMonsterResizedBuffer", testCreateMonsterResizedBuffer), - ( - "testCreateMonsterUsingCreateMonsterMethodWithNilPos", - testCreateMonsterUsingCreateMonsterMethodWithNilPos), - ( - "testCreateMonsterUsingCreateMonsterMethodWithPosX", - testCreateMonsterUsingCreateMonsterMethodWithPosX), + ("testCreateMonsterUsingCreateMonsterMethodWithNilPos", testCreateMonsterUsingCreateMonsterMethodWithNilPos), + ("testCreateMonsterUsingCreateMonsterMethodWithPosX", testCreateMonsterUsingCreateMonsterMethodWithPosX), ("testData", testData), ("testReadFromOtherLanguages", testReadFromOtherLanguages), - ( - "testReadMonsterFromUnsafePointerWithoutCopying", - testReadMonsterFromUnsafePointerWithoutCopying), + ("testReadMonsterFromUnsafePointerWithoutCopying", testReadMonsterFromUnsafePointerWithoutCopying), ] } diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift index b15eddf..d3ed40d 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift @@ -51,8 +51,8 @@ public enum MyGame_Example_Any_: UInt8, Enum { public struct MyGame_Example_Any_Union { public var type: MyGame_Example_Any_ - public var value: NativeTable? - public init(_ v: NativeTable?, type: MyGame_Example_Any_) { + public var value: UnionObject? + public init(_ v: UnionObject?, type: MyGame_Example_Any_) { self.type = type self.value = v } @@ -87,8 +87,8 @@ public enum MyGame_Example_AnyUniqueAliases: UInt8, Enum { public struct MyGame_Example_AnyUniqueAliasesUnion { public var type: MyGame_Example_AnyUniqueAliases - public var value: NativeTable? - public init(_ v: NativeTable?, type: MyGame_Example_AnyUniqueAliases) { + public var value: UnionObject? + public init(_ v: UnionObject?, type: MyGame_Example_AnyUniqueAliases) { self.type = type self.value = v } @@ -123,8 +123,8 @@ public enum MyGame_Example_AnyAmbiguousAliases: UInt8, Enum { public struct MyGame_Example_AnyAmbiguousAliasesUnion { public var type: MyGame_Example_AnyAmbiguousAliases - public var value: NativeTable? - public init(_ v: NativeTable?, type: MyGame_Example_AnyAmbiguousAliases) { + public var value: UnionObject? + public init(_ v: UnionObject?, type: MyGame_Example_AnyAmbiguousAliases) { self.type = type self.value = v } @@ -143,14 +143,39 @@ public struct MyGame_Example_AnyAmbiguousAliasesUnion { } } } -public struct MyGame_Example_Test: Readable { +public struct MyGame_Example_Test: NativeStruct, UnionObject { + + static func validateVersion() { FlatBuffersVersion_1_12_0() } + + private var _a: Int16 + private var _b: Int8 + private let padding0__: UInt8 = 0 + + public init(a: Int16, b: Int8) { + _a = a + _b = b + } + + public init() { + _a = 0 + _b = 0 + } + + public init(_ _t: inout MyGame_Example_Test_Mutable) { + _a = _t.a + _b = _t.b + } + + public var a: Int16 { _a } + public var b: Int8 { _b } +} + +public struct MyGame_Example_Test_Mutable: FlatBufferObject { static func validateVersion() { FlatBuffersVersion_1_12_0() } public var __buffer: ByteBuffer! { return _accessor.bb } private var _accessor: Struct - public static var size = 4 - public static var alignment = 2 public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) } public var a: Int16 { return _accessor.readBuffer(of: Int16.self, at: 0) } @@ -159,43 +184,75 @@ public struct MyGame_Example_Test: Readable { @discardableResult public func mutate(b: Int8) -> Bool { return _accessor.mutate(b, index: 2) } - public mutating func unpack() -> MyGame_Example_TestT { - return MyGame_Example_TestT(&self) + public mutating func unpack() -> MyGame_Example_Test { + return MyGame_Example_Test(&self) } - public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_TestT?) -> Offset { + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Test?) -> Offset { guard var obj = obj else { return Offset() } return pack(&builder, obj: &obj) } - public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_TestT) -> Offset { - return createTest(builder: &builder, a: obj.a, b: obj.b) + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Test) -> Offset { + return builder.create(struct: obj) } } -public class MyGame_Example_TestT: NativeTable { +public struct MyGame_Example_Vec3: NativeStruct, UnionObject { - public var a: Int16 - public var b: Int8 + static func validateVersion() { FlatBuffersVersion_1_12_0() } - public init(_ _t: inout MyGame_Example_Test) { - a = _t.a - b = _t.b + private var _x: Float32 + private var _y: Float32 + private var _z: Float32 + private let padding0__: UInt32 = 0 + private var _test1: Double + private var _test2: UInt8 + private let padding1__: UInt8 = 0 + private var _test3: MyGame_Example_Test + private let padding2__: UInt16 = 0 + + public init(x: Float32, y: Float32, z: Float32, test1: Double, test2: MyGame_Example_Color, test3: MyGame_Example_Test) { + _x = x + _y = y + _z = z + _test1 = test1 + _test2 = test2.value + _test3 = test3 } public init() { - a = 0 - b = 0 - } - + _x = 0.0 + _y = 0.0 + _z = 0.0 + _test1 = 0.0 + _test2 = 0 + _test3 = MyGame_Example_Test() + } + + public init(_ _t: inout MyGame_Example_Vec3_Mutable) { + _x = _t.x + _y = _t.y + _z = _t.z + _test1 = _t.test1 + _test2 = _t.test2.value + var _v = _t.test3 + _test3 = _v.unpack() + } + + public var x: Float32 { _x } + public var y: Float32 { _y } + public var z: Float32 { _z } + public var test1: Double { _test1 } + public var test2: MyGame_Example_Color { MyGame_Example_Color(rawValue: _test2)! } + public var test3: MyGame_Example_Test { _test3 } } -public struct MyGame_Example_Vec3: Readable { + +public struct MyGame_Example_Vec3_Mutable: FlatBufferObject { static func validateVersion() { FlatBuffersVersion_1_12_0() } public var __buffer: ByteBuffer! { return _accessor.bb } private var _accessor: Struct - public static var size = 32 - public static var alignment = 8 public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) } public var x: Float32 { return _accessor.readBuffer(of: Float32.self, at: 0) } @@ -207,59 +264,55 @@ public struct MyGame_Example_Vec3: Readable { public var test1: Double { return _accessor.readBuffer(of: Double.self, at: 16) } @discardableResult public func mutate(test1: Double) -> Bool { return _accessor.mutate(test1, index: 16) } public var test2: MyGame_Example_Color { return MyGame_Example_Color(rawValue: _accessor.readBuffer(of: UInt8.self, at: 24)) ?? .red } - public var test3: MyGame_Example_Test { return MyGame_Example_Test(_accessor.bb, o: _accessor.postion + 26) } + @discardableResult public func mutate(test2: MyGame_Example_Color) -> Bool { return _accessor.mutate(test2.rawValue, index: 24) } + public var test3: MyGame_Example_Test_Mutable { return MyGame_Example_Test_Mutable(_accessor.bb, o: _accessor.postion + 26) } - public mutating func unpack() -> MyGame_Example_Vec3T { - return MyGame_Example_Vec3T(&self) + public mutating func unpack() -> MyGame_Example_Vec3 { + return MyGame_Example_Vec3(&self) } - public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Vec3T?) -> Offset { + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Vec3?) -> Offset { guard var obj = obj else { return Offset() } return pack(&builder, obj: &obj) } - public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Vec3T) -> Offset { - return createVec3(builder: &builder, x: obj.x, y: obj.y, z: obj.z, test1: obj.test1, test2: obj.test2, test3a: obj.test3.a, test3b: obj.test3.b) + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Vec3) -> Offset { + return builder.create(struct: obj) } } -public class MyGame_Example_Vec3T: NativeTable { +public struct MyGame_Example_Ability: NativeStruct, UnionObject { + + static func validateVersion() { FlatBuffersVersion_1_12_0() } - public var x: Float32 - public var y: Float32 - public var z: Float32 - public var test1: Double - public var test2: MyGame_Example_Color - public var test3: MyGame_Example_TestT + private var _id: UInt32 + private var _distance: UInt32 - public init(_ _t: inout MyGame_Example_Vec3) { - x = _t.x - y = _t.y - z = _t.z - test1 = _t.test1 - test2 = _t.test2 - var __test3 = _t.test3 - test3 = __test3.unpack() + public init(id: UInt32, distance: UInt32) { + _id = id + _distance = distance } public init() { - x = 0.0 - y = 0.0 - z = 0.0 - test1 = 0.0 - test2 = .red - test3 = MyGame_Example_TestT() + _id = 0 + _distance = 0 + } + + public init(_ _t: inout MyGame_Example_Ability_Mutable) { + _id = _t.id + _distance = _t.distance } + public var id: UInt32 { _id } + public var distance: UInt32 { _distance } } -public struct MyGame_Example_Ability: Readable { + +public struct MyGame_Example_Ability_Mutable: FlatBufferObject { static func validateVersion() { FlatBuffersVersion_1_12_0() } public var __buffer: ByteBuffer! { return _accessor.bb } private var _accessor: Struct - public static var size = 8 - public static var alignment = 4 public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) } public var id: UInt32 { return _accessor.readBuffer(of: UInt32.self, at: 0) } @@ -268,73 +321,19 @@ public struct MyGame_Example_Ability: Readable { @discardableResult public func mutate(distance: UInt32) -> Bool { return _accessor.mutate(distance, index: 4) } - public mutating func unpack() -> MyGame_Example_AbilityT { - return MyGame_Example_AbilityT(&self) + public mutating func unpack() -> MyGame_Example_Ability { + return MyGame_Example_Ability(&self) } - public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_AbilityT?) -> Offset { + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Ability?) -> Offset { guard var obj = obj else { return Offset() } return pack(&builder, obj: &obj) } - public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_AbilityT) -> Offset { - return createAbility(builder: &builder, id: obj.id, distance: obj.distance) + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Ability) -> Offset { + return builder.create(struct: obj) } } -public class MyGame_Example_AbilityT: NativeTable { - - public var id: UInt32 - public var distance: UInt32 - - public init(_ _t: inout MyGame_Example_Ability) { - id = _t.id - distance = _t.distance - } - - public init() { - id = 0 - distance = 0 - } - -} -extension MyGame_Example_Test { - @discardableResult - public static func createTest(builder: inout FlatBufferBuilder, a: Int16 = 0, b: Int8 = 0) -> Offset { - builder.createStructOf(size: MyGame_Example_Test.size, alignment: MyGame_Example_Test.alignment) - builder.reverseAdd(v: a, postion: 0) - builder.reverseAdd(v: b, postion: 2) - return builder.endStruct() - } - -} - -extension MyGame_Example_Vec3 { - @discardableResult - public static func createVec3(builder: inout FlatBufferBuilder, x: Float32 = 0.0, y: Float32 = 0.0, z: Float32 = 0.0, test1: Double = 0.0, test2: MyGame_Example_Color, test3a: Int16 = 0, test3b: Int8 = 0) -> Offset { - builder.createStructOf(size: MyGame_Example_Vec3.size, alignment: MyGame_Example_Vec3.alignment) - builder.reverseAdd(v: x, postion: 0) - builder.reverseAdd(v: y, postion: 4) - builder.reverseAdd(v: z, postion: 8) - builder.reverseAdd(v: test1, postion: 16) - builder.reverseAdd(v: test2.rawValue, postion: 24) - builder.reverseAdd(v: test3a, postion: 26) - builder.reverseAdd(v: test3b, postion: 28) - return builder.endStruct() - } - -} - -extension MyGame_Example_Ability { - @discardableResult - public static func createAbility(builder: inout FlatBufferBuilder, id: UInt32 = 0, distance: UInt32 = 0) -> Offset { - builder.createStructOf(size: MyGame_Example_Ability.size, alignment: MyGame_Example_Ability.alignment) - builder.reverseAdd(v: id, postion: 0) - builder.reverseAdd(v: distance, postion: 4) - return builder.endStruct() - } - -} - public struct MyGame_InParentNamespace: FlatBufferObject, ObjectAPI { static func validateVersion() { FlatBuffersVersion_1_12_0() } @@ -365,7 +364,7 @@ public struct MyGame_InParentNamespace: FlatBufferObject, ObjectAPI { } } -public class MyGame_InParentNamespaceT: NativeTable { +public class MyGame_InParentNamespaceT: UnionObject { public init(_ _t: inout MyGame_InParentNamespace) { @@ -407,7 +406,7 @@ public struct MyGame_Example2_Monster: FlatBufferObject, ObjectAPI { } } -public class MyGame_Example2_MonsterT: NativeTable { +public class MyGame_Example2_MonsterT: UnionObject { public init(_ _t: inout MyGame_Example2_Monster) { @@ -467,7 +466,7 @@ internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferObject, Object } } -internal class MyGame_Example_TestSimpleTableWithEnumT: NativeTable { +internal class MyGame_Example_TestSimpleTableWithEnumT: UnionObject { internal var color: MyGame_Example_Color @@ -551,7 +550,7 @@ public struct MyGame_Example_Stat: FlatBufferObject, ObjectAPI { } } -public class MyGame_Example_StatT: NativeTable { +public class MyGame_Example_StatT: UnionObject { public var id: String? public var val: Int64 @@ -643,7 +642,7 @@ public struct MyGame_Example_Referrable: FlatBufferObject, ObjectAPI { } } -public class MyGame_Example_ReferrableT: NativeTable { +public class MyGame_Example_ReferrableT: UnionObject { public var id: UInt64 @@ -725,7 +724,8 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { var p: VOffset { self.rawValue } } - public var pos: MyGame_Example_Vec3? { let o = _accessor.offset(VTOFFSET.pos.v); return o == 0 ? nil : MyGame_Example_Vec3(_accessor.bb, o: o + _accessor.postion) } + public var pos: MyGame_Example_Vec3? { let o = _accessor.offset(VTOFFSET.pos.v); return o == 0 ? nil : _accessor.readBuffer(of: MyGame_Example_Vec3.self, at: o) } + public var mutablePos: MyGame_Example_Vec3_Mutable? { let o = _accessor.offset(VTOFFSET.pos.v); return o == 0 ? nil : MyGame_Example_Vec3_Mutable(_accessor.bb, o: o + _accessor.postion) } public var mana: Int16 { let o = _accessor.offset(VTOFFSET.mana.v); return o == 0 ? 150 : _accessor.readBuffer(of: Int16.self, at: o) } @discardableResult public func mutate(mana: Int16) -> Bool {let o = _accessor.offset(VTOFFSET.mana.v); return _accessor.mutate(mana, index: o) } public var hp: Int16 { let o = _accessor.offset(VTOFFSET.hp.v); return o == 0 ? 100 : _accessor.readBuffer(of: Int16.self, at: o) } @@ -741,7 +741,8 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { public var testType: MyGame_Example_Any_ { let o = _accessor.offset(VTOFFSET.testType.v); return o == 0 ? .none_ : MyGame_Example_Any_(rawValue: _accessor.readBuffer(of: UInt8.self, at: o)) ?? .none_ } public func test(type: T.Type) -> T? { let o = _accessor.offset(VTOFFSET.test.v); return o == 0 ? nil : _accessor.union(o) } public var test4Count: Int32 { let o = _accessor.offset(VTOFFSET.test4.v); return o == 0 ? 0 : _accessor.vector(count: o) } - public func test4(at index: Int32) -> MyGame_Example_Test? { let o = _accessor.offset(VTOFFSET.test4.v); return o == 0 ? nil : MyGame_Example_Test(_accessor.bb, o: _accessor.vector(at: o) + index * 4) } + public func test4(at index: Int32) -> MyGame_Example_Test? { let o = _accessor.offset(VTOFFSET.test4.v); return o == 0 ? nil : _accessor.directRead(of: MyGame_Example_Test.self, offset: _accessor.vector(at: o) + index * 4) } + public func mutableTest4(at index: Int32) -> MyGame_Example_Test_Mutable? { let o = _accessor.offset(VTOFFSET.test4.v); return o == 0 ? nil : MyGame_Example_Test_Mutable(_accessor.bb, o: _accessor.vector(at: o) + index * 4) } public var testarrayofstringCount: Int32 { let o = _accessor.offset(VTOFFSET.testarrayofstring.v); return o == 0 ? 0 : _accessor.vector(count: o) } public func testarrayofstring(at index: Int32) -> String? { let o = _accessor.offset(VTOFFSET.testarrayofstring.v); return o == 0 ? nil : _accessor.directString(at: _accessor.vector(at: o) + index * 4) } /// an example documentation comment: this will end up in the generated code @@ -786,13 +787,15 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { public var testarrayofstring2Count: Int32 { let o = _accessor.offset(VTOFFSET.testarrayofstring2.v); return o == 0 ? 0 : _accessor.vector(count: o) } public func testarrayofstring2(at index: Int32) -> String? { let o = _accessor.offset(VTOFFSET.testarrayofstring2.v); return o == 0 ? nil : _accessor.directString(at: _accessor.vector(at: o) + index * 4) } public var testarrayofsortedstructCount: Int32 { let o = _accessor.offset(VTOFFSET.testarrayofsortedstruct.v); return o == 0 ? 0 : _accessor.vector(count: o) } - public func testarrayofsortedstruct(at index: Int32) -> MyGame_Example_Ability? { let o = _accessor.offset(VTOFFSET.testarrayofsortedstruct.v); return o == 0 ? nil : MyGame_Example_Ability(_accessor.bb, o: _accessor.vector(at: o) + index * 8) } + public func testarrayofsortedstruct(at index: Int32) -> MyGame_Example_Ability? { let o = _accessor.offset(VTOFFSET.testarrayofsortedstruct.v); return o == 0 ? nil : _accessor.directRead(of: MyGame_Example_Ability.self, offset: _accessor.vector(at: o) + index * 8) } + public func mutableTestarrayofsortedstruct(at index: Int32) -> MyGame_Example_Ability_Mutable? { let o = _accessor.offset(VTOFFSET.testarrayofsortedstruct.v); return o == 0 ? nil : MyGame_Example_Ability_Mutable(_accessor.bb, o: _accessor.vector(at: o) + index * 8) } public var flexCount: Int32 { let o = _accessor.offset(VTOFFSET.flex.v); return o == 0 ? 0 : _accessor.vector(count: o) } public func flex(at index: Int32) -> UInt8 { let o = _accessor.offset(VTOFFSET.flex.v); return o == 0 ? 0 : _accessor.directRead(of: UInt8.self, offset: _accessor.vector(at: o) + index * 1) } public var flex: [UInt8] { return _accessor.getVector(at: VTOFFSET.flex.v) ?? [] } public func mutate(flex: UInt8, at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.flex.v); return _accessor.directMutate(flex, index: _accessor.vector(at: o) + index * 1) } public var test5Count: Int32 { let o = _accessor.offset(VTOFFSET.test5.v); return o == 0 ? 0 : _accessor.vector(count: o) } - public func test5(at index: Int32) -> MyGame_Example_Test? { let o = _accessor.offset(VTOFFSET.test5.v); return o == 0 ? nil : MyGame_Example_Test(_accessor.bb, o: _accessor.vector(at: o) + index * 4) } + public func test5(at index: Int32) -> MyGame_Example_Test? { let o = _accessor.offset(VTOFFSET.test5.v); return o == 0 ? nil : _accessor.directRead(of: MyGame_Example_Test.self, offset: _accessor.vector(at: o) + index * 4) } + public func mutableTest5(at index: Int32) -> MyGame_Example_Test_Mutable? { let o = _accessor.offset(VTOFFSET.test5.v); return o == 0 ? nil : MyGame_Example_Test_Mutable(_accessor.bb, o: _accessor.vector(at: o) + index * 4) } public var vectorOfLongsCount: Int32 { let o = _accessor.offset(VTOFFSET.vectorOfLongs.v); return o == 0 ? 0 : _accessor.vector(count: o) } public func vectorOfLongs(at index: Int32) -> Int64 { let o = _accessor.offset(VTOFFSET.vectorOfLongs.v); return o == 0 ? 0 : _accessor.directRead(of: Int64.self, offset: _accessor.vector(at: o) + index * 8) } public var vectorOfLongs: [Int64] { return _accessor.getVector(at: VTOFFSET.vectorOfLongs.v) ?? [] } @@ -839,7 +842,7 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { public var testrequirednestedflatbuffer: [UInt8] { return _accessor.getVector(at: VTOFFSET.testrequirednestedflatbuffer.v) ?? [] } public func mutate(testrequirednestedflatbuffer: UInt8, at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.testrequirednestedflatbuffer.v); return _accessor.directMutate(testrequirednestedflatbuffer, index: _accessor.vector(at: o) + index * 1) } public static func startMonster(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 50) } - public static func add(pos: Offset?, _ fbb: inout FlatBufferBuilder) { guard pos != nil else { return }; fbb.add(structOffset: VTOFFSET.pos.p) } + public static func add(pos: MyGame_Example_Vec3?, _ fbb: inout FlatBufferBuilder) { guard let pos = pos else { return }; fbb.create(struct: pos, position: VTOFFSET.pos.p) } public static func add(mana: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: mana, def: 150, at: VTOFFSET.mana.p) } public static func add(hp: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: hp, def: 100, at: VTOFFSET.hp.p) } public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VTOFFSET.name.p) } @@ -849,7 +852,7 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { public static func add(test: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: test, at: VTOFFSET.test.p) } public static func addVectorOf(test4: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: test4, at: VTOFFSET.test4.p) } public static func startVectorOfTest4(_ size: Int, in builder: inout FlatBufferBuilder) { - builder.startVectorOfStructs(count: size, size: MyGame_Example_Test.size, alignment: MyGame_Example_Test.alignment) + builder.startVector(size * MemoryLayout.size, elementSize: MemoryLayout.alignment) } public static func addVectorOf(testarrayofstring: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: testarrayofstring, at: VTOFFSET.testarrayofstring.p) } public static func addVectorOf(testarrayoftables: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: testarrayoftables, at: VTOFFSET.testarrayoftables.p) } @@ -873,12 +876,12 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { public static func addVectorOf(testarrayofstring2: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: testarrayofstring2, at: VTOFFSET.testarrayofstring2.p) } public static func addVectorOf(testarrayofsortedstruct: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: testarrayofsortedstruct, at: VTOFFSET.testarrayofsortedstruct.p) } public static func startVectorOfTestarrayofsortedstruct(_ size: Int, in builder: inout FlatBufferBuilder) { - builder.startVectorOfStructs(count: size, size: MyGame_Example_Ability.size, alignment: MyGame_Example_Ability.alignment) + builder.startVector(size * MemoryLayout.size, elementSize: MemoryLayout.alignment) } public static func addVectorOf(flex: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: flex, at: VTOFFSET.flex.p) } public static func addVectorOf(test5: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: test5, at: VTOFFSET.test5.p) } public static func startVectorOfTest5(_ size: Int, in builder: inout FlatBufferBuilder) { - builder.startVectorOfStructs(count: size, size: MyGame_Example_Test.size, alignment: MyGame_Example_Test.alignment) + builder.startVector(size * MemoryLayout.size, elementSize: MemoryLayout.alignment) } public static func addVectorOf(vectorOfLongs: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: vectorOfLongs, at: VTOFFSET.vectorOfLongs.p) } public static func addVectorOf(vectorOfDoubles: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: vectorOfDoubles, at: VTOFFSET.vectorOfDoubles.p) } @@ -899,6 +902,110 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { public static func add(signedEnum: MyGame_Example_Race, _ fbb: inout FlatBufferBuilder) { fbb.add(element: signedEnum.rawValue, def: -1, at: VTOFFSET.signedEnum.p) } public static func addVectorOf(testrequirednestedflatbuffer: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: testrequirednestedflatbuffer, at: VTOFFSET.testrequirednestedflatbuffer.p) } public static func endMonster(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); fbb.require(table: end, fields: [10]); return end } + public static func createMonster( + _ fbb: inout FlatBufferBuilder, + pos: MyGame_Example_Vec3? = nil, + mana: Int16 = 150, + hp: Int16 = 100, + offsetOfName name: Offset = Offset(), + vectorOfInventory inventory: Offset = Offset(), + color: MyGame_Example_Color = .blue, + testType: MyGame_Example_Any_ = .none_, + offsetOfTest test: Offset = Offset(), + vectorOfTest4 test4: Offset = Offset(), + vectorOfTestarrayofstring testarrayofstring: Offset = Offset(), + vectorOfTestarrayoftables testarrayoftables: Offset = Offset(), + offsetOfEnemy enemy: Offset = Offset(), + vectorOfTestnestedflatbuffer testnestedflatbuffer: Offset = Offset(), + offsetOfTestempty testempty: Offset = Offset(), + testbool: Bool = false, + testhashs32Fnv1: Int32 = 0, + testhashu32Fnv1: UInt32 = 0, + testhashs64Fnv1: Int64 = 0, + testhashu64Fnv1: UInt64 = 0, + testhashs32Fnv1a: Int32 = 0, + testhashu32Fnv1a: UInt32 = 0, + testhashs64Fnv1a: Int64 = 0, + testhashu64Fnv1a: UInt64 = 0, + vectorOfTestarrayofbools testarrayofbools: Offset = Offset(), + testf: Float32 = 3.14159, + testf2: Float32 = 3.0, + testf3: Float32 = 0.0, + vectorOfTestarrayofstring2 testarrayofstring2: Offset = Offset(), + vectorOfTestarrayofsortedstruct testarrayofsortedstruct: Offset = Offset(), + vectorOfFlex flex: Offset = Offset(), + vectorOfTest5 test5: Offset = Offset(), + vectorOfVectorOfLongs vectorOfLongs: Offset = Offset(), + vectorOfVectorOfDoubles vectorOfDoubles: Offset = Offset(), + offsetOfParentNamespaceTest parentNamespaceTest: Offset = Offset(), + vectorOfVectorOfReferrables vectorOfReferrables: Offset = Offset(), + singleWeakReference: UInt64 = 0, + vectorOfVectorOfWeakReferences vectorOfWeakReferences: Offset = Offset(), + vectorOfVectorOfStrongReferrables vectorOfStrongReferrables: Offset = Offset(), + coOwningReference: UInt64 = 0, + vectorOfVectorOfCoOwningReferences vectorOfCoOwningReferences: Offset = Offset(), + nonOwningReference: UInt64 = 0, + vectorOfVectorOfNonOwningReferences vectorOfNonOwningReferences: Offset = Offset(), + anyUniqueType: MyGame_Example_AnyUniqueAliases = .none_, + offsetOfAnyUnique anyUnique: Offset = Offset(), + anyAmbiguousType: MyGame_Example_AnyAmbiguousAliases = .none_, + offsetOfAnyAmbiguous anyAmbiguous: Offset = Offset(), + vectorOfVectorOfEnums vectorOfEnums: Offset = Offset(), + signedEnum: MyGame_Example_Race = .none_, + vectorOfTestrequirednestedflatbuffer testrequirednestedflatbuffer: Offset = Offset() + ) -> Offset { + let __start = MyGame_Example_Monster.startMonster(&fbb) + MyGame_Example_Monster.add(pos: pos, &fbb) + MyGame_Example_Monster.add(mana: mana, &fbb) + MyGame_Example_Monster.add(hp: hp, &fbb) + MyGame_Example_Monster.add(name: name, &fbb) + MyGame_Example_Monster.addVectorOf(inventory: inventory, &fbb) + MyGame_Example_Monster.add(color: color, &fbb) + MyGame_Example_Monster.add(testType: testType, &fbb) + MyGame_Example_Monster.add(test: test, &fbb) + MyGame_Example_Monster.addVectorOf(test4: test4, &fbb) + MyGame_Example_Monster.addVectorOf(testarrayofstring: testarrayofstring, &fbb) + MyGame_Example_Monster.addVectorOf(testarrayoftables: testarrayoftables, &fbb) + MyGame_Example_Monster.add(enemy: enemy, &fbb) + MyGame_Example_Monster.addVectorOf(testnestedflatbuffer: testnestedflatbuffer, &fbb) + MyGame_Example_Monster.add(testempty: testempty, &fbb) + MyGame_Example_Monster.add(testbool: testbool, &fbb) + MyGame_Example_Monster.add(testhashs32Fnv1: testhashs32Fnv1, &fbb) + MyGame_Example_Monster.add(testhashu32Fnv1: testhashu32Fnv1, &fbb) + MyGame_Example_Monster.add(testhashs64Fnv1: testhashs64Fnv1, &fbb) + MyGame_Example_Monster.add(testhashu64Fnv1: testhashu64Fnv1, &fbb) + MyGame_Example_Monster.add(testhashs32Fnv1a: testhashs32Fnv1a, &fbb) + MyGame_Example_Monster.add(testhashu32Fnv1a: testhashu32Fnv1a, &fbb) + MyGame_Example_Monster.add(testhashs64Fnv1a: testhashs64Fnv1a, &fbb) + MyGame_Example_Monster.add(testhashu64Fnv1a: testhashu64Fnv1a, &fbb) + MyGame_Example_Monster.addVectorOf(testarrayofbools: testarrayofbools, &fbb) + MyGame_Example_Monster.add(testf: testf, &fbb) + MyGame_Example_Monster.add(testf2: testf2, &fbb) + MyGame_Example_Monster.add(testf3: testf3, &fbb) + MyGame_Example_Monster.addVectorOf(testarrayofstring2: testarrayofstring2, &fbb) + MyGame_Example_Monster.addVectorOf(testarrayofsortedstruct: testarrayofsortedstruct, &fbb) + MyGame_Example_Monster.addVectorOf(flex: flex, &fbb) + MyGame_Example_Monster.addVectorOf(test5: test5, &fbb) + MyGame_Example_Monster.addVectorOf(vectorOfLongs: vectorOfLongs, &fbb) + MyGame_Example_Monster.addVectorOf(vectorOfDoubles: vectorOfDoubles, &fbb) + MyGame_Example_Monster.add(parentNamespaceTest: parentNamespaceTest, &fbb) + MyGame_Example_Monster.addVectorOf(vectorOfReferrables: vectorOfReferrables, &fbb) + MyGame_Example_Monster.add(singleWeakReference: singleWeakReference, &fbb) + MyGame_Example_Monster.addVectorOf(vectorOfWeakReferences: vectorOfWeakReferences, &fbb) + MyGame_Example_Monster.addVectorOf(vectorOfStrongReferrables: vectorOfStrongReferrables, &fbb) + MyGame_Example_Monster.add(coOwningReference: coOwningReference, &fbb) + MyGame_Example_Monster.addVectorOf(vectorOfCoOwningReferences: vectorOfCoOwningReferences, &fbb) + MyGame_Example_Monster.add(nonOwningReference: nonOwningReference, &fbb) + MyGame_Example_Monster.addVectorOf(vectorOfNonOwningReferences: vectorOfNonOwningReferences, &fbb) + MyGame_Example_Monster.add(anyUniqueType: anyUniqueType, &fbb) + MyGame_Example_Monster.add(anyUnique: anyUnique, &fbb) + MyGame_Example_Monster.add(anyAmbiguousType: anyAmbiguousType, &fbb) + MyGame_Example_Monster.add(anyAmbiguous: anyAmbiguous, &fbb) + MyGame_Example_Monster.addVectorOf(vectorOfEnums: vectorOfEnums, &fbb) + MyGame_Example_Monster.add(signedEnum: signedEnum, &fbb) + MyGame_Example_Monster.addVectorOf(testrequirednestedflatbuffer: testrequirednestedflatbuffer, &fbb) + return MyGame_Example_Monster.endMonster(&fbb, start: __start) + } public static func sortVectorOfMonster(offsets:[Offset], _ fbb: inout FlatBufferBuilder) -> Offset { var off = offsets off.sort { Table.compare(Table.offset(Int32($1.o), vOffset: 10, fbb: fbb.buffer), Table.offset(Int32($0.o), vOffset: 10, fbb: fbb.buffer), fbb: fbb.buffer) < 0 } @@ -941,9 +1048,9 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { MyGame_Example_Monster.startVectorOfTest4(obj.test4.count, in: &builder) for i in obj.test4 { guard let _o = i else { continue } - MyGame_Example_Test.createTest(builder: &builder, a: _o.a, b: _o.b) + builder.create(struct: _o) } - let __test4 = builder.endVectorOfStructs(count: obj.test4.count) + let __test4 = builder.endVector(len: obj.test4.count) let __testarrayofstring = builder.createVector(ofStrings: obj.testarrayofstring.compactMap({ $0 }) ) var __testarrayoftables__: [Offset] = [] for var i in obj.testarrayoftables { @@ -958,16 +1065,16 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { MyGame_Example_Monster.startVectorOfTestarrayofsortedstruct(obj.testarrayofsortedstruct.count, in: &builder) for i in obj.testarrayofsortedstruct { guard let _o = i else { continue } - MyGame_Example_Ability.createAbility(builder: &builder, id: _o.id, distance: _o.distance) + builder.create(struct: _o) } - let __testarrayofsortedstruct = builder.endVectorOfStructs(count: obj.testarrayofsortedstruct.count) + let __testarrayofsortedstruct = builder.endVector(len: obj.testarrayofsortedstruct.count) let __flex = builder.createVector(obj.flex) MyGame_Example_Monster.startVectorOfTest5(obj.test5.count, in: &builder) for i in obj.test5 { guard let _o = i else { continue } - MyGame_Example_Test.createTest(builder: &builder, a: _o.a, b: _o.b) + builder.create(struct: _o) } - let __test5 = builder.endVectorOfStructs(count: obj.test5.count) + let __test5 = builder.endVector(len: obj.test5.count) let __vectorOfLongs = builder.createVector(obj.vectorOfLongs) let __vectorOfDoubles = builder.createVector(obj.vectorOfDoubles) let __parentNamespaceTest = MyGame_InParentNamespace.pack(&builder, obj: &obj.parentNamespaceTest) @@ -989,7 +1096,7 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { let __vectorOfEnums = builder.createVector(obj.vectorOfEnums) let __testrequirednestedflatbuffer = builder.createVector(obj.testrequirednestedflatbuffer) let __root = MyGame_Example_Monster.startMonster(&builder) - MyGame_Example_Monster.add(pos: obj.pos.map { MyGame_Example_Vec3.createVec3(builder: &builder, x: $0.x, y: $0.y, z: $0.z, test1: $0.test1, test2: $0.test2, test3a: $0.test3.a, test3b: $0.test3.b) }, &builder) + MyGame_Example_Monster.add(pos: obj.pos, &builder) MyGame_Example_Monster.add(mana: obj.mana, &builder) MyGame_Example_Monster.add(hp: obj.hp, &builder) MyGame_Example_Monster.add(name: __name, &builder) @@ -1051,16 +1158,16 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPI { } } -public class MyGame_Example_MonsterT: NativeTable { +public class MyGame_Example_MonsterT: UnionObject { - public var pos: MyGame_Example_Vec3T? + public var pos: MyGame_Example_Vec3? public var mana: Int16 public var hp: Int16 public var name: String public var inventory: [UInt8] public var color: MyGame_Example_Color public var test: MyGame_Example_Any_Union? - public var test4: [MyGame_Example_TestT?] + public var test4: [MyGame_Example_Test?] public var testarrayofstring: [String?] public var testarrayoftables: [MyGame_Example_MonsterT?] public var enemy: MyGame_Example_MonsterT? @@ -1080,9 +1187,9 @@ public class MyGame_Example_MonsterT: NativeTable { public var testf2: Float32 public var testf3: Float32 public var testarrayofstring2: [String?] - public var testarrayofsortedstruct: [MyGame_Example_AbilityT?] + public var testarrayofsortedstruct: [MyGame_Example_Ability?] public var flex: [UInt8] - public var test5: [MyGame_Example_TestT?] + public var test5: [MyGame_Example_Test?] public var vectorOfLongs: [Int64] public var vectorOfDoubles: [Double] public var parentNamespaceTest: MyGame_InParentNamespaceT? @@ -1101,8 +1208,7 @@ public class MyGame_Example_MonsterT: NativeTable { public var testrequirednestedflatbuffer: [UInt8] public init(_ _t: inout MyGame_Example_Monster) { - var __pos = _t.pos - pos = __pos?.unpack() + pos = _t.pos mana = _t.mana hp = _t.hp name = _t.name @@ -1113,20 +1219,19 @@ public class MyGame_Example_MonsterT: NativeTable { color = _t.color switch _t.testType { case .monster: - var _v = _t.test(type: MyGame_Example_Monster.self) - test = MyGame_Example_Any_Union(_v?.unpack(), type: .monster) + var _v = _t.test(type: MyGame_Example_Monster.self) + test = MyGame_Example_Any_Union(_v?.unpack(), type: .monster) case .testsimpletablewithenum: - var _v = _t.test(type: MyGame_Example_TestSimpleTableWithEnum.self) - test = MyGame_Example_Any_Union(_v?.unpack(), type: .testsimpletablewithenum) + var _v = _t.test(type: MyGame_Example_TestSimpleTableWithEnum.self) + test = MyGame_Example_Any_Union(_v?.unpack(), type: .testsimpletablewithenum) case .mygameExample2Monster: - var _v = _t.test(type: MyGame_Example2_Monster.self) - test = MyGame_Example_Any_Union(_v?.unpack(), type: .mygameExample2Monster) + var _v = _t.test(type: MyGame_Example2_Monster.self) + test = MyGame_Example_Any_Union(_v?.unpack(), type: .mygameExample2Monster) default: break } test4 = [] for index in 0..<_t.test4Count { - var __v_ = _t.test4(at: index) - test4.append(__v_?.unpack()) + test4.append(_t.test4(at: index)) } testarrayofstring = [] for index in 0..<_t.testarrayofstringCount { @@ -1167,8 +1272,7 @@ public class MyGame_Example_MonsterT: NativeTable { } testarrayofsortedstruct = [] for index in 0..<_t.testarrayofsortedstructCount { - var __v_ = _t.testarrayofsortedstruct(at: index) - testarrayofsortedstruct.append(__v_?.unpack()) + testarrayofsortedstruct.append(_t.testarrayofsortedstruct(at: index)) } flex = [] for index in 0..<_t.flexCount { @@ -1176,8 +1280,7 @@ public class MyGame_Example_MonsterT: NativeTable { } test5 = [] for index in 0..<_t.test5Count { - var __v_ = _t.test5(at: index) - test5.append(__v_?.unpack()) + test5.append(_t.test5(at: index)) } vectorOfLongs = [] for index in 0..<_t.vectorOfLongsCount { @@ -1216,26 +1319,26 @@ public class MyGame_Example_MonsterT: NativeTable { } switch _t.anyUniqueType { case .m: - var _v = _t.anyUnique(type: MyGame_Example_Monster.self) - anyUnique = MyGame_Example_AnyUniqueAliasesUnion(_v?.unpack(), type: .m) + var _v = _t.anyUnique(type: MyGame_Example_Monster.self) + anyUnique = MyGame_Example_AnyUniqueAliasesUnion(_v?.unpack(), type: .m) case .ts: - var _v = _t.anyUnique(type: MyGame_Example_TestSimpleTableWithEnum.self) - anyUnique = MyGame_Example_AnyUniqueAliasesUnion(_v?.unpack(), type: .ts) + var _v = _t.anyUnique(type: MyGame_Example_TestSimpleTableWithEnum.self) + anyUnique = MyGame_Example_AnyUniqueAliasesUnion(_v?.unpack(), type: .ts) case .m2: - var _v = _t.anyUnique(type: MyGame_Example2_Monster.self) - anyUnique = MyGame_Example_AnyUniqueAliasesUnion(_v?.unpack(), type: .m2) + var _v = _t.anyUnique(type: MyGame_Example2_Monster.self) + anyUnique = MyGame_Example_AnyUniqueAliasesUnion(_v?.unpack(), type: .m2) default: break } switch _t.anyAmbiguousType { case .m1: - var _v = _t.anyAmbiguous(type: MyGame_Example_Monster.self) - anyAmbiguous = MyGame_Example_AnyAmbiguousAliasesUnion(_v?.unpack(), type: .m1) + var _v = _t.anyAmbiguous(type: MyGame_Example_Monster.self) + anyAmbiguous = MyGame_Example_AnyAmbiguousAliasesUnion(_v?.unpack(), type: .m1) case .m2: - var _v = _t.anyAmbiguous(type: MyGame_Example_Monster.self) - anyAmbiguous = MyGame_Example_AnyAmbiguousAliasesUnion(_v?.unpack(), type: .m2) + var _v = _t.anyAmbiguous(type: MyGame_Example_Monster.self) + anyAmbiguous = MyGame_Example_AnyAmbiguousAliasesUnion(_v?.unpack(), type: .m2) case .m3: - var _v = _t.anyAmbiguous(type: MyGame_Example_Monster.self) - anyAmbiguous = MyGame_Example_AnyAmbiguousAliasesUnion(_v?.unpack(), type: .m3) + var _v = _t.anyAmbiguous(type: MyGame_Example_Monster.self) + anyAmbiguous = MyGame_Example_AnyAmbiguousAliasesUnion(_v?.unpack(), type: .m3) default: break } vectorOfEnums = [] @@ -1250,7 +1353,7 @@ public class MyGame_Example_MonsterT: NativeTable { } public init() { - pos = MyGame_Example_Vec3T() + pos = MyGame_Example_Vec3() mana = 150 hp = 100 name = "" @@ -1429,7 +1532,7 @@ public struct MyGame_Example_TypeAliases: FlatBufferObject, ObjectAPI { } } -public class MyGame_Example_TypeAliasesT: NativeTable { +public class MyGame_Example_TypeAliasesT: UnionObject { public var i8: Int8 public var u8: UInt8 diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift index 88cb4fb..3eb267c 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift @@ -23,8 +23,8 @@ public enum Character: UInt8, Enum { public struct CharacterUnion { public var type: Character - public var value: NativeTable? - public init(_ v: NativeTable?, type: Character) { + public var value: UnionObject? + public init(_ v: UnionObject?, type: Character) { self.type = type self.value = v } @@ -34,116 +34,108 @@ public struct CharacterUnion { var __obj = value as? AttackerT return Attacker.pack(&builder, obj: &__obj) case .rapunzel: - var __obj = value as? RapunzelT - return Rapunzel.pack(&builder, obj: &__obj) + var __obj = value as? Rapunzel + return Rapunzel_Mutable.pack(&builder, obj: &__obj) case .belle: - var __obj = value as? BookReaderT - return BookReader.pack(&builder, obj: &__obj) + var __obj = value as? BookReader + return BookReader_Mutable.pack(&builder, obj: &__obj) case .bookfan: - var __obj = value as? BookReaderT - return BookReader.pack(&builder, obj: &__obj) + var __obj = value as? BookReader + return BookReader_Mutable.pack(&builder, obj: &__obj) default: return Offset() } } } -public struct Rapunzel: Readable { +public struct Rapunzel: NativeStruct, UnionObject { + + static func validateVersion() { FlatBuffersVersion_1_12_0() } + + private var _hairLength: Int32 + + public init(hairLength: Int32) { + _hairLength = hairLength + } + + public init() { + _hairLength = 0 + } + + public init(_ _t: inout Rapunzel_Mutable) { + _hairLength = _t.hairLength + } + + public var hairLength: Int32 { _hairLength } +} + +public struct Rapunzel_Mutable: FlatBufferObject { static func validateVersion() { FlatBuffersVersion_1_12_0() } public var __buffer: ByteBuffer! { return _accessor.bb } private var _accessor: Struct - public static var size = 4 - public static var alignment = 4 public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) } public var hairLength: Int32 { return _accessor.readBuffer(of: Int32.self, at: 0) } @discardableResult public func mutate(hairLength: Int32) -> Bool { return _accessor.mutate(hairLength, index: 0) } - public mutating func unpack() -> RapunzelT { - return RapunzelT(&self) + public mutating func unpack() -> Rapunzel { + return Rapunzel(&self) } - public static func pack(_ builder: inout FlatBufferBuilder, obj: inout RapunzelT?) -> Offset { + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout Rapunzel?) -> Offset { guard var obj = obj else { return Offset() } return pack(&builder, obj: &obj) } - public static func pack(_ builder: inout FlatBufferBuilder, obj: inout RapunzelT) -> Offset { - return createRapunzel(builder: &builder, hairLength: obj.hairLength) + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout Rapunzel) -> Offset { + return builder.create(struct: obj) } } -public class RapunzelT: NativeTable { +public struct BookReader: NativeStruct, UnionObject { - public var hairLength: Int32 + static func validateVersion() { FlatBuffersVersion_1_12_0() } + + private var _booksRead: Int32 - public init(_ _t: inout Rapunzel) { - hairLength = _t.hairLength + public init(booksRead: Int32) { + _booksRead = booksRead } public init() { - hairLength = 0 + _booksRead = 0 + } + + public init(_ _t: inout BookReader_Mutable) { + _booksRead = _t.booksRead } + public var booksRead: Int32 { _booksRead } } -public struct BookReader: Readable { + +public struct BookReader_Mutable: FlatBufferObject { static func validateVersion() { FlatBuffersVersion_1_12_0() } public var __buffer: ByteBuffer! { return _accessor.bb } private var _accessor: Struct - public static var size = 4 - public static var alignment = 4 public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) } public var booksRead: Int32 { return _accessor.readBuffer(of: Int32.self, at: 0) } @discardableResult public func mutate(booksRead: Int32) -> Bool { return _accessor.mutate(booksRead, index: 0) } - public mutating func unpack() -> BookReaderT { - return BookReaderT(&self) + public mutating func unpack() -> BookReader { + return BookReader(&self) } - public static func pack(_ builder: inout FlatBufferBuilder, obj: inout BookReaderT?) -> Offset { + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout BookReader?) -> Offset { guard var obj = obj else { return Offset() } return pack(&builder, obj: &obj) } - public static func pack(_ builder: inout FlatBufferBuilder, obj: inout BookReaderT) -> Offset { - return createBookReader(builder: &builder, booksRead: obj.booksRead) - } -} - -public class BookReaderT: NativeTable { - - public var booksRead: Int32 - - public init(_ _t: inout BookReader) { - booksRead = _t.booksRead - } - - public init() { - booksRead = 0 + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout BookReader) -> Offset { + return builder.create(struct: obj) } - -} -extension Rapunzel { - @discardableResult - public static func createRapunzel(builder: inout FlatBufferBuilder, hairLength: Int32 = 0) -> Offset { - builder.createStructOf(size: Rapunzel.size, alignment: Rapunzel.alignment) - builder.reverseAdd(v: hairLength, postion: 0) - return builder.endStruct() - } - -} - -extension BookReader { - @discardableResult - public static func createBookReader(builder: inout FlatBufferBuilder, booksRead: Int32 = 0) -> Offset { - builder.createStructOf(size: BookReader.size, alignment: BookReader.alignment) - builder.reverseAdd(v: booksRead, postion: 0) - return builder.endStruct() - } - } public struct Attacker: FlatBufferObject, ObjectAPI { @@ -194,7 +186,7 @@ public struct Attacker: FlatBufferObject, ObjectAPI { } } -public class AttackerT: NativeTable { +public class AttackerT: UnionObject { public var swordAttackDamage: Int32 @@ -287,7 +279,7 @@ public struct Movie: FlatBufferObject, ObjectAPI { } } -public class MovieT: NativeTable { +public class MovieT: UnionObject { public var mainCharacter: CharacterUnion? public var characters: [CharacterUnion?] @@ -295,34 +287,34 @@ public class MovieT: NativeTable { public init(_ _t: inout Movie) { switch _t.mainCharacterType { case .mulan: - var _v = _t.mainCharacter(type: Attacker.self) - mainCharacter = CharacterUnion(_v?.unpack(), type: .mulan) + var _v = _t.mainCharacter(type: Attacker.self) + mainCharacter = CharacterUnion(_v?.unpack(), type: .mulan) case .rapunzel: - var _v = _t.mainCharacter(type: Rapunzel.self) - mainCharacter = CharacterUnion(_v?.unpack(), type: .rapunzel) + var _v = _t.mainCharacter(type: Rapunzel_Mutable.self) + mainCharacter = CharacterUnion(_v?.unpack(), type: .rapunzel) case .belle: - var _v = _t.mainCharacter(type: BookReader.self) - mainCharacter = CharacterUnion(_v?.unpack(), type: .belle) + var _v = _t.mainCharacter(type: BookReader_Mutable.self) + mainCharacter = CharacterUnion(_v?.unpack(), type: .belle) case .bookfan: - var _v = _t.mainCharacter(type: BookReader.self) - mainCharacter = CharacterUnion(_v?.unpack(), type: .bookfan) + var _v = _t.mainCharacter(type: BookReader_Mutable.self) + mainCharacter = CharacterUnion(_v?.unpack(), type: .bookfan) default: break } characters = [] for index in 0..<_t.charactersCount { switch _t.charactersType(at: index) { case .mulan: - var _v = _t.characters(at: index, type: Attacker.self) - characters.append(CharacterUnion(_v?.unpack(), type: .mulan)) + var _v = _t.characters(at: index, type: Attacker.self) + characters.append(CharacterUnion(_v?.unpack(), type: .mulan)) case .rapunzel: - var _v = _t.characters(at: index, type: Rapunzel.self) - characters.append(CharacterUnion(_v?.unpack(), type: .rapunzel)) + var _v = _t.characters(at: index, type: Rapunzel_Mutable.self) + characters.append(CharacterUnion(_v?.unpack(), type: .rapunzel)) case .belle: - var _v = _t.characters(at: index, type: BookReader.self) - characters.append(CharacterUnion(_v?.unpack(), type: .belle)) + var _v = _t.characters(at: index, type: BookReader_Mutable.self) + characters.append(CharacterUnion(_v?.unpack(), type: .belle)) case .bookfan: - var _v = _t.characters(at: index, type: BookReader.self) - characters.append(CharacterUnion(_v?.unpack(), type: .bookfan)) + var _v = _t.characters(at: index, type: BookReader_Mutable.self) + characters.append(CharacterUnion(_v?.unpack(), type: .bookfan)) default: break } } -- 2.7.4