blob: f9c5e01cc385ae1f1cd5cc0704a62d23f6830c21 [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5import 'dart:typed_data';
6import 'dart:io' as io;
7
8import 'package:path/path.dart' as path;
9
10import 'package:flat_buffers/flat_buffers.dart';
11import 'package:test/test.dart';
12import 'package:test_reflective_loader/test_reflective_loader.dart';
13
14import './monster_test_my_game.example_generated.dart' as example;
15
16main() {
17 defineReflectiveSuite(() {
18 defineReflectiveTests(BuilderTest);
19 defineReflectiveTests(CheckOtherLangaugesData);
20 });
21}
22
23int indexToField(int index) {
24 return (1 + 1 + index) * 2;
25}
26
27@reflectiveTest
28class CheckOtherLangaugesData {
29 test_cppData() async {
30 List<int> data = await new io.File(path.join(
31 path.dirname(io.Platform.script.path),
32 'monsterdata_test.mon',
33 ))
34 .readAsBytes();
35 example.Monster mon = new example.Monster(data);
36 expect(mon.hp, 80);
37 expect(mon.mana, 150);
38 expect(mon.name, 'MyMonster');
39 expect(mon.pos.x, 1.0);
40 expect(mon.pos.y, 2.0);
41 expect(mon.pos.z, 3.0);
42 expect(mon.pos.test1, 3.0);
43 expect(mon.pos.test2.value, 2.0);
44 expect(mon.pos.test3.a, 5);
45 expect(mon.pos.test3.b, 6);
46 expect(mon.testType.value, example.AnyTypeId.Monster.value);
47 expect(mon.test is example.Monster, true);
48 final monster2 = mon.test as example.Monster;
49 expect(monster2.name, "Fred");
50
51 expect(mon.inventory.length, 5);
52 expect(mon.inventory.reduce((cur, next) => cur + next), 10);
53 expect(mon.test4.length, 2);
54 expect(
55 mon.test4[0].a + mon.test4[0].b + mon.test4[1].a + mon.test4[1].b, 100);
56 expect(mon.testarrayofstring.length, 2);
57 expect(mon.testarrayofstring[0], "test1");
58 expect(mon.testarrayofstring[1], "test2");
59
60 // this will fail if accessing any field fails.
61 expect(mon.toString(),
62 'Monster{pos: Vec3{x: 1.0, y: 2.0, z: 3.0, test1: 3.0, test2: Color{value: 2}, test3: Test{a: 5, b: 6}}, mana: 150, hp: 80, name: MyMonster, inventory: [0, 1, 2, 3, 4], color: Color{value: 8}, testType: AnyTypeId{value: 1}, test: Monster{pos: null, mana: 150, hp: 100, name: Fred, inventory: null, color: Color{value: 8}, testType: AnyTypeId{value: 0}, test: null, test4: null, testarrayofstring: null, testarrayoftables: null, enemy: null, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: 0, testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: null, vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}, test4: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], testarrayofstring: [test1, test2], testarrayoftables: null, enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, inventory: null, color: Color{value: 8}, testType: AnyTypeId{value: 0}, test: null, test4: null, testarrayofstring: null, testarrayoftables: null, enemy: null, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: 0, testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: null, vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, testhashs64Fnv1: 7930699090847568257, testhashu64Fnv1: 7930699090847568257, testhashs32Fnv1a: -1904106383, testhashu32Fnv1a: 2390860913, testhashs64Fnv1a: 4898026182817603057, testhashu64Fnv1a: 4898026182817603057, testarrayofbools: [true, false, true], testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], vectorOfLongs: [1, 100, 10000, 1000000, 100000000], vectorOfDoubles: [-1.7976931348623157e+308, 0.0, 1.7976931348623157e+308], parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}');
63 }
64}
65
66@reflectiveTest
67class BuilderTest {
68 void test_monsterBuilder() {
69 final fbBuilder = new Builder();
70 final str = fbBuilder.writeString('MyMonster');
71
72 fbBuilder.writeString('test1');
73 fbBuilder.writeString('test2');
74 final testArrayOfString = fbBuilder.endStructVector(2);
75
76 final fred = fbBuilder.writeString('Fred');
77
78 final List<int> treasure = [0, 1, 2, 3, 4];
79 final inventory = fbBuilder.writeListUint8(treasure);
80
81 final monBuilder = new example.MonsterBuilder(fbBuilder)
82 ..begin()
83 ..addNameOffset(fred);
84 final mon2 = monBuilder.finish();
85
86 final testBuilder = new example.TestBuilder(fbBuilder);
87 testBuilder.finish(10, 20);
88 testBuilder.finish(30, 40);
89 final test4 = fbBuilder.endStructVector(2);
90
91
92 monBuilder
93 ..begin()
94 ..addPos(
95 new example.Vec3Builder(fbBuilder).finish(
96 1.0,
97 2.0,
98 3.0,
99 3.0,
100 example.Color.Green,
101 () => testBuilder.finish(5, 6),
102 ),
103 )
104 ..addHp(80)
105 ..addNameOffset(str)
106 ..addInventoryOffset(inventory)
107 ..addTestType(example.AnyTypeId.Monster)
108 ..addTestOffset(mon2)
109 ..addTest4Offset(test4)
110 ..addTestarrayofstringOffset(testArrayOfString);
111 final mon = monBuilder.finish();
112 fbBuilder.finish(mon);
113 }
114
115 void test_error_addInt32_withoutStartTable() {
116 Builder builder = new Builder();
117 expect(() {
118 builder.addInt32(0, 0);
119 }, throwsStateError);
120 }
121
122 void test_error_addOffset_withoutStartTable() {
123 Builder builder = new Builder();
124 expect(() {
125 builder.addOffset(0, 0);
126 }, throwsStateError);
127 }
128
129 void test_error_endTable_withoutStartTable() {
130 Builder builder = new Builder();
131 expect(() {
132 builder.endTable();
133 }, throwsStateError);
134 }
135
136 void test_error_startTable_duringTable() {
137 Builder builder = new Builder();
138 builder.startTable();
139 expect(() {
140 builder.startTable();
141 }, throwsStateError);
142 }
143
144 void test_error_writeString_duringTable() {
145 Builder builder = new Builder();
146 builder.startTable();
147 expect(() {
148 builder.writeString('12345');
149 }, throwsStateError);
150 }
151
152 void test_file_identifier() {
153 Uint8List byteList;
154 {
155 Builder builder = new Builder(initialSize: 0);
156 builder.startTable();
157 int offset = builder.endTable();
158 byteList = builder.finish(offset, 'Az~ÿ');
159 }
160 // Convert byteList to a ByteData so that we can read data from it.
161 ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
162 // First 4 bytes are an offset to the table data.
163 int tableDataLoc = byteData.getUint32(0, Endian.little);
164 // Next 4 bytes are the file identifier.
165 expect(byteData.getUint8(4), 65); // 'a'
166 expect(byteData.getUint8(5), 122); // 'z'
167 expect(byteData.getUint8(6), 126); // '~'
168 expect(byteData.getUint8(7), 255); // 'ÿ'
169 // First 4 bytes of the table data are a backwards offset to the vtable.
170 int vTableLoc = tableDataLoc -
171 byteData.getInt32(tableDataLoc, Endian.little);
172 // First 2 bytes of the vtable are the size of the vtable in bytes, which
173 // should be 4.
174 expect(byteData.getUint16(vTableLoc, Endian.little), 4);
175 // Next 2 bytes are the size of the object in bytes (including the vtable
176 // pointer), which should be 4.
177 expect(byteData.getUint16(vTableLoc + 2, Endian.little), 4);
178 }
179
180 void test_low() {
181 Builder builder = new Builder(initialSize: 0);
182 expect((builder..putUint8(1)).lowFinish(), [1]);
183 expect((builder..putUint32(2)).lowFinish(), [2, 0, 0, 0, 0, 0, 0, 1]);
184 expect((builder..putUint8(3)).lowFinish(),
185 [0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
186 expect((builder..putUint8(4)).lowFinish(),
187 [0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
188 expect((builder..putUint8(5)).lowFinish(),
189 [0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
190 expect((builder..putUint32(6)).lowFinish(),
191 [6, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
192 }
193
194 void test_table_default() {
195 List<int> byteList;
196 {
197 Builder builder = new Builder(initialSize: 0);
198 builder.startTable();
199 builder.addInt32(0, 10, 10);
200 builder.addInt32(1, 20, 10);
201 int offset = builder.endTable();
202 byteList = builder.finish(offset);
203 }
204 // read and verify
205 BufferContext buffer = new BufferContext.fromBytes(byteList);
206 int objectOffset = buffer.derefObject(0);
207 // was not written, so uses the new default value
208 expect(
209 const Int32Reader()
210 .vTableGet(buffer, objectOffset, indexToField(0), 15),
211 15);
212 // has the written value
213 expect(
214 const Int32Reader()
215 .vTableGet(buffer, objectOffset, indexToField(1), 15),
216 20);
217 }
218
219 void test_table_format() {
220 Uint8List byteList;
221 {
222 Builder builder = new Builder(initialSize: 0);
223 builder.startTable();
224 builder.addInt32(0, 10);
225 builder.addInt32(1, 20);
226 builder.addInt32(2, 30);
227 byteList = builder.finish(builder.endTable());
228 }
229 // Convert byteList to a ByteData so that we can read data from it.
230 ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
231 // First 4 bytes are an offset to the table data.
232 int tableDataLoc = byteData.getUint32(0, Endian.little);
233 // First 4 bytes of the table data are a backwards offset to the vtable.
234 int vTableLoc = tableDataLoc -
235 byteData.getInt32(tableDataLoc, Endian.little);
236 // First 2 bytes of the vtable are the size of the vtable in bytes, which
237 // should be 10.
238 expect(byteData.getUint16(vTableLoc, Endian.little), 10);
239 // Next 2 bytes are the size of the object in bytes (including the vtable
240 // pointer), which should be 16.
241 expect(byteData.getUint16(vTableLoc + 2, Endian.little), 16);
242 // Remaining 6 bytes are the offsets within the object where the ints are
243 // located.
244 for (int i = 0; i < 3; i++) {
245 int offset =
246 byteData.getUint16(vTableLoc + 4 + 2 * i, Endian.little);
247 expect(byteData.getInt32(tableDataLoc + offset, Endian.little),
248 10 + 10 * i);
249 }
250 }
251
252 void test_table_string() {
253 String latinString = 'test';
254 String unicodeString = 'Проба пера';
255 List<int> byteList;
256 {
257 Builder builder = new Builder(initialSize: 0);
258 int latinStringOffset = builder.writeString(latinString);
259 int unicodeStringOffset = builder.writeString(unicodeString);
260 builder.startTable();
261 builder.addOffset(0, latinStringOffset);
262 builder.addOffset(1, unicodeStringOffset);
263 int offset = builder.endTable();
264 byteList = builder.finish(offset);
265 }
266 // read and verify
267 BufferContext buf = new BufferContext.fromBytes(byteList);
268 int objectOffset = buf.derefObject(0);
269 expect(const StringReader().vTableGet(buf, objectOffset, indexToField(0)),
270 latinString);
271 expect(const StringReader().vTableGet(buf, objectOffset, indexToField(1)),
272 unicodeString);
273 }
274
275 void test_table_types() {
276 List<int> byteList;
277 {
278 Builder builder = new Builder(initialSize: 0);
279 int stringOffset = builder.writeString('12345');
280 builder.startTable();
281 builder.addBool(0, true);
282 builder.addInt8(1, 10);
283 builder.addInt32(2, 20);
284 builder.addOffset(3, stringOffset);
285 builder.addInt32(4, 40);
286 builder.addUint32(5, 0x9ABCDEF0);
287 builder.addUint8(6, 0x9A);
288 int offset = builder.endTable();
289 byteList = builder.finish(offset);
290 }
291 // read and verify
292 BufferContext buf = new BufferContext.fromBytes(byteList);
293 int objectOffset = buf.derefObject(0);
294 expect(
295 const BoolReader().vTableGet(buf, objectOffset, indexToField(0)), true);
296 expect(
297 const Int8Reader().vTableGet(buf, objectOffset, indexToField(1)), 10);
298 expect(
299 const Int32Reader().vTableGet(buf, objectOffset, indexToField(2)), 20);
300 expect(const StringReader().vTableGet(buf, objectOffset, indexToField(3)),
301 '12345');
302 expect(
303 const Int32Reader().vTableGet(buf, objectOffset, indexToField(4)), 40);
304 expect(const Uint32Reader().vTableGet(buf, objectOffset, indexToField(5)),
305 0x9ABCDEF0);
306 expect(const Uint8Reader().vTableGet(buf, objectOffset, indexToField(6)),
307 0x9A);
308 }
309
310 void test_writeList_of_Uint32() {
311 List<int> values = <int>[10, 100, 12345, 0x9abcdef0];
312 // write
313 List<int> byteList;
314 {
315 Builder builder = new Builder(initialSize: 0);
316 int offset = builder.writeListUint32(values);
317 byteList = builder.finish(offset);
318 }
319 // read and verify
320 BufferContext buf = new BufferContext.fromBytes(byteList);
321 List<int> items = const Uint32ListReader().read(buf, 0);
322 expect(items, hasLength(4));
323 expect(items, orderedEquals(values));
324 }
325
326 void test_writeList_ofBool() {
327 void verifyListBooleans(int len, List<int> trueBits) {
328 // write
329 List<int> byteList;
330 {
331 Builder builder = new Builder(initialSize: 0);
332 List<bool> values = new List<bool>.filled(len, false);
333 for (int bit in trueBits) {
334 values[bit] = true;
335 }
336 int offset = builder.writeListBool(values);
337 byteList = builder.finish(offset);
338 }
339 // read and verify
340 BufferContext buf = new BufferContext.fromBytes(byteList);
341 List<bool> items = const BoolListReader().read(buf, 0);
342 expect(items, hasLength(len));
343 for (int i = 0; i < items.length; i++) {
344 expect(items[i], trueBits.contains(i), reason: 'bit $i of $len');
345 }
346 }
347
348 verifyListBooleans(0, <int>[]);
349 verifyListBooleans(1, <int>[]);
350 verifyListBooleans(1, <int>[0]);
351 verifyListBooleans(31, <int>[0, 1]);
352 verifyListBooleans(31, <int>[1, 2, 24, 25, 30]);
353 verifyListBooleans(31, <int>[0, 30]);
354 verifyListBooleans(32, <int>[1, 2, 24, 25, 31]);
355 verifyListBooleans(33, <int>[1, 2, 24, 25, 32]);
356 verifyListBooleans(33, <int>[1, 2, 24, 25, 31, 32]);
357 verifyListBooleans(63, <int>[]);
358 verifyListBooleans(63, <int>[0, 1, 2, 61, 62]);
359 verifyListBooleans(63, new List<int>.generate(63, (i) => i));
360 verifyListBooleans(64, <int>[]);
361 verifyListBooleans(64, <int>[0, 1, 2, 61, 62, 63]);
362 verifyListBooleans(64, <int>[1, 2, 62]);
363 verifyListBooleans(64, <int>[0, 1, 2, 63]);
364 verifyListBooleans(64, new List<int>.generate(64, (i) => i));
365 verifyListBooleans(100, <int>[0, 3, 30, 60, 90, 99]);
366 }
367
368 void test_writeList_ofInt32() {
369 List<int> byteList;
370 {
371 Builder builder = new Builder(initialSize: 0);
372 int offset = builder.writeListInt32(<int>[1, 2, 3, 4, 5]);
373 byteList = builder.finish(offset);
374 }
375 // read and verify
376 BufferContext buf = new BufferContext.fromBytes(byteList);
377 List<int> items = const ListReader<int>(const Int32Reader()).read(buf, 0);
378 expect(items, hasLength(5));
379 expect(items, orderedEquals(<int>[1, 2, 3, 4, 5]));
380 }
381
382 void test_writeList_ofFloat64() {
383 List<double> values = <double>[-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13];
384 // write
385 List<int> byteList;
386 {
387 Builder builder = new Builder(initialSize: 0);
388 int offset = builder.writeListFloat64(values);
389 byteList = builder.finish(offset);
390 }
391
392 // read and verify
393 BufferContext buf = new BufferContext.fromBytes(byteList);
394 List<double> items = const Float64ListReader().read(buf, 0);
395
396 expect(items, hasLength(values.length));
397 for (int i = 0; i < values.length; i++) {
398 expect(values[i], closeTo(items[i], .001));
399 }
400 }
401
402 void test_writeList_ofFloat32() {
403 List<double> values = [1.0, 2.23, -3.213, 7.8, 12.13];
404 // write
405 List<int> byteList;
406 {
407 Builder builder = new Builder(initialSize: 0);
408 int offset = builder.writeListFloat32(values);
409 byteList = builder.finish(offset);
410 }
411 // read and verify
412 BufferContext buf = new BufferContext.fromBytes(byteList);
413 List<double> items = const Float32ListReader().read(buf, 0);
414 expect(items, hasLength(5));
415 for (int i = 0; i < values.length; i++) {
416 expect(values[i], closeTo(items[i], .001));
417 }
418 }
419
420 void test_writeList_ofObjects() {
421 List<int> byteList;
422 {
423 Builder builder = new Builder(initialSize: 0);
424 // write the object #1
425 int object1;
426 {
427 builder.startTable();
428 builder.addInt32(0, 10);
429 builder.addInt32(1, 20);
430 object1 = builder.endTable();
431 }
432 // write the object #1
433 int object2;
434 {
435 builder.startTable();
436 builder.addInt32(0, 100);
437 builder.addInt32(1, 200);
438 object2 = builder.endTable();
439 }
440 // write the list
441 int offset = builder.writeList([object1, object2]);
442 byteList = builder.finish(offset);
443 }
444 // read and verify
445 BufferContext buf = new BufferContext.fromBytes(byteList);
446 List<TestPointImpl> items =
447 const ListReader<TestPointImpl>(const TestPointReader()).read(buf, 0);
448 expect(items, hasLength(2));
449 expect(items[0].x, 10);
450 expect(items[0].y, 20);
451 expect(items[1].x, 100);
452 expect(items[1].y, 200);
453 }
454
455 void test_writeList_ofStrings_asRoot() {
456 List<int> byteList;
457 {
458 Builder builder = new Builder(initialSize: 0);
459 int str1 = builder.writeString('12345');
460 int str2 = builder.writeString('ABC');
461 int offset = builder.writeList([str1, str2]);
462 byteList = builder.finish(offset);
463 }
464 // read and verify
465 BufferContext buf = new BufferContext.fromBytes(byteList);
466 List<String> items =
467 const ListReader<String>(const StringReader()).read(buf, 0);
468 expect(items, hasLength(2));
469 expect(items, contains('12345'));
470 expect(items, contains('ABC'));
471 }
472
473 void test_writeList_ofStrings_inObject() {
474 List<int> byteList;
475 {
476 Builder builder = new Builder(initialSize: 0);
477 int listOffset = builder.writeList(
478 [builder.writeString('12345'), builder.writeString('ABC')]);
479 builder.startTable();
480 builder.addOffset(0, listOffset);
481 int offset = builder.endTable();
482 byteList = builder.finish(offset);
483 }
484 // read and verify
485 BufferContext buf = new BufferContext.fromBytes(byteList);
486 StringListWrapperImpl reader = new StringListWrapperReader().read(buf, 0);
487 List<String> items = reader.items;
488 expect(items, hasLength(2));
489 expect(items, contains('12345'));
490 expect(items, contains('ABC'));
491 }
492
493 void test_writeList_ofUint32() {
494 List<int> byteList;
495 {
496 Builder builder = new Builder(initialSize: 0);
497 int offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]);
498 byteList = builder.finish(offset);
499 }
500 // read and verify
501 BufferContext buf = new BufferContext.fromBytes(byteList);
502 List<int> items = const Uint32ListReader().read(buf, 0);
503 expect(items, hasLength(3));
504 expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0]));
505 }
506
507 void test_writeList_ofUint16() {
508 List<int> byteList;
509 {
510 Builder builder = new Builder(initialSize: 0);
511 int offset = builder.writeListUint16(<int>[1, 2, 60000]);
512 byteList = builder.finish(offset);
513 }
514 // read and verify
515 BufferContext buf = new BufferContext.fromBytes(byteList);
516 List<int> items = const Uint16ListReader().read(buf, 0);
517 expect(items, hasLength(3));
518 expect(items, orderedEquals(<int>[1, 2, 60000]));
519 }
520
521 void test_writeList_ofUint8() {
522 List<int> byteList;
523 {
524 Builder builder = new Builder(initialSize: 0);
525 int offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A]);
526 byteList = builder.finish(offset);
527 }
528 // read and verify
529 BufferContext buf = new BufferContext.fromBytes(byteList);
530 List<int> items = const Uint8ListReader().read(buf, 0);
531 expect(items, hasLength(5));
532 expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A]));
533 }
534}
535
536class StringListWrapperImpl {
537 final BufferContext bp;
538 final int offset;
539
540 StringListWrapperImpl(this.bp, this.offset);
541
542 List<String> get items => const ListReader<String>(const StringReader())
543 .vTableGet(bp, offset, indexToField(0));
544}
545
546class StringListWrapperReader extends TableReader<StringListWrapperImpl> {
547 const StringListWrapperReader();
548
549 @override
550 StringListWrapperImpl createObject(BufferContext object, int offset) {
551 return new StringListWrapperImpl(object, offset);
552 }
553}
554
555class TestPointImpl {
556 final BufferContext bp;
557 final int offset;
558
559 TestPointImpl(this.bp, this.offset);
560
561 int get x => const Int32Reader().vTableGet(bp, offset, indexToField(0), 0);
562
563 int get y => const Int32Reader().vTableGet(bp, offset, indexToField(1), 0);
564}
565
566class TestPointReader extends TableReader<TestPointImpl> {
567 const TestPointReader();
568
569 @override
570 TestPointImpl createObject(BufferContext object, int offset) {
571 return new TestPointImpl(object, offset);
572 }
573}