blob: 080227206619e578bddeb44f7d6e8286915dbf0e [file] [log] [blame]
Austin Schuh58b9b472020-11-25 19:12:44 -08001/*
2 * Copyright 2020 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Austin Schuh272c6132020-11-14 16:37:52 -080017import XCTest
18@testable import FlatBuffers
19
20final class FlatBuffersUnionTests: XCTestCase {
Austin Schuh58b9b472020-11-25 19:12:44 -080021
22 func testCreateMonstor() {
23
24 var b = FlatBufferBuilder(initialSize: 20)
25 let dmg: Int16 = 5
26 let str = "Axe"
27 let axe = b.create(string: str)
28 let weapon = Weapon.createWeapon(builder: &b, offset: axe, dmg: dmg)
29 let weapons = b.createVector(ofOffsets: [weapon])
30 let root = LocalMonster.createMonster(
31 builder: &b,
32 offset: weapons,
33 equipment: .Weapon,
34 equippedOffset: weapon.o)
35 b.finish(offset: root)
36 let buffer = b.sizedByteArray
37 XCTAssertEqual(buffer, [16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 8, 0, 7, 0, 12, 0, 10, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 20, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 8, 0, 12, 0, 8, 0, 6, 0, 8, 0, 0, 0, 0, 0, 5, 0, 4, 0, 0, 0, 3, 0, 0, 0, 65, 120, 101, 0])
38 let monster = LocalMonster.getRootAsMonster(bb: ByteBuffer(bytes: buffer))
39 XCTAssertEqual(monster.weapon(at: 0)?.dmg, dmg)
40 XCTAssertEqual(monster.weapon(at: 0)?.name, str)
41 XCTAssertEqual(monster.weapon(at: 0)?.nameVector, [65, 120, 101])
42 let p: Weapon? = monster.equiped()
43 XCTAssertEqual(p?.dmg, dmg)
44 XCTAssertEqual(p?.name, str)
45 XCTAssertEqual(p?.nameVector, [65, 120, 101])
46 }
47
48 func testEndTableFinish() {
49 var builder = FlatBufferBuilder(initialSize: 20)
50 let sword = builder.create(string: "Sword")
51 let axe = builder.create(string: "Axe")
52 let weaponOne = Weapon.createWeapon(builder: &builder, offset: sword, dmg: 3)
53 let weaponTwo = Weapon.createWeapon(builder: &builder, offset: axe, dmg: 5)
54 let name = builder.create(string: "Orc")
55 let inventory: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
56 let inv = builder.createVector(inventory, size: 10)
57 let weapons = builder.createVector(ofOffsets: [weaponOne, weaponTwo])
58 builder.startVectorOfStructs(count: 2, size: Vec.size, alignment: Vec.alignment)
59 createVecWrite(builder: &builder, x: 1.0, y: 2.0, z: 3.0)
60 createVecWrite(builder: &builder, x: 4.0, y: 5.0, z: 6.0)
61 let path = builder.endVectorOfStructs(count: 2)
62 let orc = FinalMonster.createMonster(
63 builder: &builder,
64 position: createVecWrite(builder: &builder, x: 1.0, y: 2.0, z: 3.0),
65 hp: 300,
66 name: name,
67 inventory: inv,
68 color: .red,
69 weapons: weapons,
70 equipment: .Weapon,
71 equippedOffset: weaponTwo,
72 path: path)
73 builder.finish(offset: orc)
74 XCTAssertEqual(builder.sizedByteArray, [32, 0, 0, 0, 0, 0, 26, 0, 36, 0, 36, 0, 0, 0, 34, 0, 28, 0, 0, 0, 24, 0, 23, 0, 16, 0, 15, 0, 8, 0, 4, 0, 26, 0, 0, 0, 44, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 76, 0, 0, 0, 0, 0, 44, 1, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 0, 0, 0, 0, 128, 64, 0, 0, 160, 64, 0, 0, 192, 64, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 0, 0, 52, 0, 0, 0, 28, 0, 0, 0, 10, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 3, 0, 0, 0, 79, 114, 99, 0, 244, 255, 255, 255, 0, 0, 5, 0, 24, 0, 0, 0, 8, 0, 12, 0, 8, 0, 6, 0, 8, 0, 0, 0, 0, 0, 3, 0, 12, 0, 0, 0, 3, 0, 0, 0, 65, 120, 101, 0, 5, 0, 0, 0, 83, 119, 111, 114, 100, 0, 0, 0])
75 }
76
77 func testEnumVector() {
78 let vectorOfEnums: [ColorsNameSpace.RGB] = [.blue, .green]
79
80 var builder = FlatBufferBuilder(initialSize: 1)
81 let off = builder.createVector(vectorOfEnums)
82 let start = ColorsNameSpace.Monster.startMonster(&builder)
83 ColorsNameSpace.Monster.add(colors: off, &builder)
84 let end = ColorsNameSpace.Monster.endMonster(&builder, start: start)
85 builder.finish(offset: end)
86 XCTAssertEqual(builder.sizedByteArray, [12, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0])
87 let monster = ColorsNameSpace.Monster.getRootAsMonster(bb: builder.buffer)
88 XCTAssertEqual(monster.colorsCount, 2)
89 XCTAssertEqual(monster.colors(at: 0), .blue)
90 XCTAssertEqual(monster.colors(at: 1), .green)
91 }
92
93 func testUnionVector() {
94 var fb = FlatBufferBuilder()
95
96 let swordDmg: Int32 = 8
97 let attackStart = Attacker.startAttacker(&fb)
98 Attacker.add(swordAttackDamage: swordDmg, &fb)
99 let attack = Attacker.endAttacker(&fb, start: attackStart)
100
101 let characterType: [Character] = [.belle, .mulan, .bookfan]
102
103 let characters = [
104 BookReader.createBookReader(builder: &fb, booksRead: 7),
105 attack,
106 BookReader.createBookReader(builder: &fb, booksRead: 2),
107 ]
108 let types = fb.createVector(characterType)
109 let characterVector = fb.createVector(ofOffsets: characters)
110 let end = Movie.createMovie(&fb, vectorOfCharactersType: types, vectorOfCharacters: characterVector)
111 Movie.finish(&fb, end: end)
112
113 var movie = Movie.getRootAsMovie(bb: fb.buffer)
114 XCTAssertEqual(movie.charactersTypeCount, Int32(characterType.count))
115 XCTAssertEqual(movie.charactersCount, Int32(characters.count))
116
117 for i in 0..<movie.charactersTypeCount {
118 XCTAssertEqual(movie.charactersType(at: i), characterType[Int(i)])
Austin Schuh272c6132020-11-14 16:37:52 -0800119 }
Austin Schuh58b9b472020-11-25 19:12:44 -0800120
121 XCTAssertEqual(movie.characters(at: 0, type: BookReader.self)?.booksRead, 7)
122 XCTAssertEqual(movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage, swordDmg)
123 XCTAssertEqual(movie.characters(at: 2, type: BookReader.self)?.booksRead, 2)
124
125 var objc: MovieT? = movie.unpack()
126 XCTAssertEqual(movie.charactersTypeCount, Int32(objc?.characters.count ?? 0))
127 XCTAssertEqual(movie.characters(at: 0, type: BookReader.self)?.booksRead, (objc?.characters[0]?.value as? BookReaderT)?.booksRead)
128 fb.clear()
129 let newMovie = Movie.pack(&fb, obj: &objc)
130 fb.finish(offset: newMovie)
131
132 let packedMovie = Movie.getRootAsMovie(bb: fb.buffer)
133
134 XCTAssertEqual(packedMovie.characters(at: 0, type: BookReader.self)?.booksRead, movie.characters(at: 0, type: BookReader.self)?.booksRead)
135 XCTAssertEqual(packedMovie.characters(at: 1, type: Attacker.self)?.swordAttackDamage, movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage)
136 XCTAssertEqual(packedMovie.characters(at: 2, type: BookReader.self)?.booksRead, movie.characters(at: 2, type: BookReader.self)?.booksRead)
137 }
Austin Schuh272c6132020-11-14 16:37:52 -0800138}
139
140public enum ColorsNameSpace {
Austin Schuh58b9b472020-11-25 19:12:44 -0800141
142 enum RGB: Int32, Enum {
143 typealias T = Int32
144 static var byteSize: Int { MemoryLayout<Int32>.size }
145 var value: Int32 { rawValue }
146 case red = 0, green = 1, blue = 2
147 }
148
149 struct Monster: FlatBufferObject {
150 var __buffer: ByteBuffer! { _accessor.bb }
151
152 private var _accessor: Table
153 static func getRootAsMonster(bb: ByteBuffer) -> Monster { Monster(Table(
154 bb: bb,
155 position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
156
157 init(_ t: Table) { _accessor = t }
158 init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
159
160 public var colorsCount: Int32 { let o = _accessor.offset(4); return o == 0 ? 0 : _accessor.vector(count: o) }
161 public func colors(at index: Int32) -> ColorsNameSpace.RGB? { let o = _accessor.offset(4); return o == 0 ? ColorsNameSpace.RGB(rawValue: 0)! : ColorsNameSpace.RGB(rawValue: _accessor.directRead(
162 of: Int32.self,
163 offset: _accessor.vector(at: o) + index * 4)) }
164 static func startMonster(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) }
165 static func add(colors: Offset<UOffset>, _ fbb: inout FlatBufferBuilder) { fbb.add(
166 offset: colors,
167 at: 4) }
168 static func endMonster(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end }
169 }
Austin Schuh272c6132020-11-14 16:37:52 -0800170}
171
172
173enum Equipment: Byte { case none, Weapon }
174
175enum Color3: Int8 { case red = 0, green, blue }
176
177struct FinalMonster {
Austin Schuh58b9b472020-11-25 19:12:44 -0800178
179 @inlinable
180 static func createMonster(
181 builder: inout FlatBufferBuilder,
182 position: Offset<UOffset>,
183 hp: Int16,
184 name: Offset<String>,
185 inventory: Offset<UOffset>,
186 color: Color3,
187 weapons: Offset<UOffset>,
188 equipment: Equipment = .none,
189 equippedOffset: Offset<Weapon>,
190 path: Offset<UOffset>) -> Offset<LocalMonster>
191 {
192 let start = builder.startTable(with: 11)
193 builder.add(structOffset: 4)
194 builder.add(element: hp, def: 100, at: 8)
195 builder.add(offset: name, at: 10)
196 builder.add(offset: inventory, at: 14)
197 builder.add(element: color.rawValue, def: Color3.green.rawValue, at: 16)
198 builder.add(offset: weapons, at: 18)
199 builder.add(element: equipment.rawValue, def: Equipment.none.rawValue, at: 20)
200 builder.add(offset: equippedOffset, at: 22)
201 builder.add(offset: path, at: 24)
202 return Offset(offset: builder.endTable(at: start))
203 }
Austin Schuh272c6132020-11-14 16:37:52 -0800204}
205
206struct LocalMonster {
Austin Schuh58b9b472020-11-25 19:12:44 -0800207
208 private var __t: Table
209
210 init(_ fb: ByteBuffer, o: Int32) { __t = Table(bb: fb, position: o) }
211 init(_ t: Table) { __t = t }
212
213 func weapon(at index: Int32) -> Weapon? { let o = __t.offset(4); return o == 0 ? nil : Weapon.assign(
214 __t.indirect(__t.vector(at: o) + (index * 4)),
215 __t.bb) }
216
217 func equiped<T: FlatBufferObject>() -> T? {
218 let o = __t.offset(8); return o == 0 ? nil : __t.union(o)
219 }
220
221 static func getRootAsMonster(bb: ByteBuffer) -> LocalMonster {
222 LocalMonster(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: 0))))
223 }
224
225 @inlinable
226 static func createMonster(
227 builder: inout FlatBufferBuilder,
228 offset: Offset<UOffset>,
229 equipment: Equipment = .none,
230 equippedOffset: UOffset) -> Offset<LocalMonster>
231 {
232 let start = builder.startTable(with: 3)
233 builder.add(element: equippedOffset, def: 0, at: 8)
234 builder.add(offset: offset, at: 4)
235 builder.add(element: equipment.rawValue, def: Equipment.none.rawValue, at: 6)
236 return Offset(offset: builder.endTable(at: start))
237 }
Austin Schuh272c6132020-11-14 16:37:52 -0800238}
239
240struct Weapon: FlatBufferObject {
Austin Schuh58b9b472020-11-25 19:12:44 -0800241
242 var __buffer: ByteBuffer! { __t.bb }
243
244 static let offsets: (name: VOffset, dmg: VOffset) = (4, 6)
245 private var __t: Table
246
247 init(_ t: Table) { __t = t }
248 init(_ fb: ByteBuffer, o: Int32) { __t = Table(bb: fb, position: o)}
249
250 var dmg: Int16 { let o = __t.offset(6); return o == 0 ? 0 : __t.readBuffer(of: Int16.self, at: o) }
251 var nameVector: [UInt8]? { __t.getVector(at: 4) }
252 var name: String? { let o = __t.offset(4); return o == 0 ? nil : __t.string(at: o) }
253
254 static func assign(_ i: Int32, _ bb: ByteBuffer) -> Weapon { Weapon(Table(bb: bb, position: i)) }
255
256 @inlinable
257 static func createWeapon(
258 builder: inout FlatBufferBuilder,
259 offset: Offset<String>,
260 dmg: Int16) -> Offset<Weapon>
261 {
262 let _start = builder.startTable(with: 2)
263 Weapon.add(builder: &builder, name: offset)
264 Weapon.add(builder: &builder, dmg: dmg)
265 return Weapon.end(builder: &builder, startOffset: _start)
266 }
267
268 @inlinable
269 static func end(builder: inout FlatBufferBuilder, startOffset: UOffset) -> Offset<Weapon> {
270 Offset(offset: builder.endTable(at: startOffset))
271 }
272
273 @inlinable
274 static func add(builder: inout FlatBufferBuilder, name: Offset<String>) {
275 builder.add(offset: name, at: Weapon.offsets.name)
276 }
277
278 @inlinable
279 static func add(builder: inout FlatBufferBuilder, dmg: Int16) {
280 builder.add(element: dmg, def: 0, at: Weapon.offsets.dmg)
281 }
Austin Schuh272c6132020-11-14 16:37:52 -0800282}