[Swift] Rebuild the way swift handles structs from scratch (#6326)
authormustiikhalil <mustii@mmk.one>
Thu, 17 Dec 2020 22:55:32 +0000 (01:55 +0300)
committerGitHub <noreply@github.com>
Thu, 17 Dec 2020 22:55:32 +0000 (14:55 -0800)
* 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

21 files changed:
docs/source/SwiftUsage.md
docs/source/Tutorial.md
samples/monster_generated.swift [new file with mode: 0644]
samples/sample_binary.swift
src/idl_gen_swift.cpp
swift/FlatBuffers.podspec
swift/README.md
swift/Sources/FlatBuffers/ByteBuffer.swift
swift/Sources/FlatBuffers/FlatBufferBuilder.swift
swift/Sources/FlatBuffers/FlatBufferObject.swift
swift/Sources/FlatBuffers/Table.swift
swift/Sources/FlatBuffers/UnionObject.swift [moved from swift/Sources/FlatBuffers/NativeTable.swift with 97% similarity]
tests/FlatBuffers.Benchmarks.swift/Sources/FlatBuffers.Benchmarks.swift/main.swift
tests/FlatBuffers.Test.Swift/SwiftTest.sh
tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift
tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersStructsTests.swift
tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersUnionTests.swift
tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/MutatingBool_generated.swift
tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/XCTestManifests.swift
tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift
tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift

index d5640f6..1c438f2 100644 (file)
@@ -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.
index f3f03f5..0d531a3 100644 (file)
@@ -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
 ~~~
 </div>
 
@@ -1420,9 +1420,20 @@ for the `path` field above:
 <div class="language-swift">
 ~~~{.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)
 ~~~
 </div>
@@ -1702,17 +1713,16 @@ can serialize the monster itself:
 </div>
 <div class="language-swift">
 ~~~{.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)
 ~~~
 </div>
 
@@ -1780,6 +1790,21 @@ a bit more flexibility.
 ~~~
 </div>
 
+<div class="language-swift">
+~~~{.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)
+~~~
+</div>
+
 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
 ~~~
 </div>
diff --git a/samples/monster_generated.swift b/samples/monster_generated.swift
new file mode 100644 (file)
index 0000000..4400c5a
--- /dev/null
@@ -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<Int8>.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<UInt8>.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<T: FlatBufferObject>(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<String>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VTOFFSET.name.p) }
+  public static func addVectorOf(inventory: Offset<UOffset>, _ 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<UOffset>, _ 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<UOffset>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: equipped, at: VTOFFSET.equipped.p) }
+  public static func addVectorOf(path: Offset<UOffset>, _ 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<MyGame_Sample_Vec3>.size, elementSize: MemoryLayout<MyGame_Sample_Vec3>.alignment)
+  }
+  public static func endMonster(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(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<String> = Offset(),
+    vectorOfInventory inventory: Offset<UOffset> = Offset(),
+    color: MyGame_Sample_Color = .blue,
+    vectorOfWeapons weapons: Offset<UOffset> = Offset(),
+    equippedType: MyGame_Sample_Equipment = .none_,
+    offsetOfEquipped equipped: Offset<UOffset> = Offset(),
+    vectorOfPath path: Offset<UOffset> = Offset()
+  ) -> Offset<UOffset> {
+    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<String>, _ 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<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end }
+  public static func createWeapon(
+    _ fbb: inout FlatBufferBuilder,
+    offsetOfName name: Offset<String> = Offset(),
+    damage: Int16 = 0
+  ) -> Offset<UOffset> {
+    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)
+  }
+}
+
index 46ab99b..88d2578 100644 (file)
 
 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..<monster.inventoryCount {
     assert(i == monster.inventory(at: i))
   }
index 084bafe..8fcd00b 100644 (file)
@@ -153,17 +153,7 @@ class SwiftGenerator : public BaseGenerator {
       const auto &struct_def = **it;
       if (struct_def.fixed && !struct_def.generated) {
         GenStructReader(struct_def);
-        if (parser_.opts.generate_object_based_api) {
-          GenObjectAPI(struct_def);
-        }
-      }
-    }
-
-    for (auto it = parser_.structs_.vec.begin();
-         it != parser_.structs_.vec.end(); ++it) {
-      const auto &struct_def = **it;
-      if (struct_def.fixed && !struct_def.generated) {
-        GenStructWriter(struct_def);
+        GenMutableStructReader(struct_def);
       }
     }
 
@@ -188,6 +178,124 @@ class SwiftGenerator : public BaseGenerator {
     code_ += "\n// MARK: - {{MARKVALUE}}\n";
   }
 
+  // MARK: - Generating structs
+
+  // 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");
+    GenComment(struct_def.doc_comment);
+    code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
+    code_ += "{{ACCESS_TYPE}} struct {{STRUCTNAME}}: NativeStruct\\";
+    if (parser_.opts.generate_object_based_api) code_ += ", UnionObject\\";
+    code_ += " {";
+    code_ += "";
+    Indent();
+    code_ += ValidateFunc();
+    code_ += "";
+    int padding_id = 0;
+    std::string constructor = "";
+    std::vector<std::string> base_constructor;
+    std::vector<std::string> 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<int>(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<UOffset>, 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<UOffset> {";
+        "{{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<UOffset>() }";
-    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<UOffset> {";
-    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<UOffset>, 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<std::string> *create_body,
-                            std::vector<std::string> *create_header,
-                            bool &contains_structs) {
+                            std::vector<std::string> *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<UOffset>?";
-      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<String>"
-                           : "Offset<UOffset>";
+    auto offset_type =
+        IsString(field.value.type) ? "Offset<String>" : "Offset<UOffset>";
     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<UOffset> {";
+    Indent();
+    code_ += "guard var obj = obj else { return Offset<UOffset>() }";
+    code_ += "return pack(&builder, obj: &obj)";
+    Outdent();
+    code_ += "}";
+    code_ += "";
+    code_ +=
+        "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
+        "obj: "
+        "inout " +
+        name + ") -> Offset<UOffset> {";
+    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<std::string> buffer_constructor;
     std::vector<std::string> 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<std::string> 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<std::string> &body,
-                                 const std::string &header = "") {
+  void BuildObjectConstructor(const std::vector<std::string> &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<int>(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<std::string> &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())) {
index b106b4c..5fdcb37 100644 (file)
@@ -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
index c3060fd..1b90ab6 100644 (file)
@@ -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
 
index 7df41a7..17c1a87 100644 (file)
@@ -187,7 +187,7 @@ public struct ByteBuffer {
     _writerSize = _writerSize &+ (MemoryLayout<UInt8>.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<T: Scalar>(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<T: NativeStruct>(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<T: Scalar>(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<String.UTF8View.Element>,
     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<T>(
     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,
index 71fcab0..64f267b 100644 (file)
@@ -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<UOffset> {
     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<T>.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<T: Readable>(
-    structs: [UnsafeMutableRawPointer],
-    type: T.Type) -> Offset<UOffset>
-  {
-    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<T: NativeStruct>(ofStructs structs: [T]) -> Offset<UOffset> {
+    startVector(structs.count * MemoryLayout<T>.size, elementSize: MemoryLayout<T>.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<UOffset> {
-    Offset<UOffset>(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<T: Readable>(
-    struct s: UnsafeMutableRawPointer,
-    type: T.Type) -> Offset<UOffset>
+  mutating public func create<T: NativeStruct>(
+    struct s: T, position: VOffset) -> Offset<UOffset>
   {
-    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<T: Scalar>(v: T, postion: Int) {
-    _bb.reversePush(
-      value: v,
-      position: postion,
-      len: MemoryLayout<T>.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<UOffset> {
-    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<T: NativeStruct>(
+    struct s: T) -> Offset<UOffset>
+  {
+    let size = MemoryLayout<T>.size
+    preAlign(len: size, alignment: MemoryLayout<T>.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)
     }
index 7536c40..fb7408b 100644 (file)
 
 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 }
index 451398c..44bbe38 100644 (file)
@@ -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<T: Scalar>(of type: T.Type, at o: Int32) -> T {
+  public func readBuffer<T>(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<T: Scalar>(of type: T.Type, offset o: Int32) -> T {
+  public func directRead<T>(of type: T.Type, offset o: Int32) -> T {
     let r = bb.read(def: T.self, position: Int(o))
     return r
   }
similarity index 97%
rename from swift/Sources/FlatBuffers/NativeTable.swift
rename to swift/Sources/FlatBuffers/UnionObject.swift
index 5c844c1..fa45e91 100644 (file)
@@ -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
index fed3f2d..1ec5bb4 100644 (file)
@@ -89,14 +89,11 @@ func benchmarkThreeMillionStructs() {
 
   var offsets: [Offset<UOffset>] = []
   for _ in 0..<structCount {
-    fb.startVectorOfStructs(count: 5, size: 16, alignment: 8)
+    fb.startVector(5 * MemoryLayout<AA>.size, elementSize: MemoryLayout<AA>.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<UOffset>(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()
index 43c82bf..5e2916c 100755 (executable)
@@ -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
index f37f2b8..fb49e48 100644 (file)
@@ -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")
index 2c344f0..cdde364 100644 (file)
@@ -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<UOffset> {
-  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
 }
index 0802272..e401d4e 100644 (file)
@@ -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<UOffset>,
+    position: Vec,
     hp: Int16,
     name: Offset<String>,
     inventory: Offset<UOffset>,
@@ -190,7 +190,7 @@ struct FinalMonster {
     path: Offset<UOffset>) -> Offset<LocalMonster>
   {
     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)
index d51f3d9..7fc9ed2 100644 (file)
@@ -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<UOffset> {
-    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<UOffset>, _ 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<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end }
 }
 
index 8459ee5..e869acb 100644 (file)
@@ -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),
   ]
 }
 
index b15eddf..d3ed40d 100644 (file)
@@ -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<UOffset> {
+  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Test?) -> Offset<UOffset> {
     guard var obj = obj else { return Offset<UOffset>() }
     return pack(&builder, obj: &obj)
   }
 
-  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_TestT) -> Offset<UOffset> {
-    return createTest(builder: &builder, a: obj.a, b: obj.b)
+  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Test) -> Offset<UOffset> {
+    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<UOffset> {
+  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Vec3?) -> Offset<UOffset> {
     guard var obj = obj else { return Offset<UOffset>() }
     return pack(&builder, obj: &obj)
   }
 
-  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Vec3T) -> Offset<UOffset> {
-    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<UOffset> {
+    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<UOffset> {
+  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Ability?) -> Offset<UOffset> {
     guard var obj = obj else { return Offset<UOffset>() }
     return pack(&builder, obj: &obj)
   }
 
-  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_AbilityT) -> Offset<UOffset> {
-    return createAbility(builder: &builder, id: obj.id, distance: obj.distance)
+  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MyGame_Example_Ability) -> Offset<UOffset> {
+    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<UOffset> {
-    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<UOffset> {
-    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<UOffset> {
-    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<T: FlatBufferObject>(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<UOffset>?, _ 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<String>, _ 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<UOffset>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: test, at: VTOFFSET.test.p) }
   public static func addVectorOf(test4: Offset<UOffset>, _ 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<MyGame_Example_Test>.size, elementSize: MemoryLayout<MyGame_Example_Test>.alignment)
   }
   public static func addVectorOf(testarrayofstring: Offset<UOffset>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: testarrayofstring, at: VTOFFSET.testarrayofstring.p) }
   public static func addVectorOf(testarrayoftables: Offset<UOffset>, _ 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<UOffset>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: testarrayofstring2, at: VTOFFSET.testarrayofstring2.p) }
   public static func addVectorOf(testarrayofsortedstruct: Offset<UOffset>, _ 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<MyGame_Example_Ability>.size, elementSize: MemoryLayout<MyGame_Example_Ability>.alignment)
   }
   public static func addVectorOf(flex: Offset<UOffset>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: flex, at: VTOFFSET.flex.p) }
   public static func addVectorOf(test5: Offset<UOffset>, _ 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<MyGame_Example_Test>.size, elementSize: MemoryLayout<MyGame_Example_Test>.alignment)
   }
   public static func addVectorOf(vectorOfLongs: Offset<UOffset>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: vectorOfLongs, at: VTOFFSET.vectorOfLongs.p) }
   public static func addVectorOf(vectorOfDoubles: Offset<UOffset>, _ 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<UOffset>, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: testrequirednestedflatbuffer, at: VTOFFSET.testrequirednestedflatbuffer.p) }
   public static func endMonster(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(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<String> = Offset(),
+    vectorOfInventory inventory: Offset<UOffset> = Offset(),
+    color: MyGame_Example_Color = .blue,
+    testType: MyGame_Example_Any_ = .none_,
+    offsetOfTest test: Offset<UOffset> = Offset(),
+    vectorOfTest4 test4: Offset<UOffset> = Offset(),
+    vectorOfTestarrayofstring testarrayofstring: Offset<UOffset> = Offset(),
+    vectorOfTestarrayoftables testarrayoftables: Offset<UOffset> = Offset(),
+    offsetOfEnemy enemy: Offset<UOffset> = Offset(),
+    vectorOfTestnestedflatbuffer testnestedflatbuffer: Offset<UOffset> = Offset(),
+    offsetOfTestempty testempty: Offset<UOffset> = 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<UOffset> = Offset(),
+    testf: Float32 = 3.14159,
+    testf2: Float32 = 3.0,
+    testf3: Float32 = 0.0,
+    vectorOfTestarrayofstring2 testarrayofstring2: Offset<UOffset> = Offset(),
+    vectorOfTestarrayofsortedstruct testarrayofsortedstruct: Offset<UOffset> = Offset(),
+    vectorOfFlex flex: Offset<UOffset> = Offset(),
+    vectorOfTest5 test5: Offset<UOffset> = Offset(),
+    vectorOfVectorOfLongs vectorOfLongs: Offset<UOffset> = Offset(),
+    vectorOfVectorOfDoubles vectorOfDoubles: Offset<UOffset> = Offset(),
+    offsetOfParentNamespaceTest parentNamespaceTest: Offset<UOffset> = Offset(),
+    vectorOfVectorOfReferrables vectorOfReferrables: Offset<UOffset> = Offset(),
+    singleWeakReference: UInt64 = 0,
+    vectorOfVectorOfWeakReferences vectorOfWeakReferences: Offset<UOffset> = Offset(),
+    vectorOfVectorOfStrongReferrables vectorOfStrongReferrables: Offset<UOffset> = Offset(),
+    coOwningReference: UInt64 = 0,
+    vectorOfVectorOfCoOwningReferences vectorOfCoOwningReferences: Offset<UOffset> = Offset(),
+    nonOwningReference: UInt64 = 0,
+    vectorOfVectorOfNonOwningReferences vectorOfNonOwningReferences: Offset<UOffset> = Offset(),
+    anyUniqueType: MyGame_Example_AnyUniqueAliases = .none_,
+    offsetOfAnyUnique anyUnique: Offset<UOffset> = Offset(),
+    anyAmbiguousType: MyGame_Example_AnyAmbiguousAliases = .none_,
+    offsetOfAnyAmbiguous anyAmbiguous: Offset<UOffset> = Offset(),
+    vectorOfVectorOfEnums vectorOfEnums: Offset<UOffset> = Offset(),
+    signedEnum: MyGame_Example_Race = .none_,
+    vectorOfTestrequirednestedflatbuffer testrequirednestedflatbuffer: Offset<UOffset> = Offset()
+  ) -> Offset<UOffset> {
+    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<UOffset>], _ fbb: inout FlatBufferBuilder) -> Offset<UOffset> {
     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<UOffset>] = []
     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
index 88cb4fb..3eb267c 100644 (file)
@@ -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<UOffset> {
+  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout Rapunzel?) -> Offset<UOffset> {
     guard var obj = obj else { return Offset<UOffset>() }
     return pack(&builder, obj: &obj)
   }
 
-  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout RapunzelT) -> Offset<UOffset> {
-    return createRapunzel(builder: &builder, hairLength: obj.hairLength)
+  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout Rapunzel) -> Offset<UOffset> {
+    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<UOffset> {
+  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout BookReader?) -> Offset<UOffset> {
     guard var obj = obj else { return Offset<UOffset>() }
     return pack(&builder, obj: &obj)
   }
 
-  public static func pack(_ builder: inout FlatBufferBuilder, obj: inout BookReaderT) -> Offset<UOffset> {
-    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<UOffset> {
+    return builder.create(struct: obj)
   }
-
-}
-extension Rapunzel {
-  @discardableResult
-  public static func createRapunzel(builder: inout FlatBufferBuilder, hairLength: Int32 = 0) -> Offset<UOffset> {
-    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<UOffset> {
-    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
         }
     }