FlatBuffersMonsterWriterTests

/*
typealias Test = MyGame_Example_Test
typealias Monster = MyGame_Example_Monster
typealias Vec3 = MyGame_Example_Vec3
typealias Stat = MyGame_Example_Stat
class FlatBuffersMonsterWriterTests: XCTestCase {
  func testData() {
    // swiftformat:disable all
    let data: [UInt8] = [48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0]
    // swiftformat:enable all
    let _data = ByteBuffer(bytes: data)
    readVerifiedMonster(fb: _data)
  }
  func testCreateMonster() {
    let bytes = createMonster(withPrefix: false)
    // swiftformat:disable all
    XCTAssertEqual(bytes.sizedByteArray, [48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
    // swiftformat:enable all
    let monster = MyGame_Example_Monster.getRootAsMonster(bb: bytes.buffer)
    readMonster(monster: monster)
    mutateMonster(fb: bytes.buffer)
    readMonster(monster: monster)
  }
  func testCreateMonsterResizedBuffer() {
    let bytes = createMonster(withPrefix: false)
    // swiftformat:disable all
    XCTAssertEqual(bytes.sizedByteArray, [48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
    // swiftformat:enable all
    readVerifiedMonster(fb: bytes.sizedBuffer)
  }
  func testCreateMonsterPrefixed() {
    let bytes = createMonster(withPrefix: true)
    // swiftformat:disable all
    XCTAssertEqual(bytes.sizedByteArray, [44, 1, 0, 0, 44, 0, 0, 0, 77, 79, 78, 83, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
    // swiftformat:enable all
    var buffer = bytes.buffer
    readMonster(monster: getPrefixedSizeRoot(byteBuffer: &buffer))
  }
  func testCreateMonsterUsingCreateMonsterMethodWithNilPos() {
    var fbb = FlatBufferBuilder(initialSize: 1)
    let name = fbb.create(string: "Frodo")
    let mStart = Monster.startMonster(&fbb)
    Monster.add(name: name, &fbb)
    let root = Monster.endMonster(&fbb, start: mStart)
    fbb.finish(offset: root)
    let newMonster = Monster.getRootAsMonster(bb: fbb.sizedBuffer)
    XCTAssertNil(newMonster.pos)
    XCTAssertEqual(newMonster.name, "Frodo")
  }
  func testCreateMonsterUsingCreateMonsterMethodWithPosX() {
    var fbb = FlatBufferBuilder(initialSize: 1)
    let name = fbb.create(string: "Barney")
    let mStart = Monster.startMonster(&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)
    let newMonster = Monster.getRootAsMonster(bb: fbb.sizedBuffer)
    XCTAssertEqual(newMonster.pos!.x, 10)
    XCTAssertEqual(newMonster.name, "Barney")
  }
  func testArrayOfBools() {
    let boolArray = [false, true, false, true, false, true, false]
    var fbb = FlatBufferBuilder(initialSize: 1)
    let name = fbb.create(string: "Frodo")
    let bools = fbb.createVector(boolArray)
    let root = Monster.createMonster(
      &fbb,
      nameOffset: name,
      testarrayofboolsVectorOffset: bools)
    fbb.finish(offset: root)
    let monster = Monster.getRootAsMonster(bb: fbb.sizedBuffer)
    let values = monster.testarrayofbools
    XCTAssertEqual(boolArray, values)
    for i in 0..<monster.testarrayofboolsCount {
      XCTAssertEqual(boolArray[Int(i)], monster.testarrayofbools(at: i))
    }
  }
  func readVerifiedMonster(fb: ByteBuffer) {
    var byteBuffer = fb
    XCTAssertNoThrow(
      try readMonster(
        monster: getCheckedRoot(
          byteBuffer: &byteBuffer) as MyGame_Example_Monster))
  }
  func readMonster(monster: Monster) {
    var monster = monster
    readFlatbufferMonster(monster: &monster)
    let unpacked: MyGame_Example_MonsterT? = monster.unpack()
    readObjectApi(monster: unpacked!)
    guard let buffer = unpacked?.serialize()
    else { fatalError("Couldnt generate bytebuffer") }
    var newMonster = Monster.getRootAsMonster(bb: buffer)
    readFlatbufferMonster(monster: &newMonster)
  }
  func createMonster(withPrefix prefix: Bool) -> FlatBufferBuilder {
    var fbb = FlatBufferBuilder(initialSize: 1)
    let names = [
      fbb.create(string: "Frodo"),
      fbb.create(string: "Barney"),
      fbb.create(string: "Wilma"),
    ]
    var offsets: [Offset] = []
    let start1 = Monster.startMonster(&fbb)
    Monster.add(name: names[0], &fbb)
    offsets.append(Monster.endMonster(&fbb, start: start1))
    let start2 = Monster.startMonster(&fbb)
    Monster.add(name: names[1], &fbb)
    offsets.append(Monster.endMonster(&fbb, start: start2))
    let start3 = Monster.startMonster(&fbb)
    Monster.add(name: names[2], &fbb)
    offsets.append(Monster.endMonster(&fbb, start: start3))
    let sortedArray = Monster.sortVectorOfMonster(offsets: offsets, &fbb)
    let str = fbb.create(string: "MyMonster")
    let test1 = fbb.create(string: "test1")
    let test2 = fbb.create(string: "test2")
    let _inv: [Byte] = [0, 1, 2, 3, 4]
    let inv = fbb.createVector(_inv)
    let fred = fbb.create(string: "Fred")
    let mon1Start = Monster.startMonster(&fbb)
    Monster.add(name: fred, &fbb)
    let mon2 = Monster.endMonster(&fbb, start: mon1Start)
    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)
    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)
    Monster.add(testType: .monster, &fbb)
    Monster.add(test: mon2, &fbb)
    Monster.addVectorOf(test4: test4, &fbb)
    Monster.addVectorOf(testarrayofstring: stringTestVector, &fbb)
    Monster.add(testbool: true, &fbb)
    Monster.addVectorOf(testarrayoftables: sortedArray, &fbb)
    let end = Monster.endMonster(&fbb, start: mStart)
    Monster.finish(&fbb, end: end, prefix: prefix)
    return fbb
  }
  func mutateMonster(fb: ByteBuffer) {
    let monster = Monster.getRootAsMonster(bb: fb)
    XCTAssertFalse(monster.mutate(mana: 10))
    XCTAssertEqual(monster.testarrayoftables(at: 0)?.name, "Barney")
    XCTAssertEqual(monster.testarrayoftables(at: 1)?.name, "Frodo")
    XCTAssertEqual(monster.testarrayoftables(at: 2)?.name, "Wilma")
    // Example of searching for a table by the key
    XCTAssertNotNil(monster.testarrayoftablesBy(key: "Frodo"))
    XCTAssertNotNil(monster.testarrayoftablesBy(key: "Barney"))
    XCTAssertNotNil(monster.testarrayoftablesBy(key: "Wilma"))
    XCTAssertEqual(monster.testType, .monster)
    XCTAssertEqual(monster.mutate(inventory: 1, at: 0), true)
    XCTAssertEqual(monster.mutate(inventory: 2, at: 1), true)
    XCTAssertEqual(monster.mutate(inventory: 3, at: 2), true)
    XCTAssertEqual(monster.mutate(inventory: 4, at: 3), true)
    XCTAssertEqual(monster.mutate(inventory: 5, at: 4), true)
    for i in 0..<monster.inventoryCount {
      XCTAssertEqual(monster.inventory(at: i), Byte(i + 1))
    }
    XCTAssertEqual(monster.mutate(inventory: 0, at: 0), true)
    XCTAssertEqual(monster.mutate(inventory: 1, at: 1), true)
    XCTAssertEqual(monster.mutate(inventory: 2, at: 2), true)
    XCTAssertEqual(monster.mutate(inventory: 3, at: 3), true)
    XCTAssertEqual(monster.mutate(inventory: 4, at: 4), true)
    let vec = monster.mutablePos
    XCTAssertEqual(vec?.x, 1)
    XCTAssertTrue(vec?.mutate(x: 55.0) ?? false)
    XCTAssertTrue(vec?.mutate(test1: 55) ?? false)
    XCTAssertEqual(vec?.x, 55.0)
    XCTAssertEqual(vec?.test1, 55.0)
    XCTAssertTrue(vec?.mutate(x: 1) ?? false)
    XCTAssertEqual(vec?.x, 1)
    XCTAssertTrue(vec?.mutate(test1: 3) ?? false)
  }
  func readFlatbufferMonster(monster: inout MyGame_Example_Monster) {
    XCTAssertEqual(monster.hp, 80)
    XCTAssertEqual(monster.mana, 150)
    XCTAssertEqual(monster.name, "MyMonster")
    let pos = monster.pos
    XCTAssertEqual(pos?.x, 1)
    XCTAssertEqual(pos?.y, 2)
    XCTAssertEqual(pos?.z, 3)
    XCTAssertEqual(pos?.test1, 3)
    XCTAssertEqual(pos?.test2, .green)
    let test = pos?.test3
    XCTAssertEqual(test?.a, 5)
    XCTAssertEqual(test?.b, 6)
    XCTAssertEqual(monster.testType, .monster)
    let monster2 = monster.test(type: Monster.self)
    XCTAssertEqual(monster2?.name, "Fred")
    XCTAssertEqual(monster.mutate(mana: 10), false)
    XCTAssertEqual(monster.mana, 150)
    XCTAssertEqual(monster.inventoryCount, 5)
    var sum: Byte = 0
    for i in 0...monster.inventoryCount {
      sum += monster.inventory(at: i)
    }
    XCTAssertEqual(sum, 10)
    XCTAssertEqual(monster.test4Count, 2)
    let test0 = monster.test4(at: 0)
    let test1 = monster.test4(at: 1)
    var sum0 = 0
    var sum1 = 0
    if let a = test0?.a, let b = test0?.b {
      sum0 = Int(a) + Int(b)
    }
    if let a = test1?.a, let b = test1?.b {
      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")
    XCTAssertEqual(monster.testbool, true)
    let array = monster.nameSegmentArray
    XCTAssertEqual(String(bytes: array ?? [], encoding: .utf8), "MyMonster")
    if 0 == monster.testarrayofboolsCount  {
      XCTAssertEqual(monster.testarrayofbools.isEmpty, true)
    } else {
      XCTAssertEqual(monster.testarrayofbools.isEmpty, false)
    }
  }
  func readObjectApi(monster: MyGame_Example_MonsterT) {
    XCTAssertEqual(monster.hp, 80)
    XCTAssertEqual(monster.mana, 150)
    XCTAssertEqual(monster.name, "MyMonster")
    let pos = monster.pos
    XCTAssertEqual(pos?.x, 1)
    XCTAssertEqual(pos?.y, 2)
    XCTAssertEqual(pos?.z, 3)
    XCTAssertEqual(pos?.test1, 3)
    XCTAssertEqual(pos?.test2, .green)
    let test = pos?.test3
    XCTAssertEqual(test?.a, 5)
    XCTAssertEqual(test?.b, 6)
    let monster2 = monster.test?.value as? MyGame_Example_MonsterT
    XCTAssertEqual(monster2?.name, "Fred")
    XCTAssertEqual(monster.mana, 150)
    monster.mana = 10
    XCTAssertEqual(monster.mana, 10)
    monster.mana = 150
    XCTAssertEqual(monster.mana, 150)
    XCTAssertEqual(monster.inventory.count, 5)
    var sum: Byte = 0
    for i in monster.inventory {
      sum += i
    }
    XCTAssertEqual(sum, 10)
    XCTAssertEqual(monster.test4.count, 2)
    let test0 = monster.test4[0]
    let test1 = monster.test4[1]
    var sum0 = 0
    var sum1 = 0
    if let a = test0?.a, let b = test0?.b {
      sum0 = Int(a) + Int(b)
    }
    if let a = test1?.a, let b = test1?.b {
      sum1 = Int(a) + Int(b)
    }
    XCTAssertEqual(sum0 + sum1, 100)
    XCTAssertEqual(monster.testbool, true)
  }
  var jsonData: String {
    """
    {\"hp\":80,\"inventory\":[0,1,2,3,4],\"test\":{\"name\":\"Fred\"},\"testarrayofstring\":[\"test1\",\"test2\"],\"testarrayoftables\":[{\"name\":\"Barney\"},{\"name\":\"Frodo\"},{\"name\":\"Wilma\"}],\"test4\":[{\"a\":30,\"b\":40},{\"a\":10,\"b\":20}],\"testbool\":true,\"test_type\":\"Monster\",\"pos\":{\"y\":2,\"test3\":{\"a\":5,\"b\":6},\"z\":3,\"x\":1,\"test1\":3,\"test2\":\"Green\"},\"name\":\"MyMonster\"}
    """
  }
}


// swift-tools-version:5.5
/*
 */
import PackageDescription
let package = Package(
  name: "FlatBuffers",
  platforms: [
    .iOS(.v11),
    .macOS(.v10_14),
  ],
  products: [
    .library(
      name: "FlatBuffers",
      targets: ["FlatBuffers"]),
  ],
  targets: [
    .target(
      name: "FlatBuffers",
      dependencies: []),
  ])


Package

// swift-tools-version:5.2
/*
 */
import PackageDescription
let package = Package(
  name: "FlatBuffers",
  platforms: [
    .iOS(.v11),
    .macOS(.v10_14),
  ],
  products: [
    .library(
      name: "FlatBuffers",
      targets: ["FlatBuffers"]),
  ],
  targets: [
    .target(
      name: "FlatBuffers",
      dependencies: [],
      exclude: ["Documentation.docc/Resources/code/swift"]),
  ])


Offset

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// Offset object for all the Objects that are written into the buffer
public struct Offset {
  /// Offset of the object in the buffer
  public var o: UOffset
  /// Returns false if the offset is equal to zero
  public var isEmpty: Bool { o == 0 }
  public init(offset: UOffset) { o = offset }
  public init() { o = 0 }
}


Verifiable

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// Verifiable is a protocol all swift flatbuffers object should conform to,
/// since swift is similar to `cpp` and `rust` where the data is read directly
/// from `unsafeMemory` thus the need to verify if the buffer received is a valid one
public protocol Verifiable {
  /// Verifies that the current value is which the bounds of the buffer, and if
  /// the current `Value` is aligned properly
  /// - Parameters:
  ///   - verifier: Verifier that hosts the buffer
  ///   - position: Current position within the buffer
  ///   - type: The type of the object to be verified
  /// - Throws: Errors coming from `inBuffer` function
  static func verify<T>(
    _ verifier: inout Verifier,
    at position: Int,
    of type: T.Type) throws where T: Verifiable
}
extension Verifiable {
  /// Verifies if the current range to be read is within the bounds of the buffer,
  /// and if the range is properly aligned
  /// - Parameters:
  ///   - verifier: Verifier that hosts the buffer
  ///   - position: Current position within the buffer
  ///   - type: The type of the object to be verified
  /// - Throws: Erros thrown from `isAligned` & `rangeInBuffer`
  /// - Returns: a tuple of the start position and the count of objects within the range
  public static func verifyRange<T>(
    _ verifier: inout Verifier,
    at position: Int, of type: T.Type) throws -> (start: Int, count: Int)
  {
    let len: UOffset = try verifier.getValue(at: position)
    let intLen = Int(len)
    let start = Int(clamping: (position &+ MemoryLayout<Int32>.size).magnitude)
    try verifier.isAligned(position: start, type: type.self)
    try verifier.rangeInBuffer(position: start, size: intLen)
    return (start, intLen)
  }
}
extension Verifiable where Self: Scalar {
  /// Verifies that the current value is which the bounds of the buffer, and if
  /// the current `Value` is aligned properly
  /// - Parameters:
  ///   - verifier: Verifier that hosts the buffer
  ///   - position: Current position within the buffer
  ///   - type: The type of the object to be verified
  /// - Throws: Errors coming from `inBuffer` function
  public static func verify<T>(
    _ verifier: inout Verifier,
    at position: Int,
    of type: T.Type) throws where T: Verifiable
  {
    try verifier.inBuffer(position: position, of: type.self)
  }
}
// MARK: - ForwardOffset
/// ForwardOffset is a container to wrap around the Generic type to be verified
/// from the flatbuffers object.
public enum ForwardOffset<U>: Verifiable where U: Verifiable {
  /// Verifies that the current value is which the bounds of the buffer, and if
  /// the current `Value` is aligned properly
  /// - Parameters:
  ///   - verifier: Verifier that hosts the buffer
  ///   - position: Current position within the buffer
  ///   - type: The type of the object to be verified
  /// - Throws: Errors coming from `inBuffer` function
  public static func verify<T>(
    _ verifier: inout Verifier,
    at position: Int,
    of type: T.Type) throws where T: Verifiable
  {
    let offset: UOffset = try verifier.getValue(at: position)
    let nextOffset = Int(clamping: (Int(offset) &+ position).magnitude)
    try U.verify(&verifier, at: nextOffset, of: U.self)
  }
}
// MARK: - Vector
/// Vector is a container to wrap around the Generic type to be verified
/// from the flatbuffers object.
public enum Vector<U, S>: Verifiable where U: Verifiable, S: Verifiable {
  /// Verifies that the current value is which the bounds of the buffer, and if
  /// the current `Value` is aligned properly
  /// - Parameters:
  ///   - verifier: Verifier that hosts the buffer
  ///   - position: Current position within the buffer
  ///   - type: The type of the object to be verified
  /// - Throws: Errors coming from `inBuffer` function
  public static func verify<T>(
    _ verifier: inout Verifier,
    at position: Int,
    of type: T.Type) throws where T: Verifiable
  {
    /// checks if the next verification type S is equal to U of type forwardOffset
    /// This had to be done since I couldnt find a solution for duplicate call functions
    /// A fix will be appreciated
    if U.self is ForwardOffset<S>.Type {
      let range = try verifyRange(&verifier, at: position, of: UOffset.self)
      for index in stride(
        from: range.start,
        to: Int(clamping: range.start &+ range.count),
        by: MemoryLayout<UOffset>.size)
      {
        try U.verify(&verifier, at: index, of: U.self)
      }
    } else {
      try S.verifyRange(&verifier, at: position, of: S.self)
    }
  }
}
// MARK: - UnionVector
/// UnionVector is a container to wrap around the Generic type to be verified
/// from the flatbuffers object.
public enum UnionVector<S> where S: UnionEnum {
  /// Completion handler for the function Verify, that passes the verifier
  /// enum type and position of union field
  public typealias Completion = (inout Verifier, S, Int) throws -> Void
  /// Verifies if the current range to be read is within the bounds of the buffer,
  /// and if the range is properly aligned. It also verifies if the union type is a
  /// *valid/supported* union type.
  /// - Parameters:
  ///   - verifier: Verifier that hosts the buffer
  ///   - keyPosition: Current union key position within the buffer
  ///   - fieldPosition: Current union field position within the buffer
  ///   - unionKeyName: Name of key to written if error is presented
  ///   - fieldName: Name of field to written if error is presented
  ///   - completion: Completion is a handler that WILL be called in the generated
  ///   code to verify the actual objects
  /// - Throws: FlatbuffersErrors
  public static func verify(
    _ verifier: inout Verifier,
    keyPosition: Int,
    fieldPosition: Int,
    unionKeyName: String,
    fieldName: String,
  {
    /// Get offset for union key vectors and offset vectors
    let keyOffset: UOffset = try verifier.getValue(at: keyPosition)
    let fieldOffset: UOffset = try verifier.getValue(at: fieldPosition)
    /// Check if values are within the buffer, returns the start position of vectors, and vector counts
    /// Using &+ is safe since we already verified that the value is within the buffer, where the max is
    /// going to be 2Gib and swift supports Int64 by default
    let keysRange = try S.T.verifyRange(
      &verifier,
      at: Int(keyOffset) &+ keyPosition,
      of: S.T.self)
    let offsetsRange = try UOffset.verifyRange(
      &verifier,
      at: Int(fieldOffset) &+ fieldPosition,
      of: UOffset.self)
    guard keysRange.count == offsetsRange.count else {
      throw FlatbuffersErrors.unionVectorSize(
        keyVectorSize: keysRange.count,
        fieldVectorSize: offsetsRange.count,
        unionKeyName: unionKeyName,
        fieldName: fieldName)
    }
    var count = 0
    /// Iterate over the vector of keys and offsets.
    while count < keysRange.count {
      /// index of readable enum value in array
      let keysIndex = MemoryLayout<S.T>.size * count
      guard let _enum = try S.init(value: verifier._buffer.read(
        def: S.T.self,
        position: keysRange.start + keysIndex)) else
      {
        throw FlatbuffersErrors.unknownUnionCase
      }
      /// index of readable offset value in array
      let fieldIndex = MemoryLayout<UOffset>.size * count
      try completion(&verifier, _enum, offsetsRange.start + fieldIndex)
      count += 1
    }
  }
}


String+extension

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
extension String: Verifiable {
  /// Verifies that the current value is which the bounds of the buffer, and if
  /// the current `Value` is aligned properly
  /// - Parameters:
  ///   - verifier: Verifier that hosts the buffer
  ///   - position: Current position within the buffer
  ///   - type: The type of the object to be verified
  /// - Throws: Errors coming from `inBuffer`, `missingNullTerminator` and `outOfBounds`
  public static func verify<T>(
    _ verifier: inout Verifier,
    at position: Int,
    of type: T.Type) throws where T: Verifiable
  {
    let range = try String.verifyRange(&verifier, at: position, of: UInt8.self)
    /// Safe &+ since we already check for overflow in verify range
    let stringLen = range.start &+ range.count
    if stringLen >= verifier.capacity {
      throw FlatbuffersErrors.outOfBounds(
        position: UInt(clamping: stringLen.magnitude),
        end: verifier.capacity)
    }
    let isNullTerminated = verifier._buffer.read(
      def: UInt8.self,
      position: stringLen) == 0
    if !verifier._options._ignoreMissingNullTerminators && !isNullTerminated {
      let str = verifier._buffer.readString(at: range.start, count: range.count)
      throw FlatbuffersErrors.missingNullTerminator(
        position: position,
        str: str)
    }
  }
}
extension String: FlatbuffersInitializable {
  /// Initailizes a string from a Flatbuffers ByteBuffer
  /// - Parameters:
  ///   - bb: ByteBuffer containing the readable string
  ///   - o: Current position
  public init(_ bb: ByteBuffer, o: Int32) {
    let v = Int(o)
    let count = bb.read(def: Int32.self, position: v)
    self = bb.readString(
      at: MemoryLayout<Int32>.size + v,
      count: Int(count)) ?? ""
  }
}
extension String: ObjectAPIPacker {
  public static func pack(
    _ builder: inout FlatBufferBuilder,
    obj: inout String?) -> Offset
  {
    guard var obj = obj else { return Offset() }
    return pack(&builder, obj: &obj)
  }
  public static func pack(
    _ builder: inout FlatBufferBuilder,
    obj: inout String) -> Offset
  {
    builder.create(string: obj)
  }
  public mutating func unpack() -> String {
    self
  }
}
extension String: NativeObject {
  public func serialize<T: ObjectAPIPacker>(type: T.Type) -> ByteBuffer
    where T.T == Self
  {
    fatalError("serialize should never be called from string directly")
  }
  public func serialize<T: ObjectAPIPacker>(
    builder: inout FlatBufferBuilder,
    type: T.Type) -> ByteBuffer where T.T == Self
  {
    fatalError("serialize should never be called from string directly")
  }
}


Root

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// Takes in a prefixed sized buffer, where the prefixed size would be skipped.
/// And would verify that the buffer passed is a valid `Flatbuffers` Object.
/// - Parameters:
///   - byteBuffer: Buffer that needs to be checked and read
///   - options: Verifier options
/// - Throws: FlatbuffersErrors
/// - Returns: Returns a valid, checked Flatbuffers object
///
/// ``getPrefixedSizeCheckedRoot(byteBuffer:options:)`` would skip the first Bytes in
/// the ``ByteBuffer`` and verifies the buffer by calling ``getCheckedRoot(byteBuffer:options:)``
public func getPrefixedSizeCheckedRoot<T: FlatBufferObject & Verifiable>(
  byteBuffer: inout ByteBuffer,
  fileId: String? = nil,
  options: VerifierOptions = .init()) throws -> T
{
  byteBuffer.skipPrefix()
  return try getCheckedRoot(
    byteBuffer: &byteBuffer,
    fileId: fileId,
    options: options)
}
/// Takes in a prefixed sized buffer, where we check if the sized buffer is equal to prefix size.
/// And would verify that the buffer passed is a valid `Flatbuffers` Object.
/// - Parameters:
///   - byteBuffer: Buffer that needs to be checked and read
///   - options: Verifier options
/// - Throws: FlatbuffersErrors
/// - Returns: Returns a valid, checked Flatbuffers object
///
/// ``getPrefixedSizeCheckedRoot(byteBuffer:options:)`` would skip the first Bytes in
/// the ``ByteBuffer`` and verifies the buffer by calling ``getCheckedRoot(byteBuffer:options:)``
public func getCheckedPrefixedSizeRoot<T: FlatBufferObject & Verifiable>(
  byteBuffer: inout ByteBuffer,
  fileId: String? = nil,
  options: VerifierOptions = .init()) throws -> T
{
  let prefix = byteBuffer.skipPrefix()
  if prefix != byteBuffer.size {
    throw FlatbuffersErrors.prefixedSizeNotEqualToBufferSize
  }
  return try getCheckedRoot(
    byteBuffer: &byteBuffer,
    fileId: fileId,
    options: options)
}
/// Takes in a prefixed sized buffer, where the prefixed size would be skipped.
/// Returns a `NON-Checked` flatbuffers object
/// - Parameter byteBuffer: Buffer that contains data
/// - Returns: Returns a Flatbuffers object
///
/// ``getPrefixedSizeCheckedRoot(byteBuffer:options:)`` would skip the first Bytes in
/// the ``ByteBuffer`` and then calls ``getRoot(byteBuffer:)``
public func getPrefixedSizeRoot<T: FlatBufferObject>(byteBuffer: inout ByteBuffer)
  -> T
{
  byteBuffer.skipPrefix()
  return getRoot(byteBuffer: &byteBuffer)
}
/// Verifies that the buffer passed is a valid `Flatbuffers` Object.
/// - Parameters:
///   - byteBuffer: Buffer that needs to be checked and read
///   - options: Verifier options
/// - Throws: FlatbuffersErrors
/// - Returns: Returns a valid, checked Flatbuffers object
///
/// ``getCheckedRoot(byteBuffer:options:)`` Takes in a ``ByteBuffer`` and verifies
/// that by creating a ``Verifier`` and checkes if all the `Bytes` and correctly aligned
/// and within the ``ByteBuffer`` range.
public func getCheckedRoot<T: FlatBufferObject & Verifiable>(
  byteBuffer: inout ByteBuffer,
  fileId: String? = nil,
  options: VerifierOptions = .init()) throws -> T
{
  var verifier = try Verifier(buffer: &byteBuffer, options: options)
  if let fileId = fileId {
    try verifier.verify(id: fileId)
  }
  try ForwardOffset<T>.verify(&verifier, at: 0, of: T.self)
  return T.init(
    byteBuffer,
    o: Int32(byteBuffer.read(def: UOffset.self, position: byteBuffer.reader)) +
      Int32(byteBuffer.reader))
}
/// Returns a `NON-Checked` flatbuffers object
/// - Parameter byteBuffer: Buffer that contains data
/// - Returns: Returns a Flatbuffers object
public func getRoot<T: FlatBufferObject>(byteBuffer: inout ByteBuffer) -> T {
  T.init(
    byteBuffer,
    o: Int32(byteBuffer.read(def: UOffset.self, position: byteBuffer.reader)) +
      Int32(byteBuffer.reader))
}


Mutable

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// Mutable is a protocol that allows us to mutate Scalar values within a ``ByteBuffer``
public protocol Mutable {
  /// makes Flatbuffer accessed within the Protocol
  var bb: ByteBuffer { get }
  /// makes position of the ``Table``/``struct`` accessed within the Protocol
  var postion: Int32 { get }
}
extension Mutable {
  /// Mutates the memory in the buffer, this is only called from the access function of ``Table`` and ``struct``
  /// - Parameters:
  ///   - value: New value to be inserted to the buffer
  ///   - index: index of the Element
  func mutate<T: Scalar>(value: T, o: Int32) -> Bool {
    guard o != 0 else { return false }
    bb.write(value: value, index: Int(o), direct: true)
    return true
  }
}
extension Mutable where Self == Table {
  /// Mutates a value by calling mutate with respect to the position in a ``Table``
  /// - Parameters:
  ///   - value: New value to be inserted to the buffer
  ///   - index: index of the Element
  public func mutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
    guard index != 0 else { return false }
    return mutate(value: value, o: index + postion)
  }
  /// Directly mutates the element by calling mutate
  ///
  /// Mutates the Element at index ignoring the current position by calling mutate
  /// - Parameters:
  ///   - value: New value to be inserted to the buffer
  ///   - index: index of the Element
  public func directMutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
    mutate(value: value, o: index)
  }
}
extension Mutable where Self == Struct {
  /// Mutates a value by calling mutate with respect to the position in the struct
  /// - Parameters:
  ///   - value: New value to be inserted to the buffer
  ///   - index: index of the Element
  public func mutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
    mutate(value: value, o: index + postion)
  }
  /// Directly mutates the element by calling mutate
  ///
  /// Mutates the Element at index ignoring the current position by calling mutate
  /// - Parameters:
  ///   - value: New value to be inserted to the buffer
  ///   - index: index of the Element
  public func directMutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
    mutate(value: value, o: index)
  }
}
extension Struct: Mutable {}
extension Table: Mutable {}


Int+extension

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
extension Int {
  /// Moves the current int into the nearest power of two
  ///
  /// This is used since the UnsafeMutableRawPointer will face issues when writing/reading
  /// if the buffer alignment exceeds that actual size of the buffer
  var convertToPowerofTwo: Int {
    guard self > 0 else { return 1 }
    var n = UOffset(self)
    #if arch(arm) || arch(i386)
    let max = UInt32(Int.max)
    #else
    let max = UInt32.max
    #endif
    n -= 1
    n |= n >> 1
    n |= n >> 2
    n |= n >> 4
    n |= n >> 8
    n |= n >> 16
    if n != max {
      n += 1
    }
    return Int(n)
  }
}


FlatbuffersErrors

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// Collection of thrown from the Flatbuffer verifier
public enum FlatbuffersErrors: Error, Equatable {
  /// Thrown when verifying a file id that doesnt match buffer id
  case bufferIdDidntMatchPassedId
  /// Prefixed size doesnt match the current (readable) buffer size
  case prefixedSizeNotEqualToBufferSize
  /// Thrown when buffer is bigger than the allowed 2GiB
  case exceedsMaxSizeAllowed
  /// Thrown when there is an missaligned pointer at position
  /// of type
  case missAlignedPointer(position: Int, type: String)
  /// Thrown when trying to read a value that goes out of the
  /// current buffer bounds
  case outOfBounds(position: UInt, end: Int)
  /// Thrown when the signed offset is out of the bounds of the
  /// current buffer
  case signedOffsetOutOfBounds(offset: Int, position: Int)
  /// Thrown when a required field doesnt exist within the buffer
  case requiredFieldDoesntExist(position: VOffset, name: String)
  /// Thrown when a string is missing its NULL Terminator `\0`,
  /// this can be disabled in the `VerifierOptions`
  case missingNullTerminator(position: Int, str: String?)
  /// Thrown when the verifier has reached the maximum tables allowed,
  /// this can be disabled in the `VerifierOptions`
  case maximumTables
  /// Thrown when the verifier has reached the maximum depth allowed,
  /// this can be disabled in the `VerifierOptions`
  case maximumDepth
  /// Thrown when the verifier is presented with an unknown union case
  case unknownUnionCase
  /// thrown when a value for a union is not found within the buffer
  case valueNotFound(key: Int?, keyName: String, field: Int?, fieldName: String)
  /// thrown when the size of the keys vector doesnt match fields vector
  case unionVectorSize(
    keyVectorSize: Int,
    fieldVectorSize: Int,
    unionKeyName: String,
    fieldName: String)
  case apparentSizeTooLarge
}
#if !os(WASI)
extension FlatbuffersErrors {
    public static func == (
      lhs: FlatbuffersErrors,
      rhs: FlatbuffersErrors) -> Bool
    {
      lhs.localizedDescription == rhs.localizedDescription
    }
}
#endif


TableVerifier

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// `TableVerifier` verifies a table object is within a provided memory.
/// It checks if all the objects for a specific generated table, are within
/// the bounds of the buffer, aligned.
public struct TableVerifier {
  /// position of current table in `ByteBuffer`
  fileprivate var _position: Int
  /// Current VTable position
  fileprivate var _vtable: Int
  /// Length of current VTable
  fileprivate var _vtableLength: Int
  /// `Verifier` object created in the base verifable call.
  fileprivate var _verifier: Verifier
  /// Creates a `TableVerifier` verifier that allows the Flatbuffer object
  /// to verify the buffer before accessing any of the data.
  ///
  /// - Parameters:
  ///   - position: Current table Position
  ///   - vtable: Current `VTable` position
  ///   - vtableLength: Current `VTable` length
  ///   - verifier: `Verifier` Object  that caches the data of the verifiable object
  internal init(
    position: Int,
    vtable: Int,
    vtableLength: Int,
    verifier: inout Verifier)
  {
    _position = position
    _vtable = vtable
    _vtableLength = vtableLength
    _verifier = verifier
  }
  /// Dereference the current object position from the `VTable`
  /// - Parameter field: Current VTable refrence to  position.
  /// - Throws: A `FlatbuffersErrors` incase the voffset is not aligned/outOfBounds/apparentSizeTooLarge
  /// - Returns: An optional position for current field
  internal mutating func dereference(_ field: VOffset) throws -> Int? {
    if field >= _vtableLength {
      return nil
    }
    /// Reading the offset for the field needs to be read.
    let offset: VOffset = try _verifier.getValue(
      at: Int(clamping: _vtable &+ Int(field)))
    if offset > 0 {
      return Int(clamping: _position &+ Int(offset))
    }
    return nil
  }
  /// Visits all the fields within the table to validate the integrity
  /// of the data
  /// - Parameters:
  ///   - field: voffset of the current field to be read
  ///   - fieldName: fieldname to report data Errors.
  ///   - required: If the field has to be available in the buffer
  ///   - type: Type of field to be read
  /// - Throws: A `FlatbuffersErrors` where the field is corrupt
  public mutating func visit<T>(
    field: VOffset,
    fieldName: String,
    required: Bool,
    type: T.Type) throws where T: Verifiable
  {
    let derefValue = try dereference(field)
    if let value = derefValue {
      try T.verify(&_verifier, at: value, of: T.self)
      return
    }
    if required {
      throw FlatbuffersErrors.requiredFieldDoesntExist(
        position: field,
        name: fieldName)
    }
  }
  /// Visits all the fields for a union object within the table to
  /// validate the integrity of the data
  /// - Parameters:
  ///   - key: Current Key Voffset
  ///   - field: Current field Voffset
  ///   - unionKeyName: Union key name
  ///   - fieldName: Field key name
  ///   - required: indicates if an object is required to be present
  ///   - completion: Completion is a handler that WILL be called in the generated
  /// - Throws: A `FlatbuffersErrors` where the field is corrupt
  public mutating func visit<T>(
    unionKey key: VOffset,
    unionField field: VOffset,
    unionKeyName: String,
    fieldName: String,
    required: Bool,
    where T: UnionEnum
  {
    let keyPos = try dereference(key)
    let valPos = try dereference(field)
    if keyPos == nil && valPos == nil {
      if required {
        throw FlatbuffersErrors.requiredFieldDoesntExist(
          position: key,
          name: unionKeyName)
      }
      return
    }
    if let _key = keyPos,
       let _val = valPos
    {
      /// verifiying that the key is within the buffer
      try T.T.verify(&_verifier, at: _key, of: T.T.self)
      guard let _enum = try T.init(value: _verifier._buffer.read(
        def: T.T.self,
        position: _key)) else
      {
        throw FlatbuffersErrors.unknownUnionCase
      }
      /// we are assuming that Unions will always be of type Uint8
      try completion(
        &_verifier,
        _enum,
        _val)
      return
    }
    throw FlatbuffersErrors.valueNotFound(
      key: keyPos,
      keyName: unionKeyName,
      field: valPos,
      fieldName: fieldName)
  }
  /// Visits and validates all the objects within a union vector
  /// - Parameters:
  ///   - key: Current Key Voffset
  ///   - field: Current field Voffset
  ///   - unionKeyName: Union key name
  ///   - fieldName: Field key name
  ///   - required: indicates if an object is required to be present
  ///   - completion: Completion is a handler that WILL be called in the generated
  /// - Throws: A `FlatbuffersErrors` where the field is corrupt
  public mutating func visitUnionVector<T>(
    unionKey key: VOffset,
    unionField field: VOffset,
    unionKeyName: String,
    fieldName: String,
    required: Bool,
    where T: UnionEnum
  {
    let keyVectorPosition = try dereference(key)
    let offsetVectorPosition = try dereference(field)
    if let keyPos = keyVectorPosition,
       let valPos = offsetVectorPosition
    {
      try UnionVector<T>.verify(
        &_verifier,
        keyPosition: keyPos,
        fieldPosition: valPos,
        unionKeyName: unionKeyName,
        fieldName: fieldName,
        completion: completion)
      return
    }
    if required {
      throw FlatbuffersErrors.requiredFieldDoesntExist(
        position: field,
        name: fieldName)
    }
  }
  /// Finishs the current Table verifier, and subtracts the current
  /// table from the incremented depth.
  public mutating func finish() {
    _verifier.finish()
  }
}


FlatBufferBuilder

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// ``FlatBufferBuilder`` builds a `FlatBuffer` through manipulating its internal state.
///
/// This is done by creating a ``ByteBuffer`` that hosts the incoming data and
/// has a hardcoded growth limit of `2GiB` which is set by the Flatbuffers standards.
///
/// ```swift
/// var builder = FlatBufferBuilder()
/// ```
/// The builder should be always created as a variable, since it would be passed into the writers
///
  /// Reference Vtables that were already written to the buffer
  private var _vtables: [UOffset] = []
  /// 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
  private var stringOffsetMap: [String: Offset] = [:]
  /// A check to see if finish(::) was ever called to retreive data object
  private var finished = false
  /// A check to see if the buffer should serialize Default values
  private var serializeDefaults: Bool
  /// Current alignment for the buffer
  var _minAlignment: Int = 0 {
    didSet {
      _bb.alignment = _minAlignment
    }
  }
  /// Gives a read access to the buffer's size
  public var size: UOffset { _bb.size }
  #if !os(WASI)
  /// Data representation of the buffer
  ///
  /// Should only be used after ``finish(offset:addPrefix:)`` is called
  public var data: Data {
    assert(finished, "Data shouldn't be called before finish()")
    return Data(
      bytes: _bb.memory.advanced(by: _bb.writerIndex),
      count: _bb.capacity &- _bb.writerIndex)
  }
  #endif
  /// Returns the underlying bytes in the ``ByteBuffer``
  ///
  /// Note: This should be used with caution.
  public var fullSizedByteArray: [UInt8] {
    let ptr = UnsafeBufferPointer(
      start: _bb.memory.assumingMemoryBound(to: UInt8.self),
      count: _bb.capacity)
    return Array(ptr)
  }
  /// Returns the written bytes into the ``ByteBuffer``
  ///
  /// Should only be used after ``finish(offset:addPrefix:)`` is called
  public var sizedByteArray: [UInt8] {
    assert(finished, "Data shouldn't be called before finish()")
    return _bb.underlyingBytes
  }
  /// Returns the original ``ByteBuffer``
  ///
  /// Returns the current buffer that was just created
  /// with the offsets, and data written to it.
  public var buffer: ByteBuffer { _bb }
  /// Returns a newly created sized ``ByteBuffer``
  ///
  /// returns a new buffer that is sized to the data written
  /// to the main buffer
  public var sizedBuffer: ByteBuffer {
    assert(finished, "Data shouldn't be called before finish()")
    return ByteBuffer(
      memory: _bb.memory.advanced(by: _bb.reader),
      count: Int(_bb.size))
  }
  // MARK: - Init
  /// Initialize the buffer with a size
  /// - Parameters:
  ///   - initialSize: Initial size for the buffer
  ///   - force: Allows default to be serialized into the buffer
  ///
  /// This initializes a new builder with an initialSize that would initialize
  /// a new ``ByteBuffer``. ``FlatBufferBuilder`` by default doesnt serialize defaults
  /// however the builder can be force by passing true for `serializeDefaults`
  public init(
    initialSize: Int32 = 1024,
    serializeDefaults force: Bool = false)
  {
    assert(initialSize > 0, "Size should be greater than zero!")
    guard isLitteEndian else {
      fatalError(
        "Reading/Writing a buffer in big endian machine is not supported on swift")
    }
    serializeDefaults = force
    _bb = ByteBuffer(initialSize: Int(initialSize))
  }
  /// Clears the builder and the buffer from the written data.
  mutating public func clear() {
    _minAlignment = 0
    isNested = false
    stringOffsetMap.removeAll(keepingCapacity: true)
    _vtables.removeAll(keepingCapacity: true)
    _vtableStorage.clear()
    _bb.clear()
  }
  // MARK: - Create Tables
  /// Checks if the required fields were serialized into the buffer
  /// - Parameters:
  ///   - table: offset for the table
  ///   - fields: Array of all the important fields to be serialized
  ///
  /// *NOTE: Never call this function, this is only supposed to be called
  /// by the generated code*
  mutating public func require(table: Offset, fields: [Int32]) {
    for field in fields {
      let start = _bb.capacity &- Int(table.o)
      let startTable = start &- Int(_bb.read(def: Int32.self, position: start))
      let isOkay = _bb.read(
        def: VOffset.self,
        position: startTable &+ Int(field)) != 0
      assert(isOkay, "Flatbuffers requires the following field")
    }
  }
  /// Finished the buffer by adding the file id and then calling finish
  /// - Parameters:
  ///   - offset: Offset of the table
  ///   - fileId: Takes the fileId
  ///   - prefix: if false it wont add the size of the buffer
  ///
  /// ``finish(offset:fileId:addPrefix:)`` should be called at the end of creating
  /// a table
  /// ```swift
  /// var root = SomeObject
  ///   .createObject(&builder,
  ///   name: nameOffset)
  /// builder.finish(
  ///   offset: root,
  ///   fileId: "ax1a",
  ///   addPrefix: true)
  /// ```
  /// File id would append a file id name at the end of the written bytes before,
  /// finishing the buffer.
  ///
  /// Whereas, if `addPrefix` is true, the written bytes would
  /// include the size of the current buffer.
  mutating public func finish(
    offset: Offset,
    fileId: String,
    addPrefix prefix: Bool = false)
  {
    let size = MemoryLayout<UOffset>.size
    preAlign(
      len: size &+ (prefix ? size : 0) &+ FileIdLength,
      alignment: _minAlignment)
    assert(fileId.count == FileIdLength, "Flatbuffers requires file id to be 4")
    _bb.push(string: fileId, len: 4)
    finish(offset: offset, addPrefix: prefix)
  }
  /// Finished the buffer by adding the file id, offset, and prefix to it.
  /// - Parameters:
  ///   - offset: Offset of the table
  ///   - prefix: if false it wont add the size of the buffer
  ///
  /// ``finish(offset:addPrefix:)`` should be called at the end of creating
  /// a table
  /// ```swift
  /// var root = SomeObject
  ///   .createObject(&builder,
  ///   name: nameOffset)
  /// builder.finish(
  ///   offset: root,
  ///   addPrefix: true)
  /// ```
  /// If `addPrefix` is true, the written bytes would
  /// include the size of the current buffer.
  mutating public func finish(
    offset: Offset,
    addPrefix prefix: Bool = false)
  {
    notNested()
    let size = MemoryLayout<UOffset>.size
    preAlign(len: size &+ (prefix ? size : 0), alignment: _minAlignment)
    push(element: refer(to: offset.o))
    if prefix { push(element: _bb.size) }
    _vtableStorage.clear()
    finished = true
  }
  /// ``startTable(with:)`` will let the builder know, that a new object is being serialized.
  ///
  /// The function will fatalerror if called while there is another object being serialized.
  /// ```swift
  /// let start = Monster
  ///   .startMonster(&fbb)
  /// ```
  /// - Parameter numOfFields: Number of elements to be written to the buffer
  /// - Returns: Offset of the newly started table
  mutating public func startTable(with numOfFields: Int) -> UOffset {
    notNested()
    isNested = true
    _vtableStorage.start(count: numOfFields)
    return _bb.size
  }
  /// ``endTable(at:)`` will let the ``FlatBufferBuilder`` know that the
  /// object that's written to it is completed
  ///
  /// This would be called after all the elements are serialized,
  /// it will add the current vtable into the ``ByteBuffer``.
  /// The functions will `fatalError` in case the object is called
  /// without ``startTable(with:)``, or the object has exceeded  the limit of 2GB.
  ///
  /// - Parameter startOffset:Start point of the object written
  /// - returns: The root of the table
  mutating public func endTable(at startOffset: UOffset)  -> UOffset {
    assert(isNested, "Calling endtable without calling starttable")
    let sizeofVoffset = MemoryLayout<VOffset>.size
    let vTableOffset = push(element: SOffset(0))
    let tableObjectSize = vTableOffset &- startOffset
    assert(tableObjectSize < 0x10000, "Buffer can't grow beyond 2 Gigabytes")
    let _max = Int(_vtableStorage.maxOffset) &+ sizeofVoffset
    _bb.fill(padding: _max)
    _bb.write(
      value: VOffset(tableObjectSize),
      index: _bb.writerIndex &+ sizeofVoffset,
      direct: true)
    _bb.write(value: VOffset(_max), index: _bb.writerIndex, direct: true)
    var itr = 0
    while itr < _vtableStorage.writtenIndex {
      let loaded = _vtableStorage.load(at: itr)
      itr = itr &+ _vtableStorage.size
      guard loaded.offset != 0 else { continue }
      let _index = (_bb.writerIndex &+ Int(loaded.position))
      _bb.write(
        value: VOffset(vTableOffset &- loaded.offset),
        index: _index,
        direct: true)
    }
    _vtableStorage.clear()
    let vt_use = _bb.size
    var isAlreadyAdded: Int?
    let vt2 = _bb.memory.advanced(by: _bb.writerIndex)
    let len2 = vt2.load(fromByteOffset: 0, as: Int16.self)
    for table in _vtables {
      let position = _bb.capacity &- Int(table)
      let vt1 = _bb.memory.advanced(by: position)
      let len1 = _bb.read(def: Int16.self, position: position)
      if len2 != len1 || 0 != memcmp(vt1, vt2, Int(len2)) { continue }
      isAlreadyAdded = Int(table)
      break
    }
    if let offset = isAlreadyAdded {
      let vTableOff = Int(vTableOffset)
      let space = _bb.capacity &- vTableOff
      _bb.write(value: Int32(offset &- vTableOff), index: space, direct: true)
      _bb.pop(_bb.capacity &- space)
    } else {
      _bb.write(value: Int32(vt_use &- vTableOffset), index: Int(vTableOffset))
      _vtables.append(_bb.size)
    }
    isNested = false
    return vTableOffset
  }
  // MARK: - Builds Buffer
  /// Asserts to see if the object is not nested
  mutating internal func minAlignment(size: Int) {
    if size > _minAlignment {
      _minAlignment = size
    }
  }
  /// Gets the padding for the current element
  /// - Parameters:
  ///   - bufSize: Current size of the buffer + the offset of the object to be written
  ///   - elementSize: Element size
  mutating internal func preAlign(len: Int, alignment: Int) {
    minAlignment(size: alignment)
    _bb.fill(padding: Int(padding(
      bufSize: _bb.size &+ UOffset(len),
      elementSize: UOffset(alignment))))
  }
  /// Prealigns the buffer before writting a new object into the buffer
  /// - Parameters:
  ///   - len: Length of the object
  ///   - type: Type of the object to be written
  mutating internal func refer(to off: UOffset) -> UOffset {
    let size = MemoryLayout<UOffset>.size
    preAlign(len: size, alignment: size)
    return _bb.size &- off &+ UInt32(size)
  }
  /// Tracks the elements written into the buffer
  /// - Parameters:
  ///   - offset: The offset of the element witten
  ///   - position: The position of the element
  mutating internal func track(offset: UOffset, at position: VOffset) {
    _vtableStorage.add(loc: FieldLoc(offset: offset, position: position))
  }
  // MARK: - Inserting Vectors
  /// ``startVector(_:elementSize:)`` creates a new vector within buffer
  ///
  /// The function checks if there is a current object being written, if
  /// the check passes it creates a buffer alignment of `length * elementSize`
  /// ```swift
  /// builder.startVector(
  ///   int32Values.count, elementSize: 4)
  /// ```
  ///
  /// - Parameters:
  ///   - len: Length of vector to be created
  ///   - elementSize: Size of object type to be written
  mutating public func startVector(_ len: Int, elementSize: Int) {
    notNested()
    isNested = true
    preAlign(len: len &* elementSize, type: UOffset.self)
    preAlign(len: len &* elementSize, alignment: elementSize)
  }
  /// ``endVector(len:)`` ends the currently created vector
  ///
  /// Calling ``endVector(len:)`` requires the length, of the current
  /// vector. The length would be pushed to indicate the count of numbers
  /// within the vector. If ``endVector(len:)`` is called without
  /// ``startVector(_:elementSize:)`` it asserts.
  ///
  /// ```swift
  /// let vectorOffset = builder.
  ///   endVector(len: int32Values.count)
  /// ```
  ///
  /// - Parameter len: Length of the buffer
  /// - Returns: Returns the current ``Offset`` in the ``ByteBuffer``
  mutating public func endVector(len: Int) -> Offset {
    assert(isNested, "Calling endVector without calling startVector")
    isNested = false
    return Offset(offset: push(element: Int32(len)))
  }
  /// Creates a vector of type ``Scalar`` into the ``ByteBuffer``
  ///
  /// ``createVector(_:)-4swl0`` writes a vector of type Scalars into
  /// ``ByteBuffer``. This is a convenient method instead of calling,
  /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``
  /// ```swift
  /// let vectorOffset = builder.
  ///   createVector([1, 2, 3, 4])
  /// ```
  ///
  /// The underlying implementation simply calls ``createVector(_:size:)-4lhrv``
  ///
  /// - Parameter elements: elements to be written into the buffer
  /// - returns: ``Offset`` of the vector
  mutating public func createVector<T: Scalar>(_ elements: [T]) -> Offset {
    createVector(elements, size: elements.count)
  }
  ///  Creates a vector of type Scalar in the buffer
  ///
  /// ``createVector(_:)-4swl0`` writes a vector of type Scalars into
  /// ``ByteBuffer``. This is a convenient method instead of calling,
  /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``
  /// ```swift
  /// let vectorOffset = builder.
  ///   createVector([1, 2, 3, 4], size: 4)
  /// ```
  ///
  /// - Parameter elements: Elements to be written into the buffer
  /// - Parameter size: Count of elements
  /// - returns: ``Offset`` of the vector
  mutating public func createVector<T: Scalar>(
    _ elements: [T],
    size: Int) -> Offset
  {
    let size = size
    startVector(size, elementSize: MemoryLayout<T>.size)
    _bb.push(elements: elements)
    return endVector(len: size)
  }
  /// Creates a vector of type ``Enum`` into the ``ByteBuffer``
  ///
  /// ``createVector(_:)-9h189`` writes a vector of type ``Enum`` into
  /// ``ByteBuffer``. This is a convenient method instead of calling,
  /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``
  /// ```swift
  /// let vectorOffset = builder.
  ///   createVector([.swift, .cpp])
  /// ```
  ///
  /// The underlying implementation simply calls ``createVector(_:size:)-7cx6z``
  ///
  /// - Parameter elements: elements to be written into the buffer
  /// - returns: ``Offset`` of the vector
  mutating public func createVector<T: Enum>(_ elements: [T]) -> Offset {
    createVector(elements, size: elements.count)
  }
  /// Creates a vector of type ``Enum`` into the ``ByteBuffer``
  ///
  /// ``createVector(_:)-9h189`` writes a vector of type ``Enum`` into
  /// ``ByteBuffer``. This is a convenient method instead of calling,
  /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``
  /// ```swift
  /// let vectorOffset = builder.
  ///   createVector([.swift, .cpp])
  /// ```
  ///
  /// - Parameter elements: Elements to be written into the buffer
  /// - Parameter size: Count of elements
  /// - returns: ``Offset`` of the vector
  mutating public func createVector<T: Enum>(
    _ elements: [T],
    size: Int) -> Offset
  {
    let size = size
    startVector(size, elementSize: T.byteSize)
    for e in elements.reversed() {
      _bb.push(value: e.value, len: T.byteSize)
    }
    return endVector(len: size)
  }
  /// Creates a vector of already written offsets
  ///
  /// ``createVector(ofOffsets:)`` creates a vector of ``Offset`` into
  /// ``ByteBuffer``. This is a convenient method instead of calling,
  /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``.
  ///
  /// The underlying implementation simply calls ``createVector(ofOffsets:len:)``
  ///
  /// ```swift
  /// let namesOffsets = builder.
  ///   createVector(ofOffsets: [name1, name2])
  /// ```
  /// - Parameter offsets: Array of offsets of type ``Offset``
  /// - returns: ``Offset`` of the vector
  mutating public func createVector(ofOffsets offsets: [Offset]) -> Offset {
    createVector(ofOffsets: offsets, len: offsets.count)
  }
  /// Creates a vector of already written offsets
  ///
  /// ``createVector(ofOffsets:)`` creates a vector of ``Offset`` into
  /// ``ByteBuffer``. This is a convenient method instead of calling,
  /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``
  ///
  /// ```swift
  /// let namesOffsets = builder.
  ///   createVector(ofOffsets: [name1, name2])
  /// ```
  ///
  /// - Parameter offsets: Array of offsets of type ``Offset``
  /// - Parameter size: Count of elements
  /// - returns: ``Offset`` of the vector
  mutating public func createVector(
    ofOffsets offsets: [Offset],
    len: Int) -> Offset
  {
    startVector(len, elementSize: MemoryLayout<Offset>.size)
    for o in offsets.reversed() {
      push(element: o)
    }
    return endVector(len: len)
  }
  /// Creates a vector of strings
  ///
  /// ``createVector(ofStrings:)`` creates a vector of `String` into
  /// ``ByteBuffer``. This is a convenient method instead of manually
  /// creating the string offsets, you simply pass it to this function
  /// and it would write the strings into the ``ByteBuffer``.
  /// After that it calls ``createVector(ofOffsets:)``
  ///
  /// ```swift
  /// let namesOffsets = builder.
  ///   createVector(ofStrings: ["Name", "surname"])
  /// ```
  ///
  /// - Parameter str: Array of string
  /// - returns: ``Offset`` of the vector
  mutating public func createVector(ofStrings str: [String]) -> Offset {
    var offsets: [Offset] = []
    for s in str {
      offsets.append(create(string: s))
    }
    return createVector(ofOffsets: offsets)
  }
  /// Creates a vector of type ``NativeStruct``.
  ///
  /// Any swift struct in the generated code, should confirm to
  /// ``NativeStruct``. Since the generated swift structs are padded
  /// to the `FlatBuffers` standards.
  ///
  /// ```swift
  /// let offsets = builder.
  ///   createVector(ofStructs: [NativeStr(num: 1), NativeStr(num: 2)])
  /// ```
  ///
  /// - Parameter structs: A vector of ``NativeStruct``
  /// - Returns: ``Offset`` of the vector
  mutating public func createVector<T: NativeStruct>(ofStructs structs: [T])
    -> Offset
  {
    startVector(
      structs.count * MemoryLayout<T>.size,
      elementSize: MemoryLayout<T>.alignment)
    for i in structs.reversed() {
      _ = create(struct: i)
    }
    return endVector(len: structs.count)
  }
  // MARK: - Inserting Structs
  /// Writes a ``NativeStruct`` into the ``ByteBuffer``
  ///
  /// Adds a native struct that's build and padded according
  /// to `FlatBuffers` standards. with a predefined position.
  ///
  /// ```swift
  /// let offset = builder.create(
  ///   struct: NativeStr(num: 1),
  ///   position: 10)
  /// ```
  ///
  /// - Parameters:
  ///   - s: ``NativeStruct`` to be inserted into the ``ByteBuffer``
  ///   - position: The  predefined position of the object
  /// - Returns: ``Offset`` of written struct
  mutating public func create<T: NativeStruct>(
    struct s: T, position: VOffset) -> Offset
  {
    let offset = create(struct: s)
    _vtableStorage.add(loc: FieldLoc(
      offset: _bb.size,
      position: VOffset(position)))
    return offset
  }
  /// Writes a ``NativeStruct`` into the ``ByteBuffer``
  ///
  /// Adds a native struct that's build and padded according
  /// to `FlatBuffers` standards, directly into the buffer without
  /// a predefined position.
  ///
  /// ```swift
  /// let offset = builder.create(
  ///   struct: NativeStr(num: 1))
  /// ```
  ///
  /// - Parameters:
  ///   - s: ``NativeStruct`` to be inserted into the ``ByteBuffer``
  /// - Returns: ``Offset`` of written struct
  mutating public func create<T: NativeStruct>(
    struct s: T) -> Offset
  {
    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
  /// Insets a string into the buffer of type `UTF8`
  ///
  /// Adds a swift string into ``ByteBuffer`` by encoding it
  /// using `UTF8`
  ///
  /// ```swift
  /// let nameOffset = builder
  ///   .create(string: "welcome")
  /// ```
  ///
  /// - Parameter str: String to be serialized
  /// - returns: ``Offset`` of inserted string
  mutating public func create(string str: String?) -> Offset {
    guard let str = str else { return Offset() }
    let len = str.utf8.count
    notNested()
    preAlign(len: len &+ 1, type: UOffset.self)
    _bb.fill(padding: 1)
    _bb.push(string: str, len: len)
    push(element: UOffset(len))
    return Offset(offset: _bb.size)
  }
  /// Insets a shared string into the buffer of type `UTF8`
  ///
  /// Adds a swift string into ``ByteBuffer`` by encoding it
  /// using `UTF8`. The function will check if the string,
  /// is already written to the ``ByteBuffer``
  ///
  /// ```swift
  /// let nameOffset = builder
  ///   .createShared(string: "welcome")
  ///
  ///
  /// let secondOffset = builder
  ///   .createShared(string: "welcome")
  ///
  /// assert(nameOffset.o == secondOffset.o)
  /// ```
  ///
  /// - Parameter str: String to be serialized
  /// - returns: ``Offset`` of inserted string
  mutating public func createShared(string str: String?) -> Offset {
    guard let str = str else { return Offset() }
    if let offset = stringOffsetMap[str] {
      return offset
    }
    let offset = create(string: str)
    stringOffsetMap[str] = offset
    return offset
  }
  // MARK: - Inseting offsets
  /// Writes the ``Offset`` of an already written table
  ///
  /// Writes the ``Offset`` of a table if not empty into the
  /// ``ByteBuffer``
  ///
  /// - Parameters:
  ///   - offset: ``Offset`` of another object to be written
  ///   - position: The predefined position of the object
  mutating public func push(element o: Offset) -> UOffset {
    push(element: refer(to: o.o))
  }
  // MARK: - Inserting Scalars to Buffer
  /// Writes a ``Scalar`` value into ``ByteBuffer``
  ///
  /// ``add(element:def:at:)`` takes in a default value, and current value
  /// and the position within the `VTable`. The default value would not
  /// be serialized if the value is the same as the current value or
  /// `serializeDefaults` is equal to false.
  ///
  /// If serializing defaults is important ``init(initialSize:serializeDefaults:)``,
  /// passing true for `serializeDefaults` would do the job.
  ///
  /// ```swift
  /// // Adds 10 to the buffer
  /// builder.add(element: Int(10), def: 1, position 12)
  /// ```
  ///
  /// *NOTE: Never call this manually*
  ///
  /// - Parameters:
  ///   - element: Element to insert
  ///   - def: Default value for that element
  ///   - position: The predefined position of the element
  mutating public func add<T: Scalar>(
    element: T,
    def: T,
    at position: VOffset)
  {
    if element == def && !serializeDefaults { return }
    track(offset: push(element: element), at: position)
  }
  /// Writes a optional ``Scalar`` value into ``ByteBuffer``
  ///
  /// Takes an optional value to be written into the ``ByteBuffer``
  ///
  /// *NOTE: Never call this manually*
  ///
  /// - Parameters:
  ///   - element: Optional element of type scalar
  ///   - position: The predefined position of the element
  mutating public func push<T: Scalar>(element: T) -> UOffset {
    let size = MemoryLayout<T>.size
    preAlign(
      len: size,
      alignment: size)
    _bb.push(value: element, len: size)
    return _bb.size
  }
}
extension FlatBufferBuilder: CustomDebugStringConvertible {
  public var debugDescription: String {
    """
    buffer debug:
    \(_bb)
    builder debug:
    { finished: \(finished), serializeDefaults: \(serializeDefaults), isNested: \(isNested) }
    """
  }
  /// VTableStorage is a class to contain the VTable buffer that would be serialized into buffer
  internal class VTableStorage {
    /// Memory check since deallocating each time we want to clear would be expensive
    /// and memory leaks would happen if we dont deallocate the first allocated memory.
    /// memory is promised to be available before adding `FieldLoc`
    private var memoryInUse = false
    /// Size of FieldLoc in memory
    let size = MemoryLayout<FieldLoc>.stride
    /// Memeory buffer
    var memory: UnsafeMutableRawBufferPointer!
    /// Capacity of the current buffer
    var capacity: Int = 0
    /// Maximuim offset written to the class
    var maxOffset: VOffset = 0
    /// number of fields written into the buffer
    var numOfFields: Int = 0
    /// Last written Index
    var writtenIndex: Int = 0
    /// Creates the memory to store the buffer in
    func start(count: Int) {
      assert(count >= 0, "number of fields should NOT be negative")
      let capacity = count &* size
      ensure(space: capacity)
    }
    /// Adds a FieldLoc into the buffer, which would track how many have been written,
    /// and max offset
    /// - Parameter loc: Location of encoded element
    func clear() {
      maxOffset = 0
      numOfFields = 0
      writtenIndex = 0
    }
    /// Ensure that the buffer has enough space instead of recreating the buffer each time.
    /// - Parameter space: space required for the new vtable
    func load(at index: Int) -> FieldLoc {
      memory.load(fromByteOffset: index, as: FieldLoc.self)
    }
  }
  internal struct FieldLoc {
    var offset: UOffset
    var position: VOffset
  }
}


FlatBufferObject

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// 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 {}
/// FlatbuffersInitializable is a protocol that allows any object to be
/// Initialized from a ByteBuffer
public protocol FlatbuffersInitializable {
  /// Any flatbuffers object that confirms to this protocol is going to be
  /// initializable through this initializer
  init(_ bb: ByteBuffer, o: Int32)
}
/// FlatbufferObject structures all the Flatbuffers objects
public protocol FlatBufferObject: FlatbuffersInitializable {
  var __buffer: ByteBuffer! { get }
}
/// ``ObjectAPIPacker`` is a protocol that allows object to pack and unpack from a
/// ``NativeObject`` to a flatbuffers Object and vice versa.
public protocol ObjectAPIPacker {
  /// associatedtype to the object that should be unpacked.
  associatedtype T
  /// ``pack(_:obj:)-3ptws`` tries to pacs the variables of a native Object into the `ByteBuffer` by using
  /// a FlatBufferBuilder
  /// - Parameters:
  ///   - builder: FlatBufferBuilder that will host incoming data
  ///   - obj: Object of associatedtype to the current implementer
  ///
  /// ``pack(_:obj:)-3ptws`` can be called by passing through an already initialized ``FlatBufferBuilder``
  /// or it can be called by using the public API that will create a new ``FlatBufferBuilder``
  static func pack(_ builder: inout FlatBufferBuilder, obj: inout T?) -> Offset
  /// ``pack(_:obj:)-20ipk`` packs the variables of a native Object into the `ByteBuffer` by using
  /// the FlatBufferBuilder
  /// - Parameters:
  ///   - builder: FlatBufferBuilder that will host incoming data
  ///   - obj: Object of associatedtype to the current implementer
  ///
  /// ``pack(_:obj:)-20ipk`` can be called by passing through an already initialized ``FlatBufferBuilder``
  /// or it can be called by using the public API that will create a new ``FlatBufferBuilder``
  static func pack(_ builder: inout FlatBufferBuilder, obj: inout T) -> Offset
  /// ``unpack()`` unpacks a ``FlatBuffers`` object into a Native swift object.
  mutating func unpack() -> T
}


ByteBuffer

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// `ByteBuffer` is the interface that stores the data for a `Flatbuffers` object
/// it allows users to write and read data directly from memory thus the use of its
/// functions should be used
    init(count: Int, alignment: Int) {
      memory = UnsafeMutableRawPointer.allocate(
        byteCount: count,
        alignment: alignment)
      capacity = count
      unowned = false
    }
    func copy(from ptr: UnsafeRawPointer, count: Int) {
      assert(
        !unowned,
        "copy should NOT be called on a buffer that is built by assumingMemoryBound")
      memory.copyMemory(from: ptr, byteCount: count)
    }
    func reallocate(_ size: Int, writerSize: Int, alignment: Int) {
      let currentWritingIndex = capacity &- writerSize
      while capacity <= writerSize &+ size {
        capacity = capacity << 1
      }
      /// solution take from Apple-NIO
      capacity = capacity.convertToPowerofTwo
      let newData = UnsafeMutableRawPointer.allocate(
        byteCount: capacity,
        alignment: alignment)
      memset(newData, 0, capacity &- writerSize)
      memcpy(
        newData.advanced(by: capacity &- writerSize),
        memory.advanced(by: currentWritingIndex),
        writerSize)
      memory.deallocate()
      memory = newData
    }
  }
  /// The size of the elements written to the buffer + their paddings
  private var _writerSize: Int = 0
  /// Aliginment of the current  memory being written to the buffer
  var alignment = 1
  /// Current Index which is being used to write to the buffer, it is written from the end to the start of the buffer
  var writerIndex: Int { _storage.capacity &- _writerSize }
  /// Reader is the position of the current Writer Index (capacity - size)
  public var reader: Int { writerIndex }
  /// Current size of the buffer
  public var size: UOffset { UOffset(_writerSize) }
  /// Public Pointer to the buffer object in memory. This should NOT be modified for any reason
  public var memory: UnsafeMutableRawPointer { _storage.memory }
  /// Current capacity for the buffer
  public var capacity: Int { _storage.capacity }
  /// Constructor that creates a Flatbuffer object from a UInt8
  /// - Parameter bytes: Array of UInt8
  public init(bytes: [UInt8]) {
    var b = bytes
    _storage = Storage(count: bytes.count, alignment: alignment)
    _writerSize = _storage.capacity
    b.withUnsafeMutableBytes { bufferPointer in
      self._storage.copy(from: bufferPointer.baseAddress!, count: bytes.count)
    }
  }
  #if !os(WASI)
  /// Constructor that creates a Flatbuffer from the Swift Data type object
  /// - Parameter data: Swift data Object
  public init(data: Data) {
    var b = data
    _storage = Storage(count: data.count, alignment: alignment)
    _writerSize = _storage.capacity
    b.withUnsafeMutableBytes { bufferPointer in
      self._storage.copy(from: bufferPointer.baseAddress!, count: data.count)
    }
  }
  #endif
  /// Constructor that creates a Flatbuffer instance with a size
  /// - Parameter size: Length of the buffer
  init(initialSize size: Int) {
    let size = size.convertToPowerofTwo
    _storage = Storage(count: size, alignment: alignment)
    _storage.initialize(for: size)
  }
  #if swift(>=5.0) && !os(WASI)
  /// Constructor that creates a Flatbuffer object from a ContiguousBytes
  /// - Parameters:
  ///   - contiguousBytes: Binary stripe to use as the buffer
  ///   - count: amount of readable bytes
  public init<Bytes: ContiguousBytes>(
    contiguousBytes: Bytes,
    count: Int)
  {
    _storage = Storage(count: count, alignment: alignment)
    _writerSize = _storage.capacity
    contiguousBytes.withUnsafeBytes { buf in
      _storage.copy(from: buf.baseAddress!, count: buf.count)
    }
  }
  #endif
  /// - Parameter assumingMemoryBound: The unsafe memory region
  /// - Parameter capacity: The size of the given memory region
  public init(
    assumingMemoryBound memory: UnsafeMutableRawPointer,
    capacity: Int)
  {
    _storage = Storage(memory: memory, capacity: capacity, unowned: true)
    _writerSize = capacity
  }
  /// Creates a copy of the buffer that's being built by calling sizedBuffer
  /// - Parameters:
  ///   - memory: Current memory of the buffer
  ///   - count: count of bytes
  init(memory: UnsafeMutableRawPointer, count: Int) {
    _storage = Storage(count: count, alignment: alignment)
    _storage.copy(from: memory, count: count)
    _writerSize = _storage.capacity
  }
  /// - Parameters:
  ///   - memory: Current memory of the buffer
  ///   - count: count of bytes
  ///   - removeBytes: Removes a number of bytes from the current size
  init(
    memory: UnsafeMutableRawPointer,
    count: Int,
    removing removeBytes: Int)
  {
    _storage = Storage(count: count, alignment: alignment)
    _storage.copy(from: memory, count: count)
    _writerSize = removeBytes
  }
  /// Fills the buffer with padding by adding to the writersize
  /// - Parameter padding: Amount of padding between two to be serialized objects
  mutating func push<T: Scalar>(elements: [T]) {
    let size = elements.count &* MemoryLayout<T>.size
    ensureSpace(size: size)
    elements.reversed().forEach { s in
      push(value: s, len: MemoryLayout.size(ofValue: s))
    }
  }
  /// Adds an object of type NativeStruct into the buffer
  /// - Parameters:
  ///   - value: Object  that will be written to the buffer
  ///   - size: size to subtract from the WriterIndex
  mutating func push<T: Scalar>(value: T, len: Int) {
    ensureSpace(size: len)
    var v = value
    memcpy(_storage.memory.advanced(by: writerIndex &- len), &v, len)
    _writerSize = _writerSize &+ len
  }
  /// Adds a string to the buffer using swift.utf8 object
  /// - Parameter str: String that will be added to the buffer
  /// - Parameter len: length of the string
  mutating func push(string str: String, len: Int) {
    ensureSpace(size: len)
    if str.utf8
      .withContiguousStorageIfAvailable({ self.push(bytes: $0, len: len) }) !=
      nil
    {
    } else {
      let utf8View = str.utf8
      for c in utf8View.reversed() {
        push(value: c, len: 1)
      }
    }
  }
  /// Writes a string to Bytebuffer using UTF8View
  /// - Parameters:
  ///   - bytes: Pointer to the view
  ///   - len: Size of string
  mutating func push(
    bytes: UnsafeBufferPointer<String.UTF8View.Element>,
    len: Int) -> Bool
  {
    memcpy(
      _storage.memory.advanced(by: writerIndex &- len),
      UnsafeRawPointer(bytes.baseAddress!),
      len)
    _writerSize = _writerSize &+ len
    return true
  }
  /// Write stores an object into the buffer directly or indirectly.
  ///
  /// Direct: ignores the capacity of buffer which would mean we are referring to the direct point in memory
  /// indirect: takes into respect the current capacity of the buffer (capacity - index), writing to the buffer from the end
  /// - Parameters:
  ///   - value: Value that needs to be written to the buffer
  ///   - index: index to write to
  ///   - direct: Should take into consideration the capacity of the buffer
  mutating func ensureSpace(size: Int) -> Int {
    if size &+ _writerSize > _storage.capacity {
      _storage.reallocate(size, writerSize: _writerSize, alignment: alignment)
    }
    assert(size < FlatBufferMaxSize, "Buffer can't grow beyond 2 Gigabytes")
    return size
  }
  /// pops the written VTable if it's already written into the buffer
  /// - Parameter size: size of the `VTable`
  mutating public func clearSize() {
    _writerSize = 0
  }
  /// Clears the current instance of the buffer, replacing it with new memory
  public func read<T>(def: T.Type, position: Int) -> T {
    _storage.memory.advanced(by: position).load(as: T.self)
  }
  /// Reads a slice from the memory assuming a type of T
  /// - Parameters:
  ///   - index: index of the object to be read from the buffer
  ///   - count: count of bytes in memory
  public func readSlice<T>(
    index: Int,
    count: Int) -> [T]
  {
    assert(
      index + count <= _storage.capacity,
      "Reading out of bounds is illegal")
    let start = _storage.memory.advanced(by: index)
      .assumingMemoryBound(to: T.self)
    let array = UnsafeBufferPointer(start: start, count: count)
    return Array(array)
  }
  #if !os(WASI)
  /// Reads a string from the buffer and encodes it to a swift string
  /// - Parameters:
  ///   - index: index of the string in the buffer
  ///   - count: length of the string
  ///   - type: Encoding of the string
  public func readString(
    at index: Int,
    count: Int,
    type: String.Encoding = .utf8) -> String?
  {
    assert(
      index + count <= _storage.capacity,
      "Reading out of bounds is illegal")
    let start = _storage.memory.advanced(by: index)
      .assumingMemoryBound(to: UInt8.self)
    let bufprt = UnsafeBufferPointer(start: start, count: count)
    return String(bytes: Array(bufprt), encoding: type)
  }
  #else
  /// Reads a string from the buffer and encodes it to a swift string
  /// - Parameters:
  ///   - index: index of the string in the buffer
  ///   - count: length of the string
  ///   - type: Encoding of the string
  public func readString(
    at index: Int,
    count: Int) -> String?
  {
    assert(
      index + count <= _storage.capacity,
      "Reading out of bounds is illegal")
    let start = _storage.memory.advanced(by: index)
      .assumingMemoryBound(to: UInt8.self)
    let bufprt = UnsafeBufferPointer(start: start, count: count)
    return String(cString: bufprt.baseAddress!)
  }
  #endif
  /// Creates a new Flatbuffer object that's duplicated from the current one
  /// - Parameter removeBytes: the amount of bytes to remove from the current Size
  public func duplicate(removing removeBytes: Int = 0) -> ByteBuffer {
    assert(removeBytes > 0, "Can NOT remove negative bytes")
    assert(
      removeBytes < _storage.capacity,
      "Can NOT remove more bytes than the ones allocated")
    return ByteBuffer(
      memory: _storage.memory,
      count: _storage.capacity,
      removing: _writerSize &- removeBytes)
  }
  /// Returns the written bytes into the ``ByteBuffer``
    public var underlyingBytes: [UInt8] {
      let cp = capacity &- writerIndex
      let start = memory.advanced(by: writerIndex)
                                .bindMemory(to: UInt8.self, capacity: cp)
      let ptr = UnsafeBufferPointer<UInt8>(start: start, count: cp)
      return Array(ptr)
  }
  /// SkipPrefix Skips the first 4 bytes in case one of the following
  /// functions are called `getPrefixedSizeCheckedRoot` & `getPrefixedSizeRoot`
  /// which allows us to skip the first 4 bytes instead of recreating the buffer
  mutating func skipPrefix() -> Int32 {
    _writerSize = _writerSize &- MemoryLayout<Int32>.size
    return read(def: Int32.self, position: 0)
  }
}
extension ByteBuffer: CustomDebugStringConvertible {
  public var debugDescription: String {
    """
    buffer located at: \(_storage.memory), with capacity of \(_storage.capacity)
    { writerSize: \(_writerSize), readerSize: \(reader), writerIndex: \(writerIndex) }
    """
  }
}


Struct

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// Struct is a representation of a mutable `Flatbuffers` struct
/// since native structs are value types and cant be mutated
public struct Struct {
  /// Hosting Bytebuffer
  public private(set) var bb: ByteBuffer
  /// Current position of the struct
  public private(set) var postion: Int32
  /// Initializer for a mutable flatbuffers struct
  /// - Parameters:
  ///   - bb: Current hosting Bytebuffer
  ///   - position: Current position for the struct in the ByteBuffer
  public init(bb: ByteBuffer, position: Int32 = 0) {
    self.bb = bb
    postion = position
  }
  /// Reads data from the buffer directly at offset O
  /// - Parameters:
  ///   - type: Type of data to be read
  ///   - o: Current offset of the data
  /// - Returns: Data of Type T that conforms to type Scalar
  public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
    let r = bb.read(def: T.self, position: Int(o + postion))
    return r
  }
}


Message

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// FlatBufferGRPCMessage protocol that should allow us to invoke
/// initializers directly from the GRPC generated code
public protocol FlatBufferGRPCMessage {
  /// Raw pointer which would be pointing to the beginning of the readable bytes
  var rawPointer: UnsafeMutableRawPointer { get }
  /// Size of readable bytes in the buffer
  var size: Int { get }
  init(byteBuffer: ByteBuffer)
}
/// Message is a wrapper around Buffers to to able to send Flatbuffers `Buffers` through the
/// GRPC library
public struct Message<T: FlatBufferObject>: FlatBufferGRPCMessage {
  internal var buffer: ByteBuffer
  /// Returns the an object of type T that would be  read from the buffer
  public var object: T {
    T.init(
      buffer,
      o: Int32(buffer.read(def: UOffset.self, position: buffer.reader)) +
        Int32(buffer.reader))
  }
  public var rawPointer: UnsafeMutableRawPointer {
    buffer.memory.advanced(by: buffer.reader) }
  public var size: Int { Int(buffer.size) }
  /// Initializes the message with the type Flatbuffer.Bytebuffer that is transmitted over
  /// GRPC
  /// - Parameter byteBuffer: Flatbuffer ByteBuffer object
  public init(byteBuffer: ByteBuffer) {
    buffer = byteBuffer
  }
  /// from the builder
  /// - Parameter builder: FlatbufferBuilder that has the bytes created in
  /// - Note: Use  `builder.finish(offset)` before passing the builder without prefixing anything to it
  public init(builder: inout FlatBufferBuilder) {
    buffer = builder.sizedBuffer
    builder.clear()
  }
}


Verifier

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// Verifier that check if the buffer passed into it is a valid,
/// safe, aligned Flatbuffers object since swift read from `unsafeMemory`
public struct Verifier {
  /// Flag to check for alignment if true
  fileprivate let _checkAlignment: Bool
  /// Capacity of the current buffer
  fileprivate var _capacity: Int
  /// Current ApparentSize
  fileprivate var _apparentSize: UOffset = 0
  /// Amount of tables present within a buffer
  fileprivate var _tableCount = 0
  /// Capacity of the buffer
  internal var capacity: Int { _capacity }
  /// Current reached depth within the buffer
  internal var _depth = 0
  /// Current verifiable ByteBuffer
  internal var _buffer: ByteBuffer
  /// Options for verification
  internal let _options: VerifierOptions
  /// Initializer for the verifier
  /// - Parameters:
  ///   - buffer: Bytebuffer that is required to be verified
  ///   - options: `VerifierOptions` that set the rule for some of the verification done
  ///   - checkAlignment: If alignment check is required to be preformed
  /// - Throws: `exceedsMaxSizeAllowed` if capacity of the buffer is more than 2GiB
  public init(
    buffer: inout ByteBuffer,
    options: VerifierOptions = .init(),
    checkAlignment: Bool = true) throws
  {
    guard buffer.capacity < FlatBufferMaxSize else {
      throw FlatbuffersErrors.exceedsMaxSizeAllowed
    }
    _buffer = buffer
    _capacity = buffer.capacity
    _checkAlignment = checkAlignment
    _options = options
  }
  /// Resets the verifier to initial state
  public mutating func reset() {
    _depth = 0
    _tableCount = 0
  }
  /// Checks if the value of type `T` is aligned properly in the buffer
  /// - Parameters:
  ///   - position: Current position
  ///   - type: Type of value to check
  /// - Throws: `missAlignedPointer` if the pointer is not aligned properly
  public mutating func isAligned<T>(position: Int, type: T.Type) throws {
    /// If check alignment is false this mutating function doesnt continue
    if !_checkAlignment { return }
    /// advance pointer to position X
    let ptr = _buffer._storage.memory.advanced(by: position)
    /// Check if the pointer is aligned
    if Int(bitPattern: ptr) & (MemoryLayout<T>.alignment &- 1) == 0 {
      return
    }
    throw FlatbuffersErrors.missAlignedPointer(
      position: position,
      type: String(describing: T.self))
  }
  /// Checks if the value of Size "X" is within the range of the buffer
  /// - Parameters:
  ///   - position: Current postion to be read
  ///   - size: `Byte` Size of readable object within the buffer
  /// - Throws: `outOfBounds` if the value is out of the bounds of the buffer
  /// and `apparentSizeTooLarge` if the apparent size is bigger than the one specified
  /// in `VerifierOptions`
  public mutating func rangeInBuffer(position: Int, size: Int) throws {
    let end = UInt(clamping: (position &+ size).magnitude)
    if end > _buffer.capacity {
      throw FlatbuffersErrors.outOfBounds(position: end, end: capacity)
    }
    _apparentSize = _apparentSize &+ UInt32(size)
    if _apparentSize > _options._maxApparentSize {
      throw FlatbuffersErrors.apparentSizeTooLarge
    }
  }
  /// Validates if a value of type `T` is aligned and within the bounds of
  /// the buffer
  /// - Parameters:
  ///   - position: Current readable position
  ///   - type: Type of value to check
  /// - Throws: FlatbuffersErrors
  public mutating func inBuffer<T>(position: Int, of type: T.Type) throws {
    try isAligned(position: position, type: type)
    try rangeInBuffer(position: position, size: MemoryLayout<T>.size)
  }
  /// Visits a table at the current position and validates if the table meets
  /// the rules specified in the `VerifierOptions`
  /// - Parameter position: Current position to be read
  /// - Throws: FlatbuffersErrors
  /// - Returns: A `TableVerifier` at the current readable table
  public mutating func visitTable(at position: Int) throws -> TableVerifier {
    let vtablePosition = try derefOffset(position: position)
    let vtableLength: VOffset = try getValue(at: vtablePosition)
    let length = Int(vtableLength)
    try isAligned(
      position: Int(clamping: (vtablePosition + length).magnitude),
      type: VOffset.self)
    try rangeInBuffer(position: vtablePosition, size: length)
    _tableCount += 1
    if _tableCount > _options._maxTableCount {
      throw FlatbuffersErrors.maximumTables
    }
    _depth += 1
    if _depth > _options._maxDepth {
      throw FlatbuffersErrors.maximumDepth
    }
    return TableVerifier(
      position: position,
      vtable: vtablePosition,
      vtableLength: length,
      verifier: &self)
  }
  /// Validates if a value of type `T` is within the buffer and returns it
  /// - Parameter position: Current position to be read
  /// - Throws: `inBuffer` errors
  /// - Returns: a value of type `T` usually a `VTable` or a table offset
  internal mutating func getValue<T>(at position: Int) throws -> T {
    try inBuffer(position: position, of: T.self)
    return _buffer.read(def: T.self, position: position)
  }
  /// derefrences an offset within a vtable to get the position of the field
  /// in the bytebuffer
  /// - Parameter position: Current readable position
  /// - Throws: `inBuffer` errors & `signedOffsetOutOfBounds`
  /// - Returns: Current readable position for a field
  internal mutating func derefOffset(position: Int) throws -> Int {
    try inBuffer(position: position, of: Int32.self)
    let offset = _buffer.read(def: Int32.self, position: position)
    // switching to int32 since swift's default Int is int64
    // this should be safe since we already checked if its within
    // the buffer
    let _int32Position = UInt32(position)
    let reportedOverflow: (partialValue: UInt32, overflow: Bool)
    if offset > 0 {
      reportedOverflow = _int32Position
        .subtractingReportingOverflow(offset.magnitude)
    } else {
      reportedOverflow = _int32Position
        .addingReportingOverflow(offset.magnitude)
    }
    /// since `subtractingReportingOverflow` & `addingReportingOverflow` returns true,
    /// if there is overflow we return failure
    if reportedOverflow.overflow || reportedOverflow.partialValue > _buffer
      .capacity
    {
      throw FlatbuffersErrors.signedOffsetOutOfBounds(
        offset: Int(offset),
        position: position)
    }
    return Int(reportedOverflow.partialValue)
  }
  /// finishes the current iteration of verification on an object
  internal mutating func finish() {
    _depth -= 1
  }
  mutating func verify(id: String) throws {
    let size = MemoryLayout<Int32>.size
    let str = _buffer.readString(at: size, count: size)
    if id == str {
      return
    }
    throw FlatbuffersErrors.bufferIdDidntMatchPassedId
  }
}


VeriferOptions

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// `VerifierOptions` is a set of options to verify a flatbuffer
public struct VerifierOptions {
  /// Maximum `Apparent` size if the buffer can be expanded into a DAG tree
  internal var _maxApparentSize: UOffset
  /// Maximum table count allowed in a buffer
  internal var _maxTableCount: UOffset
  /// Maximum depth allowed in a buffer
  internal var _maxDepth: UOffset
  /// Ignoring missing null terminals in strings
  internal var _ignoreMissingNullTerminators: Bool
  /// initializes the set of options for the verifier
  /// - Parameters:
  ///   - maxDepth: Maximum depth allowed in a buffer
  ///   - maxTableCount: Maximum table count allowed in a buffer
  ///   - maxApparentSize: Maximum `Apparent` size if the buffer can be expanded into a DAG tree
  ///   - ignoreMissingNullTerminators: Ignoring missing null terminals in strings *Currently not supported in swift*
  public init(
    maxDepth: UOffset = 64,
    maxTableCount: UOffset = 1000000,
    maxApparentSize: UOffset = 1 << 31,
    ignoreMissingNullTerminators: Bool = false)
  {
    _maxDepth = maxDepth
    _maxTableCount = maxTableCount
    _maxApparentSize = maxApparentSize
    _ignoreMissingNullTerminators = ignoreMissingNullTerminators
  }
}


NativeObject

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// NativeObject is a protocol that all of the `Object-API` generated code should be
/// conforming to since it allows developers the ease of use to pack and unpack their
/// Flatbuffers objects
public protocol NativeObject {}
extension NativeObject {
  /// 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
  /// - Returns: returns the encoded sized ByteBuffer
  public func serialize<T: ObjectAPIPacker>(type: T.Type) -> ByteBuffer
    where T.T == Self
  {
    var builder = FlatBufferBuilder(initialSize: 1024)
    return serialize(builder: &builder, type: type.self)
  }
  /// Serialize is a helper function that serailizes the data from the Object API to a bytebuffer directly.
  ///
  /// - Parameters:
  ///   - builder: A FlatBufferBuilder
  ///   - type: Type of the Flatbuffer object
  /// - Returns: returns the encoded sized ByteBuffer
  /// - Note: The `serialize(builder:type)` can be considered as a function that allows you to create smaller builder instead of the default `1024`.
  ///  It can be considered less expensive in terms of memory allocation
  public func serialize<T: ObjectAPIPacker>(
    builder: inout FlatBufferBuilder,
    type: T.Type) -> ByteBuffer where T.T == Self
  {
    var s = self
    let root = type.pack(&builder, obj: &s)
    builder.finish(offset: root)
    return builder.sizedBuffer
  }
}


Enum

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// Enum is a protocol that all flatbuffers enums should conform to
/// Since it allows us to get the actual `ByteSize` and `Value` from
/// a swift enum.
public protocol Enum {
  /// associatedtype that the type of the enum should conform to
  associatedtype T: Scalar & Verifiable
  /// Size of the current associatedtype in the enum
  static var byteSize: Int { get }
  /// The current value the enum hosts
  var value: T { get }
}
extension Enum where Self: Verifiable {
  /// Verifies that the current value is which the bounds of the buffer, and if
  /// the current `Value` is aligned properly
  /// - Parameters:
  ///   - verifier: Verifier that hosts the buffer
  ///   - position: Current position within the buffer
  ///   - type: The type of the object to be verified
  /// - Throws: Errors coming from `inBuffer` function
  public static func verify<T>(
    _ verifier: inout Verifier,
    at position: Int,
    of type: T.Type) throws where T: Verifiable
  {
    try verifier.inBuffer(position: position, of: type.self)
  }
}
/// UnionEnum is a Protocol that allows us to create Union type of enums
/// and their value initializers. Since an `init` was required by
/// the verifier
public protocol UnionEnum: Enum {
  init?(value: T) throws
}


FlatBuffersUtils

/*
 */
#if !os(WASI)
import Foundation
#else
import SwiftOverlayShims
#endif
/// FlatBuffersUtils hosts some utility functions that might be useful
public enum FlatBuffersUtils {
  /// Gets the size of the prefix
  /// - Parameter bb: Flatbuffer object
  public static func getSizePrefix(bb: ByteBuffer) -> Int32 {
    bb.read(def: Int32.self, position: bb.reader)
  }
  /// Removes the prefix by duplicating the Flatbuffer this call is expensive since its
  /// creates a new buffer use `readPrefixedSizeCheckedRoot` instead
  /// unless a completely new buffer is required
  /// - Parameter bb: Flatbuffer object
  ///
  ///
  public static func removeSizePrefix(bb: ByteBuffer) -> ByteBuffer {
    bb.duplicate(removing: MemoryLayout<Int32>.size)
  }
}