// automatically generated by the FlatBuffers compiler, do not modify

import FlatBuffers

public enum Character: UInt8, Enum { 
	public typealias T = UInt8
	public static var byteSize: Int { return MemoryLayout<UInt8>.size }
	public var value: UInt8 { return self.rawValue }
	case none = 0
	case mulan = 1
	case rapunzel = 2
	case belle = 3
	case bookfan = 4
	case other = 5
	case unused = 6


	public static var max: Character { return .unused }
	public static var min: Character { return .none }
}

public struct Rapunzel: Readable {

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

	private var _accessor: Struct
	public static var size = 4
	public static var alignment = 4	
	public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) }

	public var hairLength: Int32 { return _accessor.readBuffer(of: Int32.self, at: 0) }
	public func mutate(hairLength: Int32) -> Bool { return _accessor.mutate(hairLength, index: 0) }
}

public struct BookReader: Readable {

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

	private var _accessor: Struct
	public static var size = 4
	public static var alignment = 4	
	public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) }

	public var booksRead: Int32 { return _accessor.readBuffer(of: Int32.self, at: 0) }
	public func mutate(booksRead: Int32) -> Bool { return _accessor.mutate(booksRead, index: 0) }
}

public func createRapunzel(hairLength: Int32) -> UnsafeMutableRawPointer {
	let memory = UnsafeMutableRawPointer.allocate(byteCount: Rapunzel.size, alignment: Rapunzel.alignment)
	memory.initializeMemory(as: UInt8.self, repeating: 0, count: Rapunzel.size)
	memory.storeBytes(of: hairLength, toByteOffset: 0, as: Int32.self)
	return memory
}

public func createBookReader(booksRead: Int32) -> UnsafeMutableRawPointer {
	let memory = UnsafeMutableRawPointer.allocate(byteCount: BookReader.size, alignment: BookReader.alignment)
	memory.initializeMemory(as: UInt8.self, repeating: 0, count: BookReader.size)
	memory.storeBytes(of: booksRead, toByteOffset: 0, as: Int32.self)
	return memory
}

public struct Attacker: FlatBufferObject {

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

	private var _accessor: Table
	public static func finish(_ fbb: FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MOVI", addPrefix: prefix) }
	public static func getRootAsAttacker(bb: ByteBuffer) -> Attacker { return Attacker(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }

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

	public var swordAttackDamage: Int32 { let o = _accessor.offset(4); return o == 0 ? 0 : _accessor.readBuffer(of: Int32.self, at: o) }
	public func mutate(swordAttackDamage: Int32) -> Bool {let o = _accessor.offset(4);  return _accessor.mutate(swordAttackDamage, index: o) }
	public static func startAttacker(_ fbb: FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) }
	public static func add(swordAttackDamage: Int32, _ fbb: FlatBufferBuilder) { fbb.add(element: swordAttackDamage, def: 0, at: 0) }
	public static func endAttacker(_ fbb: FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end }
	public static func createAttacker(_ fbb: FlatBufferBuilder,
		swordAttackDamage: Int32 = 0) -> Offset<UOffset> {
		let __start = Attacker.startAttacker(fbb)
		Attacker.add(swordAttackDamage: swordAttackDamage, fbb)
		return Attacker.endAttacker(fbb, start: __start)
	}
}

public struct Movie: FlatBufferObject {

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

	private var _accessor: Table
	public static func finish(_ fbb: FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MOVI", addPrefix: prefix) }
	public static func getRootAsMovie(bb: ByteBuffer) -> Movie { return Movie(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }

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

	public var mainCharacterType: Character { let o = _accessor.offset(4); return o == 0 ? .none : Character(rawValue: _accessor.readBuffer(of: UInt8.self, at: o)) ?? .none }
	public func mainCharacter<T: FlatBufferObject>(type: T.Type) -> T? { let o = _accessor.offset(6); return o == 0 ? nil : _accessor.union(o) }
	public var charactersTypeCount: Int32 { let o = _accessor.offset(8); return o == 0 ? 0 : _accessor.vector(count: o) }
	public func charactersType(at index: Int32) -> Character? { let o = _accessor.offset(8); return o == 0 ? Character.none : Character(rawValue: _accessor.directRead(of: UInt8.self, offset: _accessor.vector(at: o) + index * 1)) }
	public var charactersCount: Int32 { let o = _accessor.offset(10); return o == 0 ? 0 : _accessor.vector(count: o) }
	public func characters<T: FlatBufferObject>(at index: Int32, type: T.Type) -> T? { let o = _accessor.offset(10); return o == 0 ? nil : _accessor.directUnion(_accessor.vector(at: o) + index * 4) }
	public static func startMovie(_ fbb: FlatBufferBuilder) -> UOffset { fbb.startTable(with: 4) }
	public static func add(mainCharacterType: Character, _ fbb: FlatBufferBuilder) { fbb.add(element: mainCharacterType.rawValue, def: 0, at: 0) }
	public static func add(mainCharacter: Offset<UOffset>, _ fbb: FlatBufferBuilder) { fbb.add(offset: mainCharacter, at: 1)  }
	public static func addVectorOf(charactersType: Offset<UOffset>, _ fbb: FlatBufferBuilder) { fbb.add(offset: charactersType, at: 2)  }
	public static func addVectorOf(characters: Offset<UOffset>, _ fbb: FlatBufferBuilder) { fbb.add(offset: characters, at: 3)  }
	public static func endMovie(_ fbb: FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end }
	public static func createMovie(_ fbb: FlatBufferBuilder,
		mainCharacterType: Character = .none,
		offsetOfMainCharacter mainCharacter: Offset<UOffset> = Offset(),
		vectorOfCharactersType charactersType: Offset<UOffset> = Offset(),
		vectorOfCharacters characters: Offset<UOffset> = Offset()) -> Offset<UOffset> {
		let __start = Movie.startMovie(fbb)
		Movie.add(mainCharacterType: mainCharacterType, fbb)
		Movie.add(mainCharacter: mainCharacter, fbb)
		Movie.addVectorOf(charactersType: charactersType, fbb)
		Movie.addVectorOf(characters: characters, fbb)
		return Movie.endMovie(fbb, start: __start)
	}
}

