// automatically generated by the FlatBuffers compiler, do not modify
// swiftlint:disable all
// swiftformat:disable all

#if canImport(Common)
import Common
#endif

import FlatBuffers

public struct flatbuffers_goldens_Galaxy: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable {

  static func validateVersion() { FlatBuffersVersion_25_12_19() }
  public var __buffer: ByteBuffer! { return _accessor.bb }
  private var _accessor: Table

  private init(_ t: Table) { _accessor = t }
  public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }

  private enum VTOFFSET: VOffset {
    case numStars = 4
    var v: Int32 { Int32(self.rawValue) }
    var p: VOffset { self.rawValue }
  }

  public var numStars: Int64 { let o = _accessor.offset(VTOFFSET.numStars.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int64.self, at: o) }
  public static func startGalaxy(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) }
  public static func add(numStars: Int64, _ fbb: inout FlatBufferBuilder) { fbb.add(element: numStars, def: 0, at: VTOFFSET.numStars.p) }
  public static func endGalaxy(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
  public static func createGalaxy(
    _ fbb: inout FlatBufferBuilder,
    numStars: Int64 = 0
  ) -> Offset {
    let __start = flatbuffers_goldens_Galaxy.startGalaxy(&fbb)
    flatbuffers_goldens_Galaxy.add(numStars: numStars, &fbb)
    return flatbuffers_goldens_Galaxy.endGalaxy(&fbb, start: __start)
  }

  public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
    var _v = try verifier.visitTable(at: position)
    try _v.visit(field: VTOFFSET.numStars.p, fieldName: "numStars", required: false, type: Int64.self)
    _v.finish()
  }
}

public struct flatbuffers_goldens_Universe: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable {

  static func validateVersion() { FlatBuffersVersion_25_12_19() }
  public var __buffer: ByteBuffer! { return _accessor.bb }
  private var _accessor: Table

  private init(_ t: Table) { _accessor = t }
  public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }

  private enum VTOFFSET: VOffset {
    case age = 4
    case galaxies = 6
    var v: Int32 { Int32(self.rawValue) }
    var p: VOffset { self.rawValue }
  }

  public var age: Double { let o = _accessor.offset(VTOFFSET.age.v); return o == 0 ? 0.0 : _accessor.readBuffer(of: Double.self, at: o) }
  public var galaxies: FlatbufferVector<flatbuffers_goldens_Galaxy> { return _accessor.vector(at: VTOFFSET.galaxies.v, byteSize: 4) }
  public static func startUniverse(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 2) }
  public static func add(age: Double, _ fbb: inout FlatBufferBuilder) { fbb.add(element: age, def: 0.0, at: VTOFFSET.age.p) }
  public static func addVectorOf(galaxies: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: galaxies, at: VTOFFSET.galaxies.p) }
  public static func endUniverse(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
  public static func createUniverse(
    _ fbb: inout FlatBufferBuilder,
    age: Double = 0.0,
    galaxiesVectorOffset galaxies: Offset = Offset()
  ) -> Offset {
    let __start = flatbuffers_goldens_Universe.startUniverse(&fbb)
    flatbuffers_goldens_Universe.add(age: age, &fbb)
    flatbuffers_goldens_Universe.addVectorOf(galaxies: galaxies, &fbb)
    return flatbuffers_goldens_Universe.endUniverse(&fbb, start: __start)
  }

  public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
    var _v = try verifier.visitTable(at: position)
    try _v.visit(field: VTOFFSET.age.p, fieldName: "age", required: false, type: Double.self)
    try _v.visit(field: VTOFFSET.galaxies.p, fieldName: "galaxies", required: false, type: ForwardOffset<Vector<ForwardOffset<flatbuffers_goldens_Galaxy>, flatbuffers_goldens_Galaxy>>.self)
    _v.finish()
  }
}

