diff options
author | Dan Field <dfield@gmail.com> | 2018-05-18 14:06:15 -0400 |
---|---|---|
committer | Wouter van Oortmerssen <aardappel@gmail.com> | 2018-05-18 11:06:15 -0700 |
commit | 88912640d08bab0588c5804d2990173006b57207 (patch) | |
tree | 5d451dd37682d66d40b85e4c3eeadd78e1a2a385 /dart | |
parent | c43a0beff0ab4e1d5c5fe5044dfb30f24974eaff (diff) | |
download | flatbuffers-88912640d08bab0588c5804d2990173006b57207.tar.gz flatbuffers-88912640d08bab0588c5804d2990173006b57207.tar.bz2 flatbuffers-88912640d08bab0588c5804d2990173006b57207.zip |
Add [Dart] support (#4676)
* Add [Dart] support
* fix enum vectors
* Allow for opt out of string interning
* fix comment style, make interning opt in
* remove Offset<T>, prefer int
* avoid creating unnecessary vtable objects
* start work on tests - do not generate builder if struct has 0 fields - add int64
* support reading structs properly
* correctly handle reading vectors of structs, dartfmt
* support structs, fix unnecessary prepares
* fix bool customizations
* undo unintentional removal of file
* docs updates, complete tutorial, bug fix for codegen
* more documentation
* Update docs, add to doxygen file
* update package structure, add samples script/code
* rearrange sample
* Tests
* Add readme for pub
* cleanup package for pub
* update docs for renamed file
* remove custom matcher, use `closeTo` instead
* remove unintentional file
* remove unintended file checkin
* use auto, move method, cleanup
* refactor to ObjectBuilders, add Builders
* Update tests, examples
* Add files missing from previous commit
* documentation and example updates
* Update LICENSE, make dartanalyzer happy, fix minor bugs, get rid of duplicate files, publish script
* fix sample for slightly different schema
* Update pubspec.yaml
Diffstat (limited to 'dart')
-rw-r--r-- | dart/LICENSE | 233 | ||||
-rw-r--r-- | dart/README.md | 13 | ||||
-rw-r--r-- | dart/example/example.dart | 155 | ||||
-rw-r--r-- | dart/example/monster_my_game.sample_generated.dart | 440 | ||||
-rw-r--r-- | dart/lib/flat_buffers.dart | 1241 | ||||
-rwxr-xr-x | dart/publish.sh | 28 | ||||
-rw-r--r-- | dart/pubspec.yaml | 18 | ||||
-rw-r--r-- | dart/test/flat_buffers_test.dart | 573 | ||||
-rw-r--r-- | dart/test/monster_test_my_game.example2_generated.dart | 60 | ||||
-rw-r--r-- | dart/test/monster_test_my_game.example_generated.dart | 1332 | ||||
-rw-r--r-- | dart/test/monster_test_my_game_generated.dart | 60 |
11 files changed, 4153 insertions, 0 deletions
diff --git a/dart/LICENSE b/dart/LICENSE new file mode 100644 index 00000000..b2ae013b --- /dev/null +++ b/dart/LICENSE @@ -0,0 +1,233 @@ +The code in lib/flat_buffers.dart is based on code that was releases under the +following license: + +Copyright 2012, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +To the extent permissible, the changes to that code and the other assets in +this package are licensed under the Apache2 license: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/dart/README.md b/dart/README.md new file mode 100644 index 00000000..11bc0c48 --- /dev/null +++ b/dart/README.md @@ -0,0 +1,13 @@ +# FlatBuffers for Dart + +This package is used to read and write FlatBuffer files in Dart. + +Most consumers will want to use the [`flatc`](https://github.com/google/flatbuffers) +compiler to generate Dart code from a FlatBuffers IDL schema. For example, the +`monster_my_game.sample_generated.dart` was generated with `flatc` from +`monster.fbs` in the example folder. The generated classes can be used to read +or write binary files that are interoperable with other languages and platforms +supported by FlatBuffers, as illustrated in the `example.dart` in the +examples folder. + +Additional documentation and examples are available [at the FlatBuffers site](https://google.github.io/flatbuffers/index.html)
\ No newline at end of file diff --git a/dart/example/example.dart b/dart/example/example.dart new file mode 100644 index 00000000..d95bb31f --- /dev/null +++ b/dart/example/example.dart @@ -0,0 +1,155 @@ +/* + * Copyright 2018 Dan Field. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'package:flat_buffers/flat_buffers.dart' as fb; +import './monster_my_game.sample_generated.dart' as myGame; + +// Example how to use FlatBuffers to create and read binary buffers. + +void main() { + builderTest(); + objectBuilderTest(); +} + +void builderTest() { + final builder = new fb.Builder(initialSize: 1024); + final int weaponOneName = builder.writeString("Sword"); + final int weaponOneDamage = 3; + + final int weaponTwoName = builder.writeString("Axe"); + final int weaponTwoDamage = 5; + + final swordBuilder = new myGame.WeaponBuilder(builder) + ..begin() + ..addNameOffset(weaponOneName) + ..addDamage(weaponOneDamage); + final int sword = swordBuilder.finish(); + + final axeBuilder = new myGame.WeaponBuilder(builder) + ..begin() + ..addNameOffset(weaponTwoName) + ..addDamage(weaponTwoDamage); + final int axe = axeBuilder.finish(); + + // Serialize a name for our monster, called "Orc". + final int name = builder.writeString('Orc'); + + // Create a list representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + final List<int> treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + final inventory = builder.writeListUint8(treasure); + final weapons = builder.writeList([sword, axe]); + + // Struct builders are very easy to reuse. + final vec3Builder = new myGame.Vec3Builder(builder); + + vec3Builder.finish(4.0, 5.0, 6.0); + vec3Builder.finish(1.0, 2.0, 3.0); + // Set his hit points to 300 and his mana to 150. + final int hp = 300; + final int mana = 150; + + final monster = new myGame.MonsterBuilder(builder) + ..begin() + ..addNameOffset(name) + ..addInventoryOffset(inventory) + ..addWeaponsOffset(weapons) + ..addEquippedType(myGame.EquipmentTypeId.Weapon) + ..addEquippedOffset(axe) + ..addHp(hp) + ..addMana(mana) + ..addPos(vec3Builder.finish(1.0, 2.0, 3.0)) + ..addColor(myGame.Color.Red); + + final int monsteroff = monster.finish(); + final buffer = builder.finish(monsteroff); + if (verify(buffer)) { + print( + "The FlatBuffer was successfully created with a builder and verified!"); + } +} + +void objectBuilderTest() { + // Create the builder here so we can use it for both weapons and equipped + // the actual data will only be written to the buffer once. + var axe = new myGame.WeaponObjectBuilder(name: 'Axe', damage: 5); + + var monsterBuilder = new myGame.MonsterObjectBuilder( + pos: new myGame.Vec3ObjectBuilder(x: 1.0, y: 2.0, z: 3.0), + mana: 150, + hp: 300, + name: 'Orc', + inventory: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + color: myGame.Color.Red, + weapons: [new myGame.WeaponObjectBuilder(name: 'Sword', damage: 3), axe], + equippedType: myGame.EquipmentTypeId.Weapon, + equipped: axe, + ); + + var buffer = monsterBuilder.toBytes(); + + // We now have a FlatBuffer we can store on disk or send over a network. + + // ** file/network code goes here :) ** + + // Instead, we're going to access it right away (as if we just received it). + if (verify(buffer)) { + print( + "The FlatBuffer was successfully created with an object builder and verified!"); + } +} + +bool verify(List<int> buffer) { + // Get access to the root: + var monster = new myGame.Monster(buffer); + + // Get and test some scalar types from the FlatBuffer. + assert(monster.hp == 80); + assert(monster.mana == 150); // default + assert(monster.name == "MyMonster"); + + // Get and test a field of the FlatBuffer's `struct`. + var pos = monster.pos; + assert(pos != null); + assert(pos.z == 3.0); + + // Get a test an element from the `inventory` FlatBuffer's `vector`. + var inv = monster.inventory; + assert(inv != null); + assert(inv.length == 10); + assert(inv[9] == 9); + + // Get and test the `weapons` FlatBuffers's `vector`. + var expected_weapon_names = ["Sword", "Axe"]; + var expected_weapon_damages = [3, 5]; + var weps = monster.weapons; + for (int i = 0; i < weps.length; i++) { + assert(weps[i].name == expected_weapon_names[i]); + assert(weps[i].damage == expected_weapon_damages[i]); + } + + // Get and test the `Equipment` union (`equipped` field). + assert(monster.equippedType.value == myGame.EquipmentTypeId.Weapon.value); + assert(monster.equippedType == myGame.EquipmentTypeId.Weapon); + + assert(monster.equipped is myGame.Weapon); + var equipped = monster.equipped as myGame.Weapon; + assert(equipped.name == "Axe"); + assert(equipped.damage == 5); + + print(monster); + return true; +} diff --git a/dart/example/monster_my_game.sample_generated.dart b/dart/example/monster_my_game.sample_generated.dart new file mode 100644 index 00000000..2c7c10d2 --- /dev/null +++ b/dart/example/monster_my_game.sample_generated.dart @@ -0,0 +1,440 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, non_constant_identifier_names + +library my_game.sample; + +import 'dart:typed_data' show Uint8List; +import 'package:flat_buffers/flat_buffers.dart' as fb; + + +class Color { + final int value; + const Color._(this.value); + + factory Color.fromValue(int value) { + if (value == null) return null; + if (!values.containsKey(value)) { + throw new StateError('Invalid value $value for bit flag enum Color'); + } + return values[value]; + } + + static const int minValue = 0; + static const int maxValue = 2; + static bool containsValue(int value) => values.containsKey(value); + + static const Color Red = const Color._(0); + static const Color Green = const Color._(1); + static const Color Blue = const Color._(2); + static get values => {0: Red,1: Green,2: Blue,}; + + static const fb.Reader<Color> reader = const _ColorReader(); + + @override + String toString() { + return 'Color{value: $value}'; + } +} + +class _ColorReader extends fb.Reader<Color> { + const _ColorReader(); + + @override + int get size => 1; + + @override + Color read(fb.BufferContext bc, int offset) => + new Color.fromValue(const fb.Int8Reader().read(bc, offset)); +} + +class EquipmentTypeId { + final int value; + const EquipmentTypeId._(this.value); + + factory EquipmentTypeId.fromValue(int value) { + if (value == null) return null; + if (!values.containsKey(value)) { + throw new StateError('Invalid value $value for bit flag enum EquipmentTypeId'); + } + return values[value]; + } + + static const int minValue = 0; + static const int maxValue = 1; + static bool containsValue(int value) => values.containsKey(value); + + static const EquipmentTypeId NONE = const EquipmentTypeId._(0); + static const EquipmentTypeId Weapon = const EquipmentTypeId._(1); + static get values => {0: NONE,1: Weapon,}; + + static const fb.Reader<EquipmentTypeId> reader = const _EquipmentTypeIdReader(); + + @override + String toString() { + return 'EquipmentTypeId{value: $value}'; + } +} + +class _EquipmentTypeIdReader extends fb.Reader<EquipmentTypeId> { + const _EquipmentTypeIdReader(); + + @override + int get size => 1; + + @override + EquipmentTypeId read(fb.BufferContext bc, int offset) => + new EquipmentTypeId.fromValue(const fb.Uint8Reader().read(bc, offset)); +} + +class Vec3 { + Vec3._(this._bc, this._bcOffset); + + static const fb.Reader<Vec3> reader = const _Vec3Reader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + double get x => const fb.Float32Reader().read(_bc, _bcOffset + 0); + double get y => const fb.Float32Reader().read(_bc, _bcOffset + 4); + double get z => const fb.Float32Reader().read(_bc, _bcOffset + 8); + + @override + String toString() { + return 'Vec3{x: $x, y: $y, z: $z}'; + } +} + +class _Vec3Reader extends fb.StructReader<Vec3> { + const _Vec3Reader(); + + @override + int get size => 12; + + @override + Vec3 createObject(fb.BufferContext bc, int offset) => + new Vec3._(bc, offset); +} + +class Vec3Builder { + Vec3Builder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + int finish(double x, double y, double z) { + fbBuilder.putFloat32(z); + fbBuilder.putFloat32(y); + fbBuilder.putFloat32(x); + return fbBuilder.offset; + } + +} + +class Vec3ObjectBuilder extends fb.ObjectBuilder { + final double _x; + final double _y; + final double _z; + + Vec3ObjectBuilder({ + double x, + double y, + double z, + }) + : _x = x, + _y = y, + _z = z; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + + fbBuilder.putFloat32(_z); + fbBuilder.putFloat32(_y); + fbBuilder.putFloat32(_x); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} +class Monster { + Monster._(this._bc, this._bcOffset); + factory Monster(List<int> bytes) { + fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader<Monster> reader = const _MonsterReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + Vec3 get pos => Vec3.reader.vTableGet(_bc, _bcOffset, 4, null); + int get mana => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 150); + int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100); + String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 10, null); + List<int> get inventory => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 14, null); + Color get color => new Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 2)); + List<Weapon> get weapons => const fb.ListReader<Weapon>(Weapon.reader).vTableGet(_bc, _bcOffset, 18, null); + EquipmentTypeId get equippedType => new EquipmentTypeId.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 20, null)); + dynamic get equipped { + switch (equippedType?.value) { + case 1: return Weapon.reader.vTableGet(_bc, _bcOffset, 22, null); + default: return null; + } + } + List<Vec3> get path => const fb.ListReader<Vec3>(Vec3.reader).vTableGet(_bc, _bcOffset, 24, null); + + @override + String toString() { + return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, weapons: $weapons, equippedType: $equippedType, equipped: $equipped, path: $path}'; + } +} + +class _MonsterReader extends fb.TableReader<Monster> { + const _MonsterReader(); + + @override + Monster createObject(fb.BufferContext bc, int offset) => + new Monster._(bc, offset); +} + +class MonsterBuilder { + MonsterBuilder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(); + } + + int addPos(int offset) { + fbBuilder.addStruct(0, offset); + return fbBuilder.offset; + } + int addMana(int mana) { + fbBuilder.addInt16(1, mana); + return fbBuilder.offset; + } + int addHp(int hp) { + fbBuilder.addInt16(2, hp); + return fbBuilder.offset; + } + int addNameOffset(int offset) { + fbBuilder.addOffset(3, offset); + return fbBuilder.offset; + } + int addInventoryOffset(int offset) { + fbBuilder.addOffset(5, offset); + return fbBuilder.offset; + } + int addColor(Color color) { + fbBuilder.addInt8(6, color?.value); + return fbBuilder.offset; + } + int addWeaponsOffset(int offset) { + fbBuilder.addOffset(7, offset); + return fbBuilder.offset; + } + int addEquippedType(EquipmentTypeId equippedType) { + fbBuilder.addUint8(8, equippedType?.value); + return fbBuilder.offset; + } + int addEquippedOffset(int offset) { + fbBuilder.addOffset(9, offset); + return fbBuilder.offset; + } + int addPathOffset(int offset) { + fbBuilder.addOffset(10, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class MonsterObjectBuilder extends fb.ObjectBuilder { + final Vec3ObjectBuilder _pos; + final int _mana; + final int _hp; + final String _name; + final List<int> _inventory; + final Color _color; + final List<WeaponObjectBuilder> _weapons; + final EquipmentTypeId _equippedType; + final dynamic _equipped; + final List<Vec3ObjectBuilder> _path; + + MonsterObjectBuilder({ + Vec3ObjectBuilder pos, + int mana, + int hp, + String name, + List<int> inventory, + Color color, + List<WeaponObjectBuilder> weapons, + EquipmentTypeId equippedType, + dynamic equipped, + List<Vec3ObjectBuilder> path, + }) + : _pos = pos, + _mana = mana, + _hp = hp, + _name = name, + _inventory = inventory, + _color = color, + _weapons = weapons, + _equippedType = equippedType, + _equipped = equipped, + _path = path; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + final int nameOffset = fbBuilder.writeString(_name); + final int inventoryOffset = _inventory?.isNotEmpty == true + ? fbBuilder.writeListUint8(_inventory) + : null; + final int weaponsOffset = _weapons?.isNotEmpty == true + ? fbBuilder.writeList(_weapons.map((b) => b.getOrCreateOffset(fbBuilder)).toList()) + : null; + final int equippedOffset = _equipped?.getOrCreateOffset(fbBuilder); + final int pathOffset = _path?.isNotEmpty == true + ? fbBuilder.writeListOfStructs(_path) + : null; + + fbBuilder.startTable(); + if (_pos != null) { + fbBuilder.addStruct(0, _pos.finish(fbBuilder)); + } + fbBuilder.addInt16(1, _mana); + fbBuilder.addInt16(2, _hp); + if (nameOffset != null) { + fbBuilder.addOffset(3, nameOffset); + } + if (inventoryOffset != null) { + fbBuilder.addOffset(5, inventoryOffset); + } + fbBuilder.addInt8(6, _color?.value); + if (weaponsOffset != null) { + fbBuilder.addOffset(7, weaponsOffset); + } + fbBuilder.addUint8(8, _equippedType?.value); + if (equippedOffset != null) { + fbBuilder.addOffset(9, equippedOffset); + } + if (pathOffset != null) { + fbBuilder.addOffset(10, pathOffset); + } + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} +class Weapon { + Weapon._(this._bc, this._bcOffset); + factory Weapon(List<int> bytes) { + fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader<Weapon> reader = const _WeaponReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 4, null); + int get damage => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, null); + + @override + String toString() { + return 'Weapon{name: $name, damage: $damage}'; + } +} + +class _WeaponReader extends fb.TableReader<Weapon> { + const _WeaponReader(); + + @override + Weapon createObject(fb.BufferContext bc, int offset) => + new Weapon._(bc, offset); +} + +class WeaponBuilder { + WeaponBuilder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(); + } + + int addNameOffset(int offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + int addDamage(int damage) { + fbBuilder.addInt16(1, damage); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class WeaponObjectBuilder extends fb.ObjectBuilder { + final String _name; + final int _damage; + + WeaponObjectBuilder({ + String name, + int damage, + }) + : _name = name, + _damage = damage; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + final int nameOffset = fbBuilder.writeString(_name); + + fbBuilder.startTable(); + if (nameOffset != null) { + fbBuilder.addOffset(0, nameOffset); + } + fbBuilder.addInt16(1, _damage); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} diff --git a/dart/lib/flat_buffers.dart b/dart/lib/flat_buffers.dart new file mode 100644 index 00000000..baef5a35 --- /dev/null +++ b/dart/lib/flat_buffers.dart @@ -0,0 +1,1241 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; +import 'dart:convert'; +import 'dart:math'; +import 'dart:typed_data'; + +const int _sizeofUint8 = 1; +const int _sizeofUint16 = 2; +const int _sizeofUint32 = 4; +const int _sizeofUint64 = 8; +const int _sizeofInt8 = 1; +const int _sizeofInt16 = 2; +const int _sizeofInt32 = 4; +const int _sizeofInt64 = 8; +const int _sizeofFloat32 = 4; +const int _sizeofFloat64 = 8; + +/// Callback used to invoke a struct builder's finish method. +/// +/// This callback is used by other struct's `finish` methods to write the nested +/// struct's fields inline. +typedef void StructBuilder(); + +/// Buffer with data and some context about it. +class BufferContext { + final ByteData _buffer; + + factory BufferContext.fromBytes(List<int> byteList) { + Uint8List uint8List = _asUint8List(byteList); + ByteData buf = new ByteData.view(uint8List.buffer, uint8List.offsetInBytes); + return new BufferContext._(buf); + } + + BufferContext._(this._buffer); + + int derefObject(int offset) { + return offset + _getUint32(offset); + } + + Uint8List _asUint8LIst(int offset, int length) => + _buffer.buffer.asUint8List(_buffer.offsetInBytes + offset, length); + + double _getFloat64(int offset) => + _buffer.getFloat64(offset, Endianness.LITTLE_ENDIAN); + + double _getFloat32(int offset) => + _buffer.getFloat32(offset, Endianness.LITTLE_ENDIAN); + + int _getInt64(int offset) => + _buffer.getInt64(offset, Endianness.LITTLE_ENDIAN); + + int _getInt32(int offset) => + _buffer.getInt32(offset, Endianness.LITTLE_ENDIAN); + + int _getInt16(int offset) => + _buffer.getInt16(offset, Endianness.LITTLE_ENDIAN); + + int _getInt8(int offset) => _buffer.getInt8(offset); + + int _getUint64(int offset) => + _buffer.getUint64(offset, Endianness.LITTLE_ENDIAN); + + int _getUint32(int offset) => + _buffer.getUint32(offset, Endianness.LITTLE_ENDIAN); + + int _getUint16(int offset) => + _buffer.getUint16(offset, Endianness.LITTLE_ENDIAN); + + int _getUint8(int offset) => _buffer.getUint8(offset); + + /// If the [byteList] is already a [Uint8List] return it. + /// Otherwise return a [Uint8List] copy of the [byteList]. + static Uint8List _asUint8List(List<int> byteList) { + if (byteList is Uint8List) { + return byteList; + } else { + return new Uint8List.fromList(byteList); + } + } +} + +/// Class implemented by typed builders generated by flatc. +abstract class ObjectBuilder { + int _firstOffset; + + /// Can be used to write the data represented by this builder to the [Builder] + /// and reuse the offset created in multiple tables. + /// + /// Note that this method assumes you call it using the same [Builder] instance + /// every time. The returned offset is only good for the [Builder] used in the + /// first call to this method. + int getOrCreateOffset(Builder fbBuilder) { + _firstOffset ??= finish(fbBuilder); + return _firstOffset; + } + + /// Writes the data in this helper to the [Builder]. + int finish(Builder fbBuilder); + + /// Convenience method that will create a new [Builder], [finish]es the data, + /// and returns the buffer as a [Uint8List] of bytes. + Uint8List toBytes(); +} + +/// Class that helps building flat buffers. +class Builder { + final int initialSize; + + /// The list of existing VTable(s). + //final List<_VTable> _vTables = <_VTable>[]; + final List<int> _vTables = <int>[]; + + ByteData _buf; + + /// The maximum alignment that has been seen so far. If [_buf] has to be + /// reallocated in the future (to insert room at its start for more bytes) the + /// reallocation will need to be a multiple of this many bytes. + int _maxAlign; + + /// The number of bytes that have been written to the buffer so far. The + /// most recently written byte is this many bytes from the end of [_buf]. + int _tail; + + /// The location of the end of the current table, measured in bytes from the + /// end of [_buf], or `null` if a table is not currently being built. + int _currentTableEndTail; + + _VTable _currentVTable; + + /// Map containing all strings that have been written so far. This allows us + /// to avoid duplicating strings. + /// + /// Allocated only if `internStrings` is set to true on the constructor. + Map<String, int> _strings; + + /// Creates a new FlatBuffers Builder. + /// + /// `initialSize` is the initial array size in bytes. The [Builder] will + /// automatically grow the array if/as needed. `internStrings`, if set to + /// true, will cause [writeString] to pool strings in the buffer so that + /// identical strings will always use the same offset in tables. + Builder({this.initialSize: 1024, bool internStrings = false}) { + if (internStrings == true) { + _strings = new Map<String, int>(); + } + reset(); + } + + /// Add the [field] with the given boolean [value]. The field is not added if + /// the [value] is equal to [def]. Booleans are stored as 8-bit fields with + /// `0` for `false` and `1` for `true`. + void addBool(int field, bool value, [bool def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofUint8, 1); + _trackField(field); + _buf.setInt8(_buf.lengthInBytes - _tail, value ? 1 : 0); + } + } + + /// Add the [field] with the given 32-bit signed integer [value]. The field is + /// not added if the [value] is equal to [def]. + void addInt32(int field, int value, [int def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofInt32, 1); + _trackField(field); + _setInt32AtTail(_buf, _tail, value); + } + } + + /// Add the [field] with the given 32-bit signed integer [value]. The field is + /// not added if the [value] is equal to [def]. + void addInt16(int field, int value, [int def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofInt16, 1); + _trackField(field); + _setInt16AtTail(_buf, _tail, value); + } + } + + /// Add the [field] with the given 8-bit signed integer [value]. The field is + /// not added if the [value] is equal to [def]. + void addInt8(int field, int value, [int def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofInt8, 1); + _trackField(field); + _setInt8AtTail(_buf, _tail, value); + } + } + + void addStruct(int field, int offset) { + _ensureCurrentVTable(); + _trackField(field); + _currentVTable.addField(field, offset); + } + + /// Add the [field] referencing an object with the given [offset]. + void addOffset(int field, int offset) { + _ensureCurrentVTable(); + if (offset != null) { + _prepare(_sizeofUint32, 1); + _trackField(field); + _setUint32AtTail(_buf, _tail, _tail - offset); + } + } + + /// Add the [field] with the given 32-bit unsigned integer [value]. The field + /// is not added if the [value] is equal to [def]. + void addUint32(int field, int value, [int def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofUint32, 1); + _trackField(field); + _setUint32AtTail(_buf, _tail, value); + } + } + + /// Add the [field] with the given 32-bit unsigned integer [value]. The field + /// is not added if the [value] is equal to [def]. + void addUint16(int field, int value, [int def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofUint16, 1); + _trackField(field); + _setUint16AtTail(_buf, _tail, value); + } + } + + /// Add the [field] with the given 8-bit unsigned integer [value]. The field + /// is not added if the [value] is equal to [def]. + void addUint8(int field, int value, [int def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofUint8, 1); + _trackField(field); + _setUint8AtTail(_buf, _tail, value); + } + } + + /// Add the [field] with the given 32-bit float [value]. The field + /// is not added if the [value] is equal to [def]. + void addFloat32(int field, double value, [double def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofFloat32, 1); + _trackField(field); + _setFloat32AtTail(_buf, _tail, value); + } + } + + /// Add the [field] with the given 64-bit double [value]. The field + /// is not added if the [value] is equal to [def]. + void addFloat64(int field, double value, [double def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofFloat64, 1); + _trackField(field); + _setFloat64AtTail(_buf, _tail, value); + } + } + + /// Add the [field] with the given 64-bit unsigned integer [value]. The field + /// is not added if the [value] is equal to [def]. + void addUint64(int field, int value, [double def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofUint64, 1); + _trackField(field); + _setUint64AtTail(_buf, _tail, value); + } + } + + /// Add the [field] with the given 64-bit unsigned integer [value]. The field + /// is not added if the [value] is equal to [def]. + void addInt64(int field, int value, [double def]) { + _ensureCurrentVTable(); + if (value != null && value != def) { + _prepare(_sizeofInt64, 1); + _trackField(field); + _setInt64AtTail(_buf, _tail, value); + } + } + + /// End the current table and return its offset. + int endTable() { + if (_currentVTable == null) { + throw new StateError('Start a table before ending it.'); + } + // Prepare for writing the VTable. + _prepare(_sizeofInt32, 1); + int tableTail = _tail; + // Prepare the size of the current table. + _currentVTable.tableSize = tableTail - _currentTableEndTail; + // Prepare the VTable to use for the current table. + int vTableTail; + { + _currentVTable.computeFieldOffsets(tableTail); + // Try to find an existing compatible VTable. + // Search backward - more likely to have recently used one + for (int i = _vTables.length - 1; i >= 0; i--) { + final int vt2Offset = _vTables[i]; + final int vt2Start = _buf.lengthInBytes - vt2Offset; + final int vt2Size = _buf.getUint16(vt2Start, Endianness.LITTLE_ENDIAN); + + if (_currentVTable._vTableSize == vt2Size && + _currentVTable._offsetsMatch(vt2Start, _buf)) { + vTableTail = vt2Offset; + break; + } + } + // Write a new VTable. + if (vTableTail == null) { + _prepare(_sizeofUint16, _currentVTable.numOfUint16); + vTableTail = _tail; + _currentVTable.tail = vTableTail; + _currentVTable.output(_buf, _buf.lengthInBytes - _tail); + _vTables.add(_currentVTable.tail); + } + } + // Set the VTable offset. + _setInt32AtTail(_buf, tableTail, vTableTail - tableTail); + // Done with this table. + _currentVTable = null; + return tableTail; + } + + /// This method low level method can be used to return a raw piece of the buffer + /// after using the the put* methods. + /// + /// Most clients should prefer calling [finish]. + Uint8List lowFinish() { + int alignedTail = _tail + ((-_tail) % _maxAlign); + return _buf.buffer.asUint8List(_buf.lengthInBytes - alignedTail); + } + + /// Finish off the creation of the buffer. The given [offset] is used as the + /// root object offset, and usually references directly or indirectly every + /// written object. If [fileIdentifier] is specified (and not `null`), it is + /// interpreted as a 4-byte Latin-1 encoded string that should be placed at + /// bytes 4-7 of the file. + Uint8List finish(int offset, [String fileIdentifier]) { + _prepare(max(_sizeofUint32, _maxAlign), fileIdentifier == null ? 1 : 2); + int alignedTail = _tail + ((-_tail) % _maxAlign); + _setUint32AtTail(_buf, alignedTail, alignedTail - offset); + if (fileIdentifier != null) { + for (int i = 0; i < 4; i++) { + _setUint8AtTail(_buf, alignedTail - _sizeofUint32 - i, + fileIdentifier.codeUnitAt(i)); + } + } + return _buf.buffer.asUint8List(_buf.lengthInBytes - alignedTail); + } + + /// Writes a Float64 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putFloat64(double value) { + _prepare(_sizeofFloat64, 1); + _setFloat32AtTail(_buf, _tail, value); + } + + /// Writes a Float32 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putFloat32(double value) { + _prepare(_sizeofFloat32, 1); + _setFloat32AtTail(_buf, _tail, value); + } + + /// Writes a Int64 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putInt64(int value) { + _prepare(_sizeofInt64, 1); + _setInt64AtTail(_buf, _tail, value); + } + + /// Writes a Uint32 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putInt32(int value) { + _prepare(_sizeofInt32, 1); + _setInt32AtTail(_buf, _tail, value); + } + + /// Writes a Uint16 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putInt16(int value) { + _prepare(_sizeofInt16, 1); + _setInt16AtTail(_buf, _tail, value); + } + + /// Writes a Uint8 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putInt8(int value) { + _prepare(_sizeofInt8, 1); + _buf.setInt8(_buf.lengthInBytes - _tail, value); + } + + /// Writes a Uint64 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putUint64(int value) { + _prepare(_sizeofUint64, 1); + _setUint64AtTail(_buf, _tail, value); + } + + /// Writes a Uint32 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putUint32(int value) { + _prepare(_sizeofUint32, 1); + _setUint32AtTail(_buf, _tail, value); + } + + /// Writes a Uint16 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putUint16(int value) { + _prepare(_sizeofUint16, 1); + _setUint16AtTail(_buf, _tail, value); + } + + /// Writes a Uint8 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putUint8(int value) { + _prepare(_sizeofUint8, 1); + _buf.setUint8(_buf.lengthInBytes - _tail, value); + } + + /// Reset the builder and make it ready for filling a new buffer. + void reset() { + _buf = new ByteData(initialSize); + _maxAlign = 1; + _tail = 0; + _currentVTable = null; + if (_strings != null) { + _strings = new Map<String, int>(); + } + } + + /// Start a new table. Must be finished with [endTable] invocation. + void startTable() { + if (_currentVTable != null) { + throw new StateError('Inline tables are not supported.'); + } + _currentVTable = new _VTable(); + _currentTableEndTail = _tail; + } + + /// Finish a Struct vector. Most callers should preferto use [writeListOfStructs]. + /// + /// Most callers should prefer [writeListOfStructs]. + int endStructVector(int count) { + putUint32(count); + return _tail; + } + + /// Writes a list of Structs to the buffer, returning the offset + int writeListOfStructs(List<ObjectBuilder> structBuilders) { + _ensureNoVTable(); + for (int i = structBuilders.length - 1; i >= 0; i--) { + structBuilders[i].finish(this); + } + return endStructVector(structBuilders.length); + } + + /// Write the given list of [values]. + int writeList(List<int> values) { + _ensureNoVTable(); + _prepare(_sizeofUint32, 1 + values.length); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (int value in values) { + _setUint32AtTail(_buf, tail, tail - value); + tail -= _sizeofUint32; + } + return result; + } + + /// Write the given list of 64-bit float [values]. + int writeListFloat64(List<double> values) { + _ensureNoVTable(); + _prepare(4, 1 + (2 * values.length)); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (double value in values) { + _setFloat64AtTail(_buf, tail, value); + tail -= _sizeofFloat64; + } + return result; + } + + /// Write the given list of 32-bit float [values]. + int writeListFloat32(List<double> values) { + _ensureNoVTable(); + _prepare(_sizeofFloat32, 1 + values.length); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (double value in values) { + _setFloat32AtTail(_buf, tail, value); + tail -= _sizeofFloat32; + } + return result; + } + + /// Write the given list of signed 64-bit integer [values]. + int writeListInt64(List<int> values) { + _ensureNoVTable(); + _prepare(_sizeofUint32, 2 * values.length); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (int value in values) { + _setInt64AtTail(_buf, tail, value); + tail -= _sizeofInt64; + } + return result; + } + + /// Write the given list of signed 64-bit integer [values]. + int writeListUint64(List<int> values) { + _ensureNoVTable(); + _prepare(_sizeofUint32, 2 * values.length); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (int value in values) { + _setUint64AtTail(_buf, tail, value); + tail -= _sizeofUint64; + } + return result; + } + + /// Write the given list of signed 32-bit integer [values]. + int writeListInt32(List<int> values) { + _ensureNoVTable(); + _prepare(_sizeofUint32, 1 + values.length); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (int value in values) { + _setInt32AtTail(_buf, tail, value); + tail -= _sizeofInt32; + } + return result; + } + + /// Write the given list of unsigned 32-bit integer [values]. + int writeListUint32(List<int> values) { + _ensureNoVTable(); + _prepare(_sizeofUint32, 1 + values.length); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (int value in values) { + _setUint32AtTail(_buf, tail, value); + tail -= _sizeofUint32; + } + return result; + } + + /// Write the given list of signed 16-bit integer [values]. + int writeListInt16(List<int> values) { + _ensureNoVTable(); + _prepare(_sizeofUint32, 1, additionalBytes: 2 * values.length); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (int value in values) { + _setInt16AtTail(_buf, tail, value); + tail -= _sizeofInt16; + } + return result; + } + + /// Write the given list of unsigned 16-bit integer [values]. + int writeListUint16(List<int> values) { + _ensureNoVTable(); + _prepare(_sizeofUint32, 1, additionalBytes: 2 * values.length); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (int value in values) { + _setUint16AtTail(_buf, tail, value); + tail -= _sizeofUint16; + } + return result; + } + + /// Write the given list of bools as unsigend 8-bit integer [values]. + int writeListBool(List<bool> values) { + return writeListUint8(values?.map((b) => b ? 1 : 0)?.toList()); + } + + /// Write the given list of signed 8-bit integer [values]. + int writeListInt8(List<int> values) { + _ensureNoVTable(); + _prepare(_sizeofUint32, 1, additionalBytes: values.length); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (int value in values) { + _setInt8AtTail(_buf, tail, value); + tail -= _sizeofUint8; + } + return result; + } + + /// Write the given list of unsigned 8-bit integer [values]. + int writeListUint8(List<int> values) { + _ensureNoVTable(); + _prepare(_sizeofUint32, 1, additionalBytes: values.length); + final int result = _tail; + int tail = _tail; + _setUint32AtTail(_buf, tail, values.length); + tail -= _sizeofUint32; + for (int value in values) { + _setUint8AtTail(_buf, tail, value); + tail -= _sizeofUint8; + } + return result; + } + + /// Write the given string [value] and return its offset, or `null` if + /// the [value] is `null`. + int writeString(String value) { + _ensureNoVTable(); + if (value != null) { + if (_strings != null) { + return _strings.putIfAbsent(value, () => _writeString(value)); + } else { + return _writeString(value); + } + } + return null; + } + + int _writeString(String value) { + // TODO(scheglov) optimize for ASCII strings + List<int> bytes = UTF8.encode(value); + int length = bytes.length; + _prepare(4, 1, additionalBytes: length); + final int result = _tail; + _setUint32AtTail(_buf, _tail, length); + int offset = _buf.lengthInBytes - _tail + 4; + for (int i = 0; i < length; i++) { + _buf.setUint8(offset++, bytes[i]); + } + return result; + } + + /// Throw an exception if there is not currently a vtable. + void _ensureCurrentVTable() { + if (_currentVTable == null) { + throw new StateError('Start a table before adding values.'); + } + } + + /// Throw an exception if there is currently a vtable. + void _ensureNoVTable() { + if (_currentVTable != null) { + throw new StateError( + 'Cannot write a non-scalar value while writing a table.'); + } + } + + /// The number of bytes that have been written to the buffer so far. The + /// most recently written byte is this many bytes from the end of the buffer. + int get offset => _tail; + + /// Zero-pads the buffer, which may be required for some struct layouts. + void pad(int howManyBytes) { + for (int i = 0; i < howManyBytes; i++) putUint8(0); + } + + /// Prepare for writing the given `count` of scalars of the given `size`. + /// Additionally allocate the specified `additionalBytes`. Update the current + /// tail pointer to point at the allocated space. + void _prepare(int size, int count, {int additionalBytes = 0}) { + // Update the alignment. + if (_maxAlign < size) { + _maxAlign = size; + } + // Prepare amount of required space. + int dataSize = size * count + additionalBytes; + int alignDelta = (-(_tail + dataSize)) % size; + int bufSize = alignDelta + dataSize; + // Ensure that we have the required amount of space. + { + int oldCapacity = _buf.lengthInBytes; + if (_tail + bufSize > oldCapacity) { + int desiredNewCapacity = (oldCapacity + bufSize) * 2; + int deltaCapacity = desiredNewCapacity - oldCapacity; + deltaCapacity += (-deltaCapacity) % _maxAlign; + int newCapacity = oldCapacity + deltaCapacity; + ByteData newBuf = new ByteData(newCapacity); + newBuf.buffer + .asUint8List() + .setAll(deltaCapacity, _buf.buffer.asUint8List()); + _buf = newBuf; + } + } + // Update the tail pointer. + _tail += bufSize; + } + + /// Record the offset of the given [field]. + void _trackField(int field) { + _currentVTable.addField(field, _tail); + } + + static void _setFloat64AtTail(ByteData _buf, int tail, double x) { + _buf.setFloat64(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN); + } + + static void _setFloat32AtTail(ByteData _buf, int tail, double x) { + _buf.setFloat32(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN); + } + + static void _setUint64AtTail(ByteData _buf, int tail, int x) { + _buf.setUint64(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN); + } + + static void _setInt64AtTail(ByteData _buf, int tail, int x) { + _buf.setInt64(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN); + } + + static void _setInt32AtTail(ByteData _buf, int tail, int x) { + _buf.setInt32(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN); + } + + static void _setUint32AtTail(ByteData _buf, int tail, int x) { + _buf.setUint32(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN); + } + + static void _setInt16AtTail(ByteData _buf, int tail, int x) { + _buf.setInt16(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN); + } + + static void _setUint16AtTail(ByteData _buf, int tail, int x) { + _buf.setUint16(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN); + } + + static void _setInt8AtTail(ByteData _buf, int tail, int x) { + _buf.setInt8(_buf.lengthInBytes - tail, x); + } + + static void _setUint8AtTail(ByteData _buf, int tail, int x) { + _buf.setUint8(_buf.lengthInBytes - tail, x); + } +} + +/// Reader of lists of boolean values. +/// +/// The returned unmodifiable lists lazily read values on access. +class BoolListReader extends Reader<List<bool>> { + const BoolListReader(); + + @override + int get size => _sizeofUint32; + + @override + List<bool> read(BufferContext bc, int offset) => + new _FbBoolList(bc, bc.derefObject(offset)); +} + +/// The reader of booleans. +class BoolReader extends Reader<bool> { + const BoolReader() : super(); + + @override + int get size => _sizeofUint8; + + @override + bool read(BufferContext bc, int offset) => bc._getInt8(offset) != 0; +} + +/// The reader of lists of 64-bit float values. +/// +/// The returned unmodifiable lists lazily read values on access. +class Float64ListReader extends Reader<List<double>> { + const Float64ListReader(); + + @override + int get size => _sizeofFloat64; + + @override + List<double> read(BufferContext bc, int offset) => + new _FbFloat64List(bc, bc.derefObject(offset)); +} + +class Float32ListReader extends Reader<List<double>> { + const Float32ListReader(); + + @override + int get size => _sizeofFloat32; + + @override + List<double> read(BufferContext bc, int offset) => + new _FbFloat32List(bc, bc.derefObject(offset)); +} + +class Float64Reader extends Reader<double> { + const Float64Reader(); + + @override + int get size => _sizeofFloat64; + + @override + double read(BufferContext bc, int offset) => bc._getFloat64(offset); +} + +class Float32Reader extends Reader<double> { + const Float32Reader(); + + @override + int get size => _sizeofFloat32; + + @override + double read(BufferContext bc, int offset) => bc._getFloat32(offset); +} + +class Int64Reader extends Reader<int> { + const Int64Reader() : super(); + @override + int get size => _sizeofInt64; + + @override + int read(BufferContext bc, int offset) => bc._getInt64(offset); +} + +/// The reader of signed 32-bit integers. +class Int32Reader extends Reader<int> { + const Int32Reader() : super(); + + @override + int get size => _sizeofInt32; + + @override + int read(BufferContext bc, int offset) => bc._getInt32(offset); +} + +/// The reader of signed 32-bit integers. +class Int16Reader extends Reader<int> { + const Int16Reader() : super(); + + @override + int get size => _sizeofInt16; + + @override + int read(BufferContext bc, int offset) => bc._getInt16(offset); +} + +/// The reader of 8-bit signed integers. +class Int8Reader extends Reader<int> { + const Int8Reader() : super(); + + @override + int get size => _sizeofInt8; + + @override + int read(BufferContext bc, int offset) => bc._getInt8(offset); +} + +/// The reader of lists of objects. +/// +/// The returned unmodifiable lists lazily read objects on access. +class ListReader<E> extends Reader<List<E>> { + final Reader<E> _elementReader; + + const ListReader(this._elementReader); + + @override + int get size => _sizeofUint32; + + @override + List<E> read(BufferContext bc, int offset) => + new _FbGenericList<E>(_elementReader, bc, bc.derefObject(offset)); +} + +/// Object that can read a value at a [BufferContext]. +abstract class Reader<T> { + const Reader(); + + /// The size of the value in bytes. + int get size; + + /// Read the value at the given [offset] in [bc]. + T read(BufferContext bc, int offset); + + /// Read the value of the given [field] in the given [object]. + T vTableGet(BufferContext object, int offset, int field, [T defaultValue]) { + int vTableSOffset = object._getInt32(offset); + int vTableOffset = offset - vTableSOffset; + int vTableSize = object._getUint16(vTableOffset); + int vTableFieldOffset = field; + if (vTableFieldOffset < vTableSize) { + int fieldOffsetInObject = + object._getUint16(vTableOffset + vTableFieldOffset); + if (fieldOffsetInObject != 0) { + return read(object, offset + fieldOffsetInObject); + } + } + return defaultValue; + } +} + +/// The reader of string values. +class StringReader extends Reader<String> { + const StringReader() : super(); + + @override + int get size => 4; + + @override + String read(BufferContext bc, int offset) { + int strOffset = bc.derefObject(offset); + int length = bc._getUint32(strOffset); + Uint8List bytes = bc._asUint8LIst(strOffset + 4, length); + if (_isLatin(bytes)) { + return new String.fromCharCodes(bytes); + } + return UTF8.decode(bytes); + } + + static bool _isLatin(Uint8List bytes) { + int length = bytes.length; + for (int i = 0; i < length; i++) { + if (bytes[i] > 127) { + return false; + } + } + return true; + } +} + +/// An abstract reader for structs. +abstract class StructReader<T> extends Reader<T> { + const StructReader(); + + /// Return the object at `offset`. + T createObject(BufferContext bc, int offset); + + T read(BufferContext bp, int offset) { + return createObject(bp, offset); + } +} + +/// An abstract reader for tables. +abstract class TableReader<T> extends Reader<T> { + const TableReader(); + + @override + int get size => 4; + + /// Return the object at [offset]. + T createObject(BufferContext bc, int offset); + + @override + T read(BufferContext bp, int offset) { + int objectOffset = bp.derefObject(offset); + return createObject(bp, objectOffset); + } +} + +/// Reader of lists of unsigned 32-bit integer values. +/// +/// The returned unmodifiable lists lazily read values on access. +class Uint32ListReader extends Reader<List<int>> { + const Uint32ListReader(); + + @override + int get size => _sizeofUint32; + + @override + List<int> read(BufferContext bc, int offset) => + new _FbUint32List(bc, bc.derefObject(offset)); +} + +/// The reader of unsigned 64-bit integers. +/// +/// WARNING: May have compatibility issues with JavaScript +class Uint64Reader extends Reader<int> { + const Uint64Reader() : super(); + + @override + int get size => _sizeofUint64; + + @override + int read(BufferContext bc, int offset) => bc._getUint64(offset); +} + +/// The reader of unsigned 32-bit integers. +class Uint32Reader extends Reader<int> { + const Uint32Reader() : super(); + + @override + int get size => _sizeofUint32; + + @override + int read(BufferContext bc, int offset) => bc._getUint32(offset); +} + +/// Reader of lists of unsigned 32-bit integer values. +/// +/// The returned unmodifiable lists lazily read values on access. +class Uint16ListReader extends Reader<List<int>> { + const Uint16ListReader(); + + @override + int get size => _sizeofUint32; + + @override + List<int> read(BufferContext bc, int offset) => + new _FbUint16List(bc, bc.derefObject(offset)); +} + +/// The reader of unsigned 32-bit integers. +class Uint16Reader extends Reader<int> { + const Uint16Reader() : super(); + + @override + int get size => _sizeofUint16; + + @override + int read(BufferContext bc, int offset) => bc._getUint16(offset); +} + +/// Reader of lists of unsigned 8-bit integer values. +/// +/// The returned unmodifiable lists lazily read values on access. +class Uint8ListReader extends Reader<List<int>> { + const Uint8ListReader(); + + @override + int get size => _sizeofUint32; + + @override + List<int> read(BufferContext bc, int offset) => + new _FbUint8List(bc, bc.derefObject(offset)); +} + +/// The reader of unsigned 8-bit integers. +class Uint8Reader extends Reader<int> { + const Uint8Reader() : super(); + + @override + int get size => _sizeofUint8; + + @override + int read(BufferContext bc, int offset) => bc._getUint8(offset); +} + +/// The list backed by 64-bit values - Uint64 length and Float64. +class _FbFloat64List extends _FbList<double> { + _FbFloat64List(BufferContext bc, int offset) : super(bc, offset); + + @override + double operator [](int i) { + return bc._getFloat64(offset + 4 + 8 * i); + } +} + +/// The list backed by 32-bit values - Float32. +class _FbFloat32List extends _FbList<double> { + _FbFloat32List(BufferContext bc, int offset) : super(bc, offset); + + @override + double operator [](int i) { + return bc._getFloat32(offset + 4 + 4 * i); + } +} + +/// List backed by a generic object which may have any size. +class _FbGenericList<E> extends _FbList<E> { + final Reader<E> elementReader; + + List<E> _items; + + _FbGenericList(this.elementReader, BufferContext bp, int offset) + : super(bp, offset); + + @override + E operator [](int i) { + _items ??= new List<E>(length); + E item = _items[i]; + if (item == null) { + item = elementReader.read(bc, offset + 4 + elementReader.size * i); + _items[i] = item; + } + return item; + } +} + +/// The base class for immutable lists read from flat buffers. +abstract class _FbList<E> extends Object with ListMixin<E> implements List<E> { + final BufferContext bc; + final int offset; + int _length; + + _FbList(this.bc, this.offset); + + @override + int get length { + _length ??= bc._getUint32(offset); + return _length; + } + + @override + void set length(int i) => + throw new StateError('Attempt to modify immutable list'); + + @override + void operator []=(int i, E e) => + throw new StateError('Attempt to modify immutable list'); +} + +/// List backed by 32-bit unsigned integers. +class _FbUint32List extends _FbList<int> { + _FbUint32List(BufferContext bc, int offset) : super(bc, offset); + + @override + int operator [](int i) { + return bc._getUint32(offset + 4 + 4 * i); + } +} + +/// List backed by 16-bit unsigned integers. +class _FbUint16List extends _FbList<int> { + _FbUint16List(BufferContext bc, int offset) : super(bc, offset); + + @override + int operator [](int i) { + return bc._getUint16(offset + 4 + 2 * i); + } +} + +/// List backed by 8-bit unsigned integers. +class _FbUint8List extends _FbList<int> { + _FbUint8List(BufferContext bc, int offset) : super(bc, offset); + + @override + int operator [](int i) { + return bc._getUint8(offset + 4 + i); + } +} + +/// List backed by 8-bit unsigned integers. +class _FbBoolList extends _FbList<bool> { + _FbBoolList(BufferContext bc, int offset) : super(bc, offset); + + @override + bool operator [](int i) { + return bc._getUint8(offset + 4 + i) == 1 ? true : false; + } +} + +/// Class that describes the structure of a table. +class _VTable { + static const int _metadataLength = 4; + + final List<int> fieldTails = <int>[]; + final List<int> fieldOffsets = <int>[]; + + /// The size of the table that uses this VTable. + int tableSize; + + /// The tail of this VTable. It is used to share the same VTable between + /// multiple tables of identical structure. + int tail; + + int get _vTableSize => numOfUint16 * _sizeofUint16; + + int get numOfUint16 => 1 + 1 + fieldTails.length; + + void addField(int field, int offset) { + while (fieldTails.length <= field) { + fieldTails.add(null); + } + fieldTails[field] = offset; + } + + bool _offsetsMatch(int vt2Start, ByteData buf) { + for (int i = 0; i < fieldOffsets.length; i++) { + if (fieldOffsets[i] != + buf.getUint16( + vt2Start + _metadataLength + (2 * i), Endianness.LITTLE_ENDIAN)) { + return false; + } + } + return true; + } + + /// Fill the [fieldOffsets] field. + void computeFieldOffsets(int tableTail) { + assert(fieldOffsets.isEmpty); + for (int fieldTail in fieldTails) { + int fieldOffset = fieldTail == null ? 0 : tableTail - fieldTail; + fieldOffsets.add(fieldOffset); + } + } + + /// Outputs this VTable to [buf], which is is expected to be aligned to 16-bit + /// and have at least [numOfUint16] 16-bit words available. + void output(ByteData buf, int bufOffset) { + // VTable size. + buf.setUint16(bufOffset, numOfUint16 * 2, Endianness.LITTLE_ENDIAN); + bufOffset += 2; + // Table size. + buf.setUint16(bufOffset, tableSize, Endianness.LITTLE_ENDIAN); + bufOffset += 2; + // Field offsets. + for (int fieldOffset in fieldOffsets) { + buf.setUint16(bufOffset, fieldOffset, Endianness.LITTLE_ENDIAN); + bufOffset += 2; + } + } +} diff --git a/dart/publish.sh b/dart/publish.sh new file mode 100755 index 00000000..167a4a34 --- /dev/null +++ b/dart/publish.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# +# Copyright 2018 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Note to pub consumers: this file is used to assist with publishing the +# pub package from the flatbuffers repository and is not meant for general use. +# As pub does not currently provide a way to exclude files, it is included here. + +command -v pub >/dev/null 2>&1 || { echo >&2 "Require `pub` but it's not installed. Aborting."; exit 1; } + +cp ../samples/monster.fbs example/ +cp ../tests/monster_test.fbs test/ +pub publish + +rm example/monster.fbs +rm test/monster_test.fbs
\ No newline at end of file diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml new file mode 100644 index 00000000..c71f831d --- /dev/null +++ b/dart/pubspec.yaml @@ -0,0 +1,18 @@ +name: flat_buffers +version: 1.9.0 +description: > + FlatBuffers reading and writing library for Dart. Use the flatc compiler to + generate Dart classes for a FlatBuffers schema, and this library to assist with + reading and writing the binary format. + + Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team. +authors: +- Dan Field <dfield@gmail.com> +- Konstantin Scheglov +- Paul Berry +homepage: https://github.com/google/flatbuffers +documentation: https://google.github.io/flatbuffers/index.html +dev_dependencies: + test: ^0.12.33 + test_reflective_loader: ^0.1.4 + path: ^1.5.1 diff --git a/dart/test/flat_buffers_test.dart b/dart/test/flat_buffers_test.dart new file mode 100644 index 00000000..9fbbf8ae --- /dev/null +++ b/dart/test/flat_buffers_test.dart @@ -0,0 +1,573 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:typed_data'; +import 'dart:io' as io; + +import 'package:path/path.dart' as path; + +import 'package:flat_buffers/flat_buffers.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import './monster_test_my_game.example_generated.dart' as example; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(BuilderTest); + defineReflectiveTests(CheckOtherLangaugesData); + }); +} + +int indexToField(int index) { + return (1 + 1 + index) * 2; +} + +@reflectiveTest +class CheckOtherLangaugesData { + test_cppData() async { + List<int> data = await new io.File(path.join( + path.dirname(io.Platform.script.path), + 'monsterdata_test.mon', + )) + .readAsBytes(); + example.Monster mon = new example.Monster(data); + expect(mon.hp, 80); + expect(mon.mana, 150); + expect(mon.name, 'MyMonster'); + expect(mon.pos.x, 1.0); + expect(mon.pos.y, 2.0); + expect(mon.pos.z, 3.0); + expect(mon.pos.test1, 3.0); + expect(mon.pos.test2.value, 2.0); + expect(mon.pos.test3.a, 5); + expect(mon.pos.test3.b, 6); + expect(mon.testType.value, example.AnyTypeId.Monster.value); + expect(mon.test is example.Monster, true); + final monster2 = mon.test as example.Monster; + expect(monster2.name, "Fred"); + + expect(mon.inventory.length, 5); + expect(mon.inventory.reduce((cur, next) => cur + next), 10); + expect(mon.test4.length, 2); + expect( + mon.test4[0].a + mon.test4[0].b + mon.test4[1].a + mon.test4[1].b, 100); + expect(mon.testarrayofstring.length, 2); + expect(mon.testarrayofstring[0], "test1"); + expect(mon.testarrayofstring[1], "test2"); + + // this will fail if accessing any field fails. + expect(mon.toString(), + '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: null, test: null, test4: null, testarrayofstring: null, testarrayoftables: null, enemy: null, testnestedflatbuffer: null, testempty: null, testbool: null, testhashs32Fnv1: null, testhashu32Fnv1: null, testhashs64Fnv1: null, testhashu64Fnv1: null, testhashs32Fnv1a: null, testhashu32Fnv1a: null, testhashs64Fnv1a: null, testhashu64Fnv1a: null, 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: null, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: null, vectorOfCoOwningReferences: null, nonOwningReference: null, 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: null, test: null, test4: null, testarrayofstring: null, testarrayoftables: null, enemy: null, testnestedflatbuffer: null, testempty: null, testbool: null, testhashs32Fnv1: null, testhashu32Fnv1: null, testhashs64Fnv1: null, testhashu64Fnv1: null, testhashs32Fnv1a: null, testhashu32Fnv1a: null, testhashs64Fnv1a: null, testhashu64Fnv1a: null, 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: null, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: null, vectorOfCoOwningReferences: null, nonOwningReference: null, vectorOfNonOwningReferences: null}, testnestedflatbuffer: null, testempty: null, testbool: null, 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: null, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: null, vectorOfCoOwningReferences: null, nonOwningReference: null, vectorOfNonOwningReferences: null}'); + } +} + +@reflectiveTest +class BuilderTest { + void test_monsterBuilder() { + final fbBuilder = new Builder(); + final str = fbBuilder.writeString('MyMonster'); + + fbBuilder.writeString('test1'); + fbBuilder.writeString('test2'); + final testArrayOfString = fbBuilder.endStructVector(2); + + final fred = fbBuilder.writeString('Fred'); + + final List<int> treasure = [0, 1, 2, 3, 4]; + final inventory = fbBuilder.writeListUint8(treasure); + + final monBuilder = new example.MonsterBuilder(fbBuilder) + ..begin() + ..addNameOffset(fred); + final mon2 = monBuilder.finish(); + + final testBuilder = new example.TestBuilder(fbBuilder); + testBuilder.finish(10, 20); + testBuilder.finish(30, 40); + final test4 = fbBuilder.endStructVector(2); + + + monBuilder + ..begin() + ..addPos( + new example.Vec3Builder(fbBuilder).finish( + 1.0, + 2.0, + 3.0, + 3.0, + example.Color.Green, + () => testBuilder.finish(5, 6), + ), + ) + ..addHp(80) + ..addNameOffset(str) + ..addInventoryOffset(inventory) + ..addTestType(example.AnyTypeId.Monster) + ..addTestOffset(mon2) + ..addTest4Offset(test4) + ..addTestarrayofstringOffset(testArrayOfString); + final mon = monBuilder.finish(); + fbBuilder.finish(mon); + } + + void test_error_addInt32_withoutStartTable() { + Builder builder = new Builder(); + expect(() { + builder.addInt32(0, 0); + }, throwsStateError); + } + + void test_error_addOffset_withoutStartTable() { + Builder builder = new Builder(); + expect(() { + builder.addOffset(0, 0); + }, throwsStateError); + } + + void test_error_endTable_withoutStartTable() { + Builder builder = new Builder(); + expect(() { + builder.endTable(); + }, throwsStateError); + } + + void test_error_startTable_duringTable() { + Builder builder = new Builder(); + builder.startTable(); + expect(() { + builder.startTable(); + }, throwsStateError); + } + + void test_error_writeString_duringTable() { + Builder builder = new Builder(); + builder.startTable(); + expect(() { + builder.writeString('12345'); + }, throwsStateError); + } + + void test_file_identifier() { + Uint8List byteList; + { + Builder builder = new Builder(initialSize: 0); + builder.startTable(); + int offset = builder.endTable(); + byteList = builder.finish(offset, 'Az~ÿ'); + } + // Convert byteList to a ByteData so that we can read data from it. + ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes); + // First 4 bytes are an offset to the table data. + int tableDataLoc = byteData.getUint32(0, Endianness.LITTLE_ENDIAN); + // Next 4 bytes are the file identifier. + expect(byteData.getUint8(4), 65); // 'a' + expect(byteData.getUint8(5), 122); // 'z' + expect(byteData.getUint8(6), 126); // '~' + expect(byteData.getUint8(7), 255); // 'ÿ' + // First 4 bytes of the table data are a backwards offset to the vtable. + int vTableLoc = tableDataLoc - + byteData.getInt32(tableDataLoc, Endianness.LITTLE_ENDIAN); + // First 2 bytes of the vtable are the size of the vtable in bytes, which + // should be 4. + expect(byteData.getUint16(vTableLoc, Endianness.LITTLE_ENDIAN), 4); + // Next 2 bytes are the size of the object in bytes (including the vtable + // pointer), which should be 4. + expect(byteData.getUint16(vTableLoc + 2, Endianness.LITTLE_ENDIAN), 4); + } + + void test_low() { + Builder builder = new Builder(initialSize: 0); + expect((builder..putUint8(1)).lowFinish(), [1]); + expect((builder..putUint32(2)).lowFinish(), [2, 0, 0, 0, 0, 0, 0, 1]); + expect((builder..putUint8(3)).lowFinish(), + [0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]); + expect((builder..putUint8(4)).lowFinish(), + [0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]); + expect((builder..putUint8(5)).lowFinish(), + [0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]); + expect((builder..putUint32(6)).lowFinish(), + [6, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]); + } + + void test_table_default() { + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + builder.startTable(); + builder.addInt32(0, 10, 10); + builder.addInt32(1, 20, 10); + int offset = builder.endTable(); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buffer = new BufferContext.fromBytes(byteList); + int objectOffset = buffer.derefObject(0); + // was not written, so uses the new default value + expect( + const Int32Reader() + .vTableGet(buffer, objectOffset, indexToField(0), 15), + 15); + // has the written value + expect( + const Int32Reader() + .vTableGet(buffer, objectOffset, indexToField(1), 15), + 20); + } + + void test_table_format() { + Uint8List byteList; + { + Builder builder = new Builder(initialSize: 0); + builder.startTable(); + builder.addInt32(0, 10); + builder.addInt32(1, 20); + builder.addInt32(2, 30); + byteList = builder.finish(builder.endTable()); + } + // Convert byteList to a ByteData so that we can read data from it. + ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes); + // First 4 bytes are an offset to the table data. + int tableDataLoc = byteData.getUint32(0, Endianness.LITTLE_ENDIAN); + // First 4 bytes of the table data are a backwards offset to the vtable. + int vTableLoc = tableDataLoc - + byteData.getInt32(tableDataLoc, Endianness.LITTLE_ENDIAN); + // First 2 bytes of the vtable are the size of the vtable in bytes, which + // should be 10. + expect(byteData.getUint16(vTableLoc, Endianness.LITTLE_ENDIAN), 10); + // Next 2 bytes are the size of the object in bytes (including the vtable + // pointer), which should be 16. + expect(byteData.getUint16(vTableLoc + 2, Endianness.LITTLE_ENDIAN), 16); + // Remaining 6 bytes are the offsets within the object where the ints are + // located. + for (int i = 0; i < 3; i++) { + int offset = + byteData.getUint16(vTableLoc + 4 + 2 * i, Endianness.LITTLE_ENDIAN); + expect(byteData.getInt32(tableDataLoc + offset, Endianness.LITTLE_ENDIAN), + 10 + 10 * i); + } + } + + void test_table_string() { + String latinString = 'test'; + String unicodeString = 'Проба пера'; + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int latinStringOffset = builder.writeString(latinString); + int unicodeStringOffset = builder.writeString(unicodeString); + builder.startTable(); + builder.addOffset(0, latinStringOffset); + builder.addOffset(1, unicodeStringOffset); + int offset = builder.endTable(); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + int objectOffset = buf.derefObject(0); + expect(const StringReader().vTableGet(buf, objectOffset, indexToField(0)), + latinString); + expect(const StringReader().vTableGet(buf, objectOffset, indexToField(1)), + unicodeString); + } + + void test_table_types() { + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int stringOffset = builder.writeString('12345'); + builder.startTable(); + builder.addBool(0, true); + builder.addInt8(1, 10); + builder.addInt32(2, 20); + builder.addOffset(3, stringOffset); + builder.addInt32(4, 40); + builder.addUint32(5, 0x9ABCDEF0); + builder.addUint8(6, 0x9A); + int offset = builder.endTable(); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + int objectOffset = buf.derefObject(0); + expect( + const BoolReader().vTableGet(buf, objectOffset, indexToField(0)), true); + expect( + const Int8Reader().vTableGet(buf, objectOffset, indexToField(1)), 10); + expect( + const Int32Reader().vTableGet(buf, objectOffset, indexToField(2)), 20); + expect(const StringReader().vTableGet(buf, objectOffset, indexToField(3)), + '12345'); + expect( + const Int32Reader().vTableGet(buf, objectOffset, indexToField(4)), 40); + expect(const Uint32Reader().vTableGet(buf, objectOffset, indexToField(5)), + 0x9ABCDEF0); + expect(const Uint8Reader().vTableGet(buf, objectOffset, indexToField(6)), + 0x9A); + } + + void test_writeList_of_Uint32() { + List<int> values = <int>[10, 100, 12345, 0x9abcdef0]; + // write + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int offset = builder.writeListUint32(values); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + List<int> items = const Uint32ListReader().read(buf, 0); + expect(items, hasLength(4)); + expect(items, orderedEquals(values)); + } + + void test_writeList_ofBool() { + void verifyListBooleans(int len, List<int> trueBits) { + // write + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + List<bool> values = new List<bool>.filled(len, false); + for (int bit in trueBits) { + values[bit] = true; + } + int offset = builder.writeListBool(values); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + List<bool> items = const BoolListReader().read(buf, 0); + expect(items, hasLength(len)); + for (int i = 0; i < items.length; i++) { + expect(items[i], trueBits.contains(i), reason: 'bit $i of $len'); + } + } + + verifyListBooleans(0, <int>[]); + verifyListBooleans(1, <int>[]); + verifyListBooleans(1, <int>[0]); + verifyListBooleans(31, <int>[0, 1]); + verifyListBooleans(31, <int>[1, 2, 24, 25, 30]); + verifyListBooleans(31, <int>[0, 30]); + verifyListBooleans(32, <int>[1, 2, 24, 25, 31]); + verifyListBooleans(33, <int>[1, 2, 24, 25, 32]); + verifyListBooleans(33, <int>[1, 2, 24, 25, 31, 32]); + verifyListBooleans(63, <int>[]); + verifyListBooleans(63, <int>[0, 1, 2, 61, 62]); + verifyListBooleans(63, new List<int>.generate(63, (i) => i)); + verifyListBooleans(64, <int>[]); + verifyListBooleans(64, <int>[0, 1, 2, 61, 62, 63]); + verifyListBooleans(64, <int>[1, 2, 62]); + verifyListBooleans(64, <int>[0, 1, 2, 63]); + verifyListBooleans(64, new List<int>.generate(64, (i) => i)); + verifyListBooleans(100, <int>[0, 3, 30, 60, 90, 99]); + } + + void test_writeList_ofInt32() { + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int offset = builder.writeListInt32(<int>[1, 2, 3, 4, 5]); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + List<int> items = const ListReader<int>(const Int32Reader()).read(buf, 0); + expect(items, hasLength(5)); + expect(items, orderedEquals(<int>[1, 2, 3, 4, 5])); + } + + void test_writeList_ofFloat64() { + List<double> values = <double>[-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13]; + // write + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int offset = builder.writeListFloat64(values); + byteList = builder.finish(offset); + } + + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + List<double> items = const Float64ListReader().read(buf, 0); + + expect(items, hasLength(values.length)); + for (int i = 0; i < values.length; i++) { + expect(values[i], closeTo(items[i], .001)); + } + } + + void test_writeList_ofFloat32() { + List<double> values = [1.0, 2.23, -3.213, 7.8, 12.13]; + // write + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int offset = builder.writeListFloat32(values); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + List<double> items = const Float32ListReader().read(buf, 0); + expect(items, hasLength(5)); + for (int i = 0; i < values.length; i++) { + expect(values[i], closeTo(items[i], .001)); + } + } + + void test_writeList_ofObjects() { + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + // write the object #1 + int object1; + { + builder.startTable(); + builder.addInt32(0, 10); + builder.addInt32(1, 20); + object1 = builder.endTable(); + } + // write the object #1 + int object2; + { + builder.startTable(); + builder.addInt32(0, 100); + builder.addInt32(1, 200); + object2 = builder.endTable(); + } + // write the list + int offset = builder.writeList([object1, object2]); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + List<TestPointImpl> items = + const ListReader<TestPointImpl>(const TestPointReader()).read(buf, 0); + expect(items, hasLength(2)); + expect(items[0].x, 10); + expect(items[0].y, 20); + expect(items[1].x, 100); + expect(items[1].y, 200); + } + + void test_writeList_ofStrings_asRoot() { + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int str1 = builder.writeString('12345'); + int str2 = builder.writeString('ABC'); + int offset = builder.writeList([str1, str2]); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + List<String> items = + const ListReader<String>(const StringReader()).read(buf, 0); + expect(items, hasLength(2)); + expect(items, contains('12345')); + expect(items, contains('ABC')); + } + + void test_writeList_ofStrings_inObject() { + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int listOffset = builder.writeList( + [builder.writeString('12345'), builder.writeString('ABC')]); + builder.startTable(); + builder.addOffset(0, listOffset); + int offset = builder.endTable(); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + StringListWrapperImpl reader = new StringListWrapperReader().read(buf, 0); + List<String> items = reader.items; + expect(items, hasLength(2)); + expect(items, contains('12345')); + expect(items, contains('ABC')); + } + + void test_writeList_ofUint32() { + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + List<int> items = const Uint32ListReader().read(buf, 0); + expect(items, hasLength(3)); + expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0])); + } + + void test_writeList_ofUint16() { + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int offset = builder.writeListUint16(<int>[1, 2, 60000]); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + List<int> items = const Uint16ListReader().read(buf, 0); + expect(items, hasLength(3)); + expect(items, orderedEquals(<int>[1, 2, 60000])); + } + + void test_writeList_ofUint8() { + List<int> byteList; + { + Builder builder = new Builder(initialSize: 0); + int offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A]); + byteList = builder.finish(offset); + } + // read and verify + BufferContext buf = new BufferContext.fromBytes(byteList); + List<int> items = const Uint8ListReader().read(buf, 0); + expect(items, hasLength(5)); + expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A])); + } +} + +class StringListWrapperImpl { + final BufferContext bp; + final int offset; + + StringListWrapperImpl(this.bp, this.offset); + + List<String> get items => const ListReader<String>(const StringReader()) + .vTableGet(bp, offset, indexToField(0)); +} + +class StringListWrapperReader extends TableReader<StringListWrapperImpl> { + const StringListWrapperReader(); + + @override + StringListWrapperImpl createObject(BufferContext object, int offset) { + return new StringListWrapperImpl(object, offset); + } +} + +class TestPointImpl { + final BufferContext bp; + final int offset; + + TestPointImpl(this.bp, this.offset); + + int get x => const Int32Reader().vTableGet(bp, offset, indexToField(0), 0); + + int get y => const Int32Reader().vTableGet(bp, offset, indexToField(1), 0); +} + +class TestPointReader extends TableReader<TestPointImpl> { + const TestPointReader(); + + @override + TestPointImpl createObject(BufferContext object, int offset) { + return new TestPointImpl(object, offset); + } +} diff --git a/dart/test/monster_test_my_game.example2_generated.dart b/dart/test/monster_test_my_game.example2_generated.dart new file mode 100644 index 00000000..eed14bc2 --- /dev/null +++ b/dart/test/monster_test_my_game.example2_generated.dart @@ -0,0 +1,60 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_local_variable + +library my_game.example2; + +import 'dart:typed_data' show Uint8List; +import 'package:flat_buffers/flat_buffers.dart' as fb; + +import './monster_test_my_game_generated.dart' as my_game; +import './monster_test_my_game.example_generated.dart' as my_game_example; + +class Monster { + Monster._(this._bc, this._bcOffset); + factory Monster(List<int> bytes) { + fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader<Monster> reader = const _MonsterReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + + @override + String toString() { + return 'Monster{}'; + } +} + +class _MonsterReader extends fb.TableReader<Monster> { + const _MonsterReader(); + + @override + Monster createObject(fb.BufferContext bc, int offset) => + new Monster._(bc, offset); +} + +class MonsterObjectBuilder extends fb.ObjectBuilder { + + MonsterObjectBuilder(); + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + + fbBuilder.startTable(); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} diff --git a/dart/test/monster_test_my_game.example_generated.dart b/dart/test/monster_test_my_game.example_generated.dart new file mode 100644 index 00000000..d85b5919 --- /dev/null +++ b/dart/test/monster_test_my_game.example_generated.dart @@ -0,0 +1,1332 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_local_variable + +library my_game.example; + +import 'dart:typed_data' show Uint8List; +import 'package:flat_buffers/flat_buffers.dart' as fb; + +import './monster_test_my_game.example2_generated.dart' as my_game_example2; +import './monster_test_my_game_generated.dart' as my_game; + +class Color { + final int value; + const Color._(this.value); + + factory Color.fromValue(int value) { + if (value == null) return null; + if (!values.containsKey(value)) { + throw new StateError('Invalid value $value for bit flag enum Color'); + } + return values[value]; + } + + static bool containsValue(int value) => values.containsKey(value); + + static const Color Red = const Color._(1); + static const Color Green = const Color._(2); + static const Color Blue = const Color._(8); + static get values => {1: Red,2: Green,8: Blue,}; + + static const fb.Reader<Color> reader = const _ColorReader(); + + @override + String toString() { + return 'Color{value: $value}'; + } +} + +class _ColorReader extends fb.Reader<Color> { + const _ColorReader(); + + @override + int get size => 1; + + @override + Color read(fb.BufferContext bc, int offset) => + new Color.fromValue(const fb.Int8Reader().read(bc, offset)); +} + +class AnyTypeId { + final int value; + const AnyTypeId._(this.value); + + factory AnyTypeId.fromValue(int value) { + if (value == null) return null; + if (!values.containsKey(value)) { + throw new StateError('Invalid value $value for bit flag enum AnyTypeId'); + } + return values[value]; + } + + static const int minValue = 0; + static const int maxValue = 3; + static bool containsValue(int value) => values.containsKey(value); + + static const AnyTypeId NONE = const AnyTypeId._(0); + static const AnyTypeId Monster = const AnyTypeId._(1); + static const AnyTypeId TestSimpleTableWithEnum = const AnyTypeId._(2); + static const AnyTypeId MyGame_Example2_Monster = const AnyTypeId._(3); + static get values => {0: NONE,1: Monster,2: TestSimpleTableWithEnum,3: MyGame_Example2_Monster,}; + + static const fb.Reader<AnyTypeId> reader = const _AnyTypeIdReader(); + + @override + String toString() { + return 'AnyTypeId{value: $value}'; + } +} + +class _AnyTypeIdReader extends fb.Reader<AnyTypeId> { + const _AnyTypeIdReader(); + + @override + int get size => 1; + + @override + AnyTypeId read(fb.BufferContext bc, int offset) => + new AnyTypeId.fromValue(const fb.Uint8Reader().read(bc, offset)); +} + +class Test { + Test._(this._bc, this._bcOffset); + + static const fb.Reader<Test> reader = const _TestReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get a => const fb.Int16Reader().read(_bc, _bcOffset + 0); + int get b => const fb.Int8Reader().read(_bc, _bcOffset + 2); + + @override + String toString() { + return 'Test{a: $a, b: $b}'; + } +} + +class _TestReader extends fb.StructReader<Test> { + const _TestReader(); + + @override + int get size => 4; + + @override + Test createObject(fb.BufferContext bc, int offset) => + new Test._(bc, offset); +} + +class TestBuilder { + TestBuilder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + int finish(int a, int b) { + fbBuilder.pad(1); + fbBuilder.putInt8(b); + fbBuilder.putInt16(a); + return fbBuilder.offset; + } + +} + +class TestObjectBuilder extends fb.ObjectBuilder { + final int _a; + final int _b; + + TestObjectBuilder({ + int a, + int b, + }) + : _a = a, + _b = b; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + + fbBuilder.pad(1); + fbBuilder.putInt8(_b); + fbBuilder.putInt16(_a); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} +class TestSimpleTableWithEnum { + TestSimpleTableWithEnum._(this._bc, this._bcOffset); + factory TestSimpleTableWithEnum(List<int> bytes) { + fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader<TestSimpleTableWithEnum> reader = const _TestSimpleTableWithEnumReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + Color get color => new Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 4, 2)); + + @override + String toString() { + return 'TestSimpleTableWithEnum{color: $color}'; + } +} + +class _TestSimpleTableWithEnumReader extends fb.TableReader<TestSimpleTableWithEnum> { + const _TestSimpleTableWithEnumReader(); + + @override + TestSimpleTableWithEnum createObject(fb.BufferContext bc, int offset) => + new TestSimpleTableWithEnum._(bc, offset); +} + +class TestSimpleTableWithEnumBuilder { + TestSimpleTableWithEnumBuilder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(); + } + + int addColor(Color color) { + fbBuilder.addInt8(0, color?.value); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class TestSimpleTableWithEnumObjectBuilder extends fb.ObjectBuilder { + final Color _color; + + TestSimpleTableWithEnumObjectBuilder({ + Color color, + }) + : _color = color; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + + fbBuilder.startTable(); + fbBuilder.addInt8(0, _color?.value); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} +class Vec3 { + Vec3._(this._bc, this._bcOffset); + + static const fb.Reader<Vec3> reader = const _Vec3Reader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + double get x => const fb.Float32Reader().read(_bc, _bcOffset + 0); + double get y => const fb.Float32Reader().read(_bc, _bcOffset + 4); + double get z => const fb.Float32Reader().read(_bc, _bcOffset + 8); + double get test1 => const fb.Float64Reader().read(_bc, _bcOffset + 16); + Color get test2 => new Color.fromValue(const fb.Int8Reader().read(_bc, _bcOffset + 24)); + Test get test3 => Test.reader.read(_bc, _bcOffset + 26); + + @override + String toString() { + return 'Vec3{x: $x, y: $y, z: $z, test1: $test1, test2: $test2, test3: $test3}'; + } +} + +class _Vec3Reader extends fb.StructReader<Vec3> { + const _Vec3Reader(); + + @override + int get size => 32; + + @override + Vec3 createObject(fb.BufferContext bc, int offset) => + new Vec3._(bc, offset); +} + +class Vec3Builder { + Vec3Builder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + int finish(double x, double y, double z, double test1, Color test2, fb.StructBuilder test3) { + fbBuilder.pad(2); + test3(); + fbBuilder.pad(1); + fbBuilder.putInt8(test2?.value); + fbBuilder.putFloat64(test1); + fbBuilder.pad(4); + fbBuilder.putFloat32(z); + fbBuilder.putFloat32(y); + fbBuilder.putFloat32(x); + return fbBuilder.offset; + } + +} + +class Vec3ObjectBuilder extends fb.ObjectBuilder { + final double _x; + final double _y; + final double _z; + final double _test1; + final Color _test2; + final TestObjectBuilder _test3; + + Vec3ObjectBuilder({ + double x, + double y, + double z, + double test1, + Color test2, + TestObjectBuilder test3, + }) + : _x = x, + _y = y, + _z = z, + _test1 = test1, + _test2 = test2, + _test3 = test3; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + + fbBuilder.pad(2); + _test3.finish(fbBuilder); + fbBuilder.pad(1); + fbBuilder.putInt8(_test2?.value); + fbBuilder.putFloat64(_test1); + fbBuilder.pad(4); + fbBuilder.putFloat32(_z); + fbBuilder.putFloat32(_y); + fbBuilder.putFloat32(_x); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} +class Ability { + Ability._(this._bc, this._bcOffset); + + static const fb.Reader<Ability> reader = const _AbilityReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get id => const fb.Uint32Reader().read(_bc, _bcOffset + 0); + int get distance => const fb.Uint32Reader().read(_bc, _bcOffset + 4); + + @override + String toString() { + return 'Ability{id: $id, distance: $distance}'; + } +} + +class _AbilityReader extends fb.StructReader<Ability> { + const _AbilityReader(); + + @override + int get size => 8; + + @override + Ability createObject(fb.BufferContext bc, int offset) => + new Ability._(bc, offset); +} + +class AbilityBuilder { + AbilityBuilder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + int finish(int id, int distance) { + fbBuilder.putUint32(distance); + fbBuilder.putUint32(id); + return fbBuilder.offset; + } + +} + +class AbilityObjectBuilder extends fb.ObjectBuilder { + final int _id; + final int _distance; + + AbilityObjectBuilder({ + int id, + int distance, + }) + : _id = id, + _distance = distance; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + + fbBuilder.putUint32(_distance); + fbBuilder.putUint32(_id); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} +class Stat { + Stat._(this._bc, this._bcOffset); + factory Stat(List<int> bytes) { + fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader<Stat> reader = const _StatReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + String get id => const fb.StringReader().vTableGet(_bc, _bcOffset, 4, null); + int get val => const fb.Int64Reader().vTableGet(_bc, _bcOffset, 6, null); + int get count => const fb.Uint16Reader().vTableGet(_bc, _bcOffset, 8, null); + + @override + String toString() { + return 'Stat{id: $id, val: $val, count: $count}'; + } +} + +class _StatReader extends fb.TableReader<Stat> { + const _StatReader(); + + @override + Stat createObject(fb.BufferContext bc, int offset) => + new Stat._(bc, offset); +} + +class StatBuilder { + StatBuilder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(); + } + + int addIdOffset(int offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + int addVal(int val) { + fbBuilder.addInt64(1, val); + return fbBuilder.offset; + } + int addCount(int count) { + fbBuilder.addUint16(2, count); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class StatObjectBuilder extends fb.ObjectBuilder { + final String _id; + final int _val; + final int _count; + + StatObjectBuilder({ + String id, + int val, + int count, + }) + : _id = id, + _val = val, + _count = count; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + final int idOffset = fbBuilder.writeString(_id); + + fbBuilder.startTable(); + if (idOffset != null) { + fbBuilder.addOffset(0, idOffset); + } + fbBuilder.addInt64(1, _val); + fbBuilder.addUint16(2, _count); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} +class Referrable { + Referrable._(this._bc, this._bcOffset); + factory Referrable(List<int> bytes) { + fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader<Referrable> reader = const _ReferrableReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get id => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 4, null); + + @override + String toString() { + return 'Referrable{id: $id}'; + } +} + +class _ReferrableReader extends fb.TableReader<Referrable> { + const _ReferrableReader(); + + @override + Referrable createObject(fb.BufferContext bc, int offset) => + new Referrable._(bc, offset); +} + +class ReferrableBuilder { + ReferrableBuilder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(); + } + + int addId(int id) { + fbBuilder.addUint64(0, id); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class ReferrableObjectBuilder extends fb.ObjectBuilder { + final int _id; + + ReferrableObjectBuilder({ + int id, + }) + : _id = id; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + + fbBuilder.startTable(); + fbBuilder.addUint64(0, _id); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} +/// an example documentation comment: monster object +class Monster { + Monster._(this._bc, this._bcOffset); + factory Monster(List<int> bytes) { + fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader<Monster> reader = const _MonsterReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + Vec3 get pos => Vec3.reader.vTableGet(_bc, _bcOffset, 4, null); + int get mana => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 150); + int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100); + String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 10, null); + List<int> get inventory => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 14, null); + Color get color => new Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 8)); + AnyTypeId get testType => new AnyTypeId.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 18, null)); + dynamic get test { + switch (testType?.value) { + case 1: return Monster.reader.vTableGet(_bc, _bcOffset, 20, null); + case 2: return TestSimpleTableWithEnum.reader.vTableGet(_bc, _bcOffset, 20, null); + case 3: return my_game_example2.Monster.reader.vTableGet(_bc, _bcOffset, 20, null); + default: return null; + } + } + List<Test> get test4 => const fb.ListReader<Test>(Test.reader).vTableGet(_bc, _bcOffset, 22, null); + List<String> get testarrayofstring => const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bc, _bcOffset, 24, null); +/// an example documentation comment: this will end up in the generated code +/// multiline too + List<Monster> get testarrayoftables => const fb.ListReader<Monster>(Monster.reader).vTableGet(_bc, _bcOffset, 26, null); + Monster get enemy => Monster.reader.vTableGet(_bc, _bcOffset, 28, null); + List<int> get testnestedflatbuffer => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 30, null); + Stat get testempty => Stat.reader.vTableGet(_bc, _bcOffset, 32, null); + bool get testbool => const fb.BoolReader().vTableGet(_bc, _bcOffset, 34, null); + int get testhashs32Fnv1 => const fb.Int32Reader().vTableGet(_bc, _bcOffset, 36, null); + int get testhashu32Fnv1 => const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 38, null); + int get testhashs64Fnv1 => const fb.Int64Reader().vTableGet(_bc, _bcOffset, 40, null); + int get testhashu64Fnv1 => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 42, null); + int get testhashs32Fnv1a => const fb.Int32Reader().vTableGet(_bc, _bcOffset, 44, null); + int get testhashu32Fnv1a => const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 46, null); + int get testhashs64Fnv1a => const fb.Int64Reader().vTableGet(_bc, _bcOffset, 48, null); + int get testhashu64Fnv1a => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 50, null); + List<bool> get testarrayofbools => const fb.ListReader<bool>(const fb.BoolReader()).vTableGet(_bc, _bcOffset, 52, null); + double get testf => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 54, 3.14159); + double get testf2 => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 56, 3.0); + double get testf3 => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 58, 0.0); + List<String> get testarrayofstring2 => const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bc, _bcOffset, 60, null); + List<Ability> get testarrayofsortedstruct => const fb.ListReader<Ability>(Ability.reader).vTableGet(_bc, _bcOffset, 62, null); + List<int> get flex => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 64, null); + List<Test> get test5 => const fb.ListReader<Test>(Test.reader).vTableGet(_bc, _bcOffset, 66, null); + List<int> get vectorOfLongs => const fb.ListReader<int>(const fb.Int64Reader()).vTableGet(_bc, _bcOffset, 68, null); + List<double> get vectorOfDoubles => const fb.ListReader<double>(const fb.Float64Reader()).vTableGet(_bc, _bcOffset, 70, null); + my_game.InParentNamespace get parentNamespaceTest => my_game.InParentNamespace.reader.vTableGet(_bc, _bcOffset, 72, null); + List<Referrable> get vectorOfReferrables => const fb.ListReader<Referrable>(Referrable.reader).vTableGet(_bc, _bcOffset, 74, null); + int get singleWeakReference => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 76, null); + List<int> get vectorOfWeakReferences => const fb.ListReader<int>(const fb.Uint64Reader()).vTableGet(_bc, _bcOffset, 78, null); + List<Referrable> get vectorOfStrongReferrables => const fb.ListReader<Referrable>(Referrable.reader).vTableGet(_bc, _bcOffset, 80, null); + int get coOwningReference => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 82, null); + List<int> get vectorOfCoOwningReferences => const fb.ListReader<int>(const fb.Uint64Reader()).vTableGet(_bc, _bcOffset, 84, null); + int get nonOwningReference => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 86, null); + List<int> get vectorOfNonOwningReferences => const fb.ListReader<int>(const fb.Uint64Reader()).vTableGet(_bc, _bcOffset, 88, null); + + @override + String toString() { + return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences}'; + } +} + +class _MonsterReader extends fb.TableReader<Monster> { + const _MonsterReader(); + + @override + Monster createObject(fb.BufferContext bc, int offset) => + new Monster._(bc, offset); +} + +class MonsterBuilder { + MonsterBuilder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(); + } + + int addPos(int offset) { + fbBuilder.addStruct(0, offset); + return fbBuilder.offset; + } + int addMana(int mana) { + fbBuilder.addInt16(1, mana); + return fbBuilder.offset; + } + int addHp(int hp) { + fbBuilder.addInt16(2, hp); + return fbBuilder.offset; + } + int addNameOffset(int offset) { + fbBuilder.addOffset(3, offset); + return fbBuilder.offset; + } + int addInventoryOffset(int offset) { + fbBuilder.addOffset(5, offset); + return fbBuilder.offset; + } + int addColor(Color color) { + fbBuilder.addInt8(6, color?.value); + return fbBuilder.offset; + } + int addTestType(AnyTypeId testType) { + fbBuilder.addUint8(7, testType?.value); + return fbBuilder.offset; + } + int addTestOffset(int offset) { + fbBuilder.addOffset(8, offset); + return fbBuilder.offset; + } + int addTest4Offset(int offset) { + fbBuilder.addOffset(9, offset); + return fbBuilder.offset; + } + int addTestarrayofstringOffset(int offset) { + fbBuilder.addOffset(10, offset); + return fbBuilder.offset; + } + int addTestarrayoftablesOffset(int offset) { + fbBuilder.addOffset(11, offset); + return fbBuilder.offset; + } + int addEnemyOffset(int offset) { + fbBuilder.addOffset(12, offset); + return fbBuilder.offset; + } + int addTestnestedflatbufferOffset(int offset) { + fbBuilder.addOffset(13, offset); + return fbBuilder.offset; + } + int addTestemptyOffset(int offset) { + fbBuilder.addOffset(14, offset); + return fbBuilder.offset; + } + int addTestbool(bool testbool) { + fbBuilder.addBool(15, testbool); + return fbBuilder.offset; + } + int addTesthashs32Fnv1(int testhashs32Fnv1) { + fbBuilder.addInt32(16, testhashs32Fnv1); + return fbBuilder.offset; + } + int addTesthashu32Fnv1(int testhashu32Fnv1) { + fbBuilder.addUint32(17, testhashu32Fnv1); + return fbBuilder.offset; + } + int addTesthashs64Fnv1(int testhashs64Fnv1) { + fbBuilder.addInt64(18, testhashs64Fnv1); + return fbBuilder.offset; + } + int addTesthashu64Fnv1(int testhashu64Fnv1) { + fbBuilder.addUint64(19, testhashu64Fnv1); + return fbBuilder.offset; + } + int addTesthashs32Fnv1a(int testhashs32Fnv1a) { + fbBuilder.addInt32(20, testhashs32Fnv1a); + return fbBuilder.offset; + } + int addTesthashu32Fnv1a(int testhashu32Fnv1a) { + fbBuilder.addUint32(21, testhashu32Fnv1a); + return fbBuilder.offset; + } + int addTesthashs64Fnv1a(int testhashs64Fnv1a) { + fbBuilder.addInt64(22, testhashs64Fnv1a); + return fbBuilder.offset; + } + int addTesthashu64Fnv1a(int testhashu64Fnv1a) { + fbBuilder.addUint64(23, testhashu64Fnv1a); + return fbBuilder.offset; + } + int addTestarrayofboolsOffset(int offset) { + fbBuilder.addOffset(24, offset); + return fbBuilder.offset; + } + int addTestf(double testf) { + fbBuilder.addFloat32(25, testf); + return fbBuilder.offset; + } + int addTestf2(double testf2) { + fbBuilder.addFloat32(26, testf2); + return fbBuilder.offset; + } + int addTestf3(double testf3) { + fbBuilder.addFloat32(27, testf3); + return fbBuilder.offset; + } + int addTestarrayofstring2Offset(int offset) { + fbBuilder.addOffset(28, offset); + return fbBuilder.offset; + } + int addTestarrayofsortedstructOffset(int offset) { + fbBuilder.addOffset(29, offset); + return fbBuilder.offset; + } + int addFlexOffset(int offset) { + fbBuilder.addOffset(30, offset); + return fbBuilder.offset; + } + int addTest5Offset(int offset) { + fbBuilder.addOffset(31, offset); + return fbBuilder.offset; + } + int addVectorOfLongsOffset(int offset) { + fbBuilder.addOffset(32, offset); + return fbBuilder.offset; + } + int addVectorOfDoublesOffset(int offset) { + fbBuilder.addOffset(33, offset); + return fbBuilder.offset; + } + int addParentNamespaceTestOffset(int offset) { + fbBuilder.addOffset(34, offset); + return fbBuilder.offset; + } + int addVectorOfReferrablesOffset(int offset) { + fbBuilder.addOffset(35, offset); + return fbBuilder.offset; + } + int addSingleWeakReference(int singleWeakReference) { + fbBuilder.addUint64(36, singleWeakReference); + return fbBuilder.offset; + } + int addVectorOfWeakReferencesOffset(int offset) { + fbBuilder.addOffset(37, offset); + return fbBuilder.offset; + } + int addVectorOfStrongReferrablesOffset(int offset) { + fbBuilder.addOffset(38, offset); + return fbBuilder.offset; + } + int addCoOwningReference(int coOwningReference) { + fbBuilder.addUint64(39, coOwningReference); + return fbBuilder.offset; + } + int addVectorOfCoOwningReferencesOffset(int offset) { + fbBuilder.addOffset(40, offset); + return fbBuilder.offset; + } + int addNonOwningReference(int nonOwningReference) { + fbBuilder.addUint64(41, nonOwningReference); + return fbBuilder.offset; + } + int addVectorOfNonOwningReferencesOffset(int offset) { + fbBuilder.addOffset(42, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class MonsterObjectBuilder extends fb.ObjectBuilder { + final Vec3ObjectBuilder _pos; + final int _mana; + final int _hp; + final String _name; + final List<int> _inventory; + final Color _color; + final AnyTypeId _testType; + final dynamic _test; + final List<TestObjectBuilder> _test4; + final List<String> _testarrayofstring; + final List<MonsterObjectBuilder> _testarrayoftables; + final MonsterObjectBuilder _enemy; + final List<int> _testnestedflatbuffer; + final StatObjectBuilder _testempty; + final bool _testbool; + final int _testhashs32Fnv1; + final int _testhashu32Fnv1; + final int _testhashs64Fnv1; + final int _testhashu64Fnv1; + final int _testhashs32Fnv1a; + final int _testhashu32Fnv1a; + final int _testhashs64Fnv1a; + final int _testhashu64Fnv1a; + final List<bool> _testarrayofbools; + final double _testf; + final double _testf2; + final double _testf3; + final List<String> _testarrayofstring2; + final List<AbilityObjectBuilder> _testarrayofsortedstruct; + final List<int> _flex; + final List<TestObjectBuilder> _test5; + final List<int> _vectorOfLongs; + final List<double> _vectorOfDoubles; + final my_game.InParentNamespaceObjectBuilder _parentNamespaceTest; + final List<ReferrableObjectBuilder> _vectorOfReferrables; + final int _singleWeakReference; + final List<int> _vectorOfWeakReferences; + final List<ReferrableObjectBuilder> _vectorOfStrongReferrables; + final int _coOwningReference; + final List<int> _vectorOfCoOwningReferences; + final int _nonOwningReference; + final List<int> _vectorOfNonOwningReferences; + + MonsterObjectBuilder({ + Vec3ObjectBuilder pos, + int mana, + int hp, + String name, + List<int> inventory, + Color color, + AnyTypeId testType, + dynamic test, + List<TestObjectBuilder> test4, + List<String> testarrayofstring, + List<MonsterObjectBuilder> testarrayoftables, + MonsterObjectBuilder enemy, + List<int> testnestedflatbuffer, + StatObjectBuilder testempty, + bool testbool, + int testhashs32Fnv1, + int testhashu32Fnv1, + int testhashs64Fnv1, + int testhashu64Fnv1, + int testhashs32Fnv1a, + int testhashu32Fnv1a, + int testhashs64Fnv1a, + int testhashu64Fnv1a, + List<bool> testarrayofbools, + double testf, + double testf2, + double testf3, + List<String> testarrayofstring2, + List<AbilityObjectBuilder> testarrayofsortedstruct, + List<int> flex, + List<TestObjectBuilder> test5, + List<int> vectorOfLongs, + List<double> vectorOfDoubles, + my_game.InParentNamespaceObjectBuilder parentNamespaceTest, + List<ReferrableObjectBuilder> vectorOfReferrables, + int singleWeakReference, + List<int> vectorOfWeakReferences, + List<ReferrableObjectBuilder> vectorOfStrongReferrables, + int coOwningReference, + List<int> vectorOfCoOwningReferences, + int nonOwningReference, + List<int> vectorOfNonOwningReferences, + }) + : _pos = pos, + _mana = mana, + _hp = hp, + _name = name, + _inventory = inventory, + _color = color, + _testType = testType, + _test = test, + _test4 = test4, + _testarrayofstring = testarrayofstring, + _testarrayoftables = testarrayoftables, + _enemy = enemy, + _testnestedflatbuffer = testnestedflatbuffer, + _testempty = testempty, + _testbool = testbool, + _testhashs32Fnv1 = testhashs32Fnv1, + _testhashu32Fnv1 = testhashu32Fnv1, + _testhashs64Fnv1 = testhashs64Fnv1, + _testhashu64Fnv1 = testhashu64Fnv1, + _testhashs32Fnv1a = testhashs32Fnv1a, + _testhashu32Fnv1a = testhashu32Fnv1a, + _testhashs64Fnv1a = testhashs64Fnv1a, + _testhashu64Fnv1a = testhashu64Fnv1a, + _testarrayofbools = testarrayofbools, + _testf = testf, + _testf2 = testf2, + _testf3 = testf3, + _testarrayofstring2 = testarrayofstring2, + _testarrayofsortedstruct = testarrayofsortedstruct, + _flex = flex, + _test5 = test5, + _vectorOfLongs = vectorOfLongs, + _vectorOfDoubles = vectorOfDoubles, + _parentNamespaceTest = parentNamespaceTest, + _vectorOfReferrables = vectorOfReferrables, + _singleWeakReference = singleWeakReference, + _vectorOfWeakReferences = vectorOfWeakReferences, + _vectorOfStrongReferrables = vectorOfStrongReferrables, + _coOwningReference = coOwningReference, + _vectorOfCoOwningReferences = vectorOfCoOwningReferences, + _nonOwningReference = nonOwningReference, + _vectorOfNonOwningReferences = vectorOfNonOwningReferences; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + final int nameOffset = fbBuilder.writeString(_name); + final int inventoryOffset = _inventory?.isNotEmpty == true + ? fbBuilder.writeListUint8(_inventory) + : null; + final int testOffset = _test?.getOrCreateOffset(fbBuilder); + final int test4Offset = _test4?.isNotEmpty == true + ? fbBuilder.writeListOfStructs(_test4) + : null; + final int testarrayofstringOffset = _testarrayofstring?.isNotEmpty == true + ? fbBuilder.writeList(_testarrayofstring.map((b) => fbBuilder.writeString(b)).toList()) + : null; + final int testarrayoftablesOffset = _testarrayoftables?.isNotEmpty == true + ? fbBuilder.writeList(_testarrayoftables.map((b) => b.getOrCreateOffset(fbBuilder)).toList()) + : null; + final int enemyOffset = _enemy?.getOrCreateOffset(fbBuilder); + final int testnestedflatbufferOffset = _testnestedflatbuffer?.isNotEmpty == true + ? fbBuilder.writeListUint8(_testnestedflatbuffer) + : null; + final int testemptyOffset = _testempty?.getOrCreateOffset(fbBuilder); + final int testarrayofboolsOffset = _testarrayofbools?.isNotEmpty == true + ? fbBuilder.writeListBool(_testarrayofbools) + : null; + final int testarrayofstring2Offset = _testarrayofstring2?.isNotEmpty == true + ? fbBuilder.writeList(_testarrayofstring2.map((b) => fbBuilder.writeString(b)).toList()) + : null; + final int testarrayofsortedstructOffset = _testarrayofsortedstruct?.isNotEmpty == true + ? fbBuilder.writeListOfStructs(_testarrayofsortedstruct) + : null; + final int flexOffset = _flex?.isNotEmpty == true + ? fbBuilder.writeListUint8(_flex) + : null; + final int test5Offset = _test5?.isNotEmpty == true + ? fbBuilder.writeListOfStructs(_test5) + : null; + final int vectorOfLongsOffset = _vectorOfLongs?.isNotEmpty == true + ? fbBuilder.writeListInt64(_vectorOfLongs) + : null; + final int vectorOfDoublesOffset = _vectorOfDoubles?.isNotEmpty == true + ? fbBuilder.writeListFloat64(_vectorOfDoubles) + : null; + final int parentNamespaceTestOffset = _parentNamespaceTest?.getOrCreateOffset(fbBuilder); + final int vectorOfReferrablesOffset = _vectorOfReferrables?.isNotEmpty == true + ? fbBuilder.writeList(_vectorOfReferrables.map((b) => b.getOrCreateOffset(fbBuilder)).toList()) + : null; + final int vectorOfWeakReferencesOffset = _vectorOfWeakReferences?.isNotEmpty == true + ? fbBuilder.writeListUint64(_vectorOfWeakReferences) + : null; + final int vectorOfStrongReferrablesOffset = _vectorOfStrongReferrables?.isNotEmpty == true + ? fbBuilder.writeList(_vectorOfStrongReferrables.map((b) => b.getOrCreateOffset(fbBuilder)).toList()) + : null; + final int vectorOfCoOwningReferencesOffset = _vectorOfCoOwningReferences?.isNotEmpty == true + ? fbBuilder.writeListUint64(_vectorOfCoOwningReferences) + : null; + final int vectorOfNonOwningReferencesOffset = _vectorOfNonOwningReferences?.isNotEmpty == true + ? fbBuilder.writeListUint64(_vectorOfNonOwningReferences) + : null; + + fbBuilder.startTable(); + if (_pos != null) { + fbBuilder.addStruct(0, _pos.finish(fbBuilder)); + } + fbBuilder.addInt16(1, _mana); + fbBuilder.addInt16(2, _hp); + if (nameOffset != null) { + fbBuilder.addOffset(3, nameOffset); + } + if (inventoryOffset != null) { + fbBuilder.addOffset(5, inventoryOffset); + } + fbBuilder.addInt8(6, _color?.value); + fbBuilder.addUint8(7, _testType?.value); + if (testOffset != null) { + fbBuilder.addOffset(8, testOffset); + } + if (test4Offset != null) { + fbBuilder.addOffset(9, test4Offset); + } + if (testarrayofstringOffset != null) { + fbBuilder.addOffset(10, testarrayofstringOffset); + } + if (testarrayoftablesOffset != null) { + fbBuilder.addOffset(11, testarrayoftablesOffset); + } + if (enemyOffset != null) { + fbBuilder.addOffset(12, enemyOffset); + } + if (testnestedflatbufferOffset != null) { + fbBuilder.addOffset(13, testnestedflatbufferOffset); + } + if (testemptyOffset != null) { + fbBuilder.addOffset(14, testemptyOffset); + } + fbBuilder.addBool(15, _testbool); + fbBuilder.addInt32(16, _testhashs32Fnv1); + fbBuilder.addUint32(17, _testhashu32Fnv1); + fbBuilder.addInt64(18, _testhashs64Fnv1); + fbBuilder.addUint64(19, _testhashu64Fnv1); + fbBuilder.addInt32(20, _testhashs32Fnv1a); + fbBuilder.addUint32(21, _testhashu32Fnv1a); + fbBuilder.addInt64(22, _testhashs64Fnv1a); + fbBuilder.addUint64(23, _testhashu64Fnv1a); + if (testarrayofboolsOffset != null) { + fbBuilder.addOffset(24, testarrayofboolsOffset); + } + fbBuilder.addFloat32(25, _testf); + fbBuilder.addFloat32(26, _testf2); + fbBuilder.addFloat32(27, _testf3); + if (testarrayofstring2Offset != null) { + fbBuilder.addOffset(28, testarrayofstring2Offset); + } + if (testarrayofsortedstructOffset != null) { + fbBuilder.addOffset(29, testarrayofsortedstructOffset); + } + if (flexOffset != null) { + fbBuilder.addOffset(30, flexOffset); + } + if (test5Offset != null) { + fbBuilder.addOffset(31, test5Offset); + } + if (vectorOfLongsOffset != null) { + fbBuilder.addOffset(32, vectorOfLongsOffset); + } + if (vectorOfDoublesOffset != null) { + fbBuilder.addOffset(33, vectorOfDoublesOffset); + } + if (parentNamespaceTestOffset != null) { + fbBuilder.addOffset(34, parentNamespaceTestOffset); + } + if (vectorOfReferrablesOffset != null) { + fbBuilder.addOffset(35, vectorOfReferrablesOffset); + } + fbBuilder.addUint64(36, _singleWeakReference); + if (vectorOfWeakReferencesOffset != null) { + fbBuilder.addOffset(37, vectorOfWeakReferencesOffset); + } + if (vectorOfStrongReferrablesOffset != null) { + fbBuilder.addOffset(38, vectorOfStrongReferrablesOffset); + } + fbBuilder.addUint64(39, _coOwningReference); + if (vectorOfCoOwningReferencesOffset != null) { + fbBuilder.addOffset(40, vectorOfCoOwningReferencesOffset); + } + fbBuilder.addUint64(41, _nonOwningReference); + if (vectorOfNonOwningReferencesOffset != null) { + fbBuilder.addOffset(42, vectorOfNonOwningReferencesOffset); + } + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} +class TypeAliases { + TypeAliases._(this._bc, this._bcOffset); + factory TypeAliases(List<int> bytes) { + fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader<TypeAliases> reader = const _TypeAliasesReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get i8 => const fb.Int8Reader().vTableGet(_bc, _bcOffset, 4, null); + int get u8 => const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 6, null); + int get i16 => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, null); + int get u16 => const fb.Uint16Reader().vTableGet(_bc, _bcOffset, 10, null); + int get i32 => const fb.Int32Reader().vTableGet(_bc, _bcOffset, 12, null); + int get u32 => const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 14, null); + int get i64 => const fb.Int64Reader().vTableGet(_bc, _bcOffset, 16, null); + int get u64 => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 18, null); + double get f32 => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 20, 0.0); + double get f64 => const fb.Float64Reader().vTableGet(_bc, _bcOffset, 22, 0.0); + List<int> get v8 => const fb.ListReader<int>(const fb.Int8Reader()).vTableGet(_bc, _bcOffset, 24, null); + List<double> get vf64 => const fb.ListReader<double>(const fb.Float64Reader()).vTableGet(_bc, _bcOffset, 26, null); + + @override + String toString() { + return 'TypeAliases{i8: $i8, u8: $u8, i16: $i16, u16: $u16, i32: $i32, u32: $u32, i64: $i64, u64: $u64, f32: $f32, f64: $f64, v8: $v8, vf64: $vf64}'; + } +} + +class _TypeAliasesReader extends fb.TableReader<TypeAliases> { + const _TypeAliasesReader(); + + @override + TypeAliases createObject(fb.BufferContext bc, int offset) => + new TypeAliases._(bc, offset); +} + +class TypeAliasesBuilder { + TypeAliasesBuilder(this.fbBuilder) { + assert(fbBuilder != null); + } + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(); + } + + int addI8(int i8) { + fbBuilder.addInt8(0, i8); + return fbBuilder.offset; + } + int addU8(int u8) { + fbBuilder.addUint8(1, u8); + return fbBuilder.offset; + } + int addI16(int i16) { + fbBuilder.addInt16(2, i16); + return fbBuilder.offset; + } + int addU16(int u16) { + fbBuilder.addUint16(3, u16); + return fbBuilder.offset; + } + int addI32(int i32) { + fbBuilder.addInt32(4, i32); + return fbBuilder.offset; + } + int addU32(int u32) { + fbBuilder.addUint32(5, u32); + return fbBuilder.offset; + } + int addI64(int i64) { + fbBuilder.addInt64(6, i64); + return fbBuilder.offset; + } + int addU64(int u64) { + fbBuilder.addUint64(7, u64); + return fbBuilder.offset; + } + int addF32(double f32) { + fbBuilder.addFloat32(8, f32); + return fbBuilder.offset; + } + int addF64(double f64) { + fbBuilder.addFloat64(9, f64); + return fbBuilder.offset; + } + int addV8Offset(int offset) { + fbBuilder.addOffset(10, offset); + return fbBuilder.offset; + } + int addVf64Offset(int offset) { + fbBuilder.addOffset(11, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class TypeAliasesObjectBuilder extends fb.ObjectBuilder { + final int _i8; + final int _u8; + final int _i16; + final int _u16; + final int _i32; + final int _u32; + final int _i64; + final int _u64; + final double _f32; + final double _f64; + final List<int> _v8; + final List<double> _vf64; + + TypeAliasesObjectBuilder({ + int i8, + int u8, + int i16, + int u16, + int i32, + int u32, + int i64, + int u64, + double f32, + double f64, + List<int> v8, + List<double> vf64, + }) + : _i8 = i8, + _u8 = u8, + _i16 = i16, + _u16 = u16, + _i32 = i32, + _u32 = u32, + _i64 = i64, + _u64 = u64, + _f32 = f32, + _f64 = f64, + _v8 = v8, + _vf64 = vf64; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + final int v8Offset = _v8?.isNotEmpty == true + ? fbBuilder.writeListInt8(_v8) + : null; + final int vf64Offset = _vf64?.isNotEmpty == true + ? fbBuilder.writeListFloat64(_vf64) + : null; + + fbBuilder.startTable(); + fbBuilder.addInt8(0, _i8); + fbBuilder.addUint8(1, _u8); + fbBuilder.addInt16(2, _i16); + fbBuilder.addUint16(3, _u16); + fbBuilder.addInt32(4, _i32); + fbBuilder.addUint32(5, _u32); + fbBuilder.addInt64(6, _i64); + fbBuilder.addUint64(7, _u64); + fbBuilder.addFloat32(8, _f32); + fbBuilder.addFloat64(9, _f64); + if (v8Offset != null) { + fbBuilder.addOffset(10, v8Offset); + } + if (vf64Offset != null) { + fbBuilder.addOffset(11, vf64Offset); + } + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} diff --git a/dart/test/monster_test_my_game_generated.dart b/dart/test/monster_test_my_game_generated.dart new file mode 100644 index 00000000..425bae33 --- /dev/null +++ b/dart/test/monster_test_my_game_generated.dart @@ -0,0 +1,60 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_local_variable + +library my_game; + +import 'dart:typed_data' show Uint8List; +import 'package:flat_buffers/flat_buffers.dart' as fb; + +import './monster_test_my_game.example2_generated.dart' as my_game_example2; +import './monster_test_my_game.example_generated.dart' as my_game_example; + +class InParentNamespace { + InParentNamespace._(this._bc, this._bcOffset); + factory InParentNamespace(List<int> bytes) { + fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader<InParentNamespace> reader = const _InParentNamespaceReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + + @override + String toString() { + return 'InParentNamespace{}'; + } +} + +class _InParentNamespaceReader extends fb.TableReader<InParentNamespace> { + const _InParentNamespaceReader(); + + @override + InParentNamespace createObject(fb.BufferContext bc, int offset) => + new InParentNamespace._(bc, offset); +} + +class InParentNamespaceObjectBuilder extends fb.ObjectBuilder { + + InParentNamespaceObjectBuilder(); + + /// Finish building, and store into the [fbBuilder]. + @override + int finish( + fb.Builder fbBuilder) { + assert(fbBuilder != null); + + fbBuilder.startTable(); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String fileIdentifier]) { + fb.Builder fbBuilder = new fb.Builder(); + int offset = finish(fbBuilder); + return fbBuilder.finish(offset, fileIdentifier); + } +} |