Commit 88912640 authored by Dan Field's avatar Dan Field Committed by Wouter van Oortmerssen

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
parent c43a0bef
......@@ -45,6 +45,7 @@ grpctest
grpctest.exe
snapshot.sh
tags
tests/dart_gen
tests/go_gen
tests/monsterdata_java_wire.mon
tests/monsterdata_java_wire_sp.mon
......@@ -94,3 +95,9 @@ js/flatbuffers.mjs
build.ninja
rules.ninja
.vscode
dart/.pub/
dart/.packages
dart/pubspec.lock
dart/.dart_tool/
dart/build/
dart/doc/api/
......@@ -86,6 +86,7 @@ cc_binary(
"grpc/src/compiler/schema_interface.h",
"src/flatc_main.cpp",
"src/idl_gen_cpp.cpp",
"src/idl_gen_dart.cpp",
"src/idl_gen_general.cpp",
"src/idl_gen_go.cpp",
"src/idl_gen_grpc.cpp",
......
......@@ -45,6 +45,7 @@ set(FlatBuffers_Library_SRCS
set(FlatBuffers_Compiler_SRCS
${FlatBuffers_Library_SRCS}
src/idl_gen_cpp.cpp
src/idl_gen_dart.cpp
src/idl_gen_general.cpp
src/idl_gen_go.cpp
src/idl_gen_js.cpp
......
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.
# 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
/*
* 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;
}
// 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);
}
}
// 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;
}
}
}
#!/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
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
// 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);
}
}
// 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);
}
}
// 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);
}
}
// 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);
}
}
......@@ -35,6 +35,8 @@ For any schema input files, one or more generators can be specified:
- `--grpc`: Generate RPC stub code for GRPC.
- `--dart`: Generate Dart code.
For any data input files:
- `--binary`, `-b` : If data is contained in this file, generate a
......
Use in Dart {#flatbuffers_guide_use_dart}
===========
## Before you get started
Before diving into the FlatBuffers usage in Dart, it should be noted that
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
to general FlatBuffers usage in all of the supported languages (including Dart).
This page is designed to cover the nuances of FlatBuffers usage, specific to
Dart.
You should also have read the [Building](@ref flatbuffers_guide_building)
documentation to build `flatc` and should be familiar with
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
[Writing a schema](@ref flatbuffers_guide_writing_schema).
## FlatBuffers Dart library code location
The code for the FlatBuffers Go library can be found at
`flatbuffers/dart`. You can browse the library code on the [FlatBuffers
GitHub page](https://github.com/google/flatbuffers/tree/master/dart).
## Testing the FlatBuffers Dart library
The code to test the Dart library can be found at `flatbuffers/tests`.
The test code itself is located in [dart_test.dart](https://github.com/google/
flatbuffers/blob/master/tests/dart_test.dart).
To run the tests, use the [DartTest.sh](https://github.com/google/flatbuffers/
blob/master/tests/DartTest.sh) shell script.
*Note: The shell script requires the [Dart SDK](https://www.dartlang.org/tools/sdk)
to be installed.*
## Using the FlatBuffers Dart library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in Dart.*
FlatBuffers supports reading and writing binary FlatBuffers in Dart.
To use FlatBuffers in your own code, first generate Dart classes from your
schema with the `--dart` option to `flatc`. Then you can include both FlatBuffers
and the generated code to read or write a FlatBuffer.
For example, here is how you would read a FlatBuffer binary file in Dart: First,
include the library and generated code. Then read a FlatBuffer binary file into
a `List<int>`, which you pass to the factory constructor for `Monster`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
import 'dart:io' as io;
import 'package:flat_buffers/flat_buffers.dart' as fb;
import './monster_my_game.sample_generated.dart' as myGame;
List<int> data = await new io.File('monster.dat').readAsBytes();
var monster = new myGame.Monster(data);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access values like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
var hp = monster.hp;
var pos = monster.pos;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Differences from the Dart SDK Front End flat_buffers
The work in this repository is signfiicantly based on the implementation used
internally by the Dart SDK in the front end/analyzer package. Several
significant changes have been made.
1. Support for packed boolean lists has been removed. This is not standard
in other implementations and is not compatible with them. Do note that,
like in the JavaScript implementation, __null values in boolean lists
will be treated as false__. It is also still entirely possible to pack data
in a single scalar field, but that would have to be done on the application
side.
2. The SDK implementation supports enums with regular Dart enums, which
works if enums are always indexed at 1; however, FlatBuffers does not
require that. This implementation uses specialized enum-like classes to
ensure proper mapping from FlatBuffers to Dart and other platforms.
3. The SDK implementation does not appear to support FlatBuffer structs or
vectors of structs - it treated everything as a built-in scalar or a table.
This implementation treats structs in a way that is compatible with other
non-Dart implementations, and properly handles vectors of structs. Many of
the methods prefixed with 'low' have been prepurposed to support this.
4. The SDK implementation treats int64 and uint64 as float64s. This
implementation does not. This may cause problems with JavaScript
compatibility - however, it should be possible to use the JavaScript
implementation, or to do a customized implementation that treats all 64 bit
numbers as floats. Supporting the Dart VM and Flutter was a more important
goal of this implementation. Support for 16 bit integers was also added.
5. The code generation in this offers an "ObjectBuilder", which generates code
very similar to the SDK classes that consume FlatBuffers, as well as Builder
classes, which produces code which more closely resembles the builders in
other languages. The ObjectBuilder classes are easier to use, at the cost of
additional references allocated.
## Text Parsing
There currently is no support for parsing text (Schema's and JSON) directly
from Dart, though you could use the C++ parser through Dart Native Extensions.
Please see the C++ documentation for more on text parsing (note that this is
not currently an option in Flutter - follow [this issue](https://github.com/flutter/flutter/issues/7053)
for the latest).
<br>
......@@ -18,23 +18,24 @@ In general:
NOTE: this table is a start, it needs to be extended.
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Ruby
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ----
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | WiP
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No
Reflection | Yes | No | No | No | No | No | No | Basic | No | No
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | ?
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | ?
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ?
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | ?
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | ?
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | ?
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | ?
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | ?
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ?
Primary authors (github) | gwvo | gwvo | ev*/js*| rw | rw | evanw/ev* | kr | mik* | ch* | rw
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Ruby | Dart
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ---- | ----
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | WiP | Yes
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | No
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | ? | Yes
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | ? | No
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | ?
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | ? | Yes
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | ? | Yes
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | ? | Yes
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | ? | Flutter
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | ?
Primary authors (github) | gwvo | gwvo | ev*/js*| rw | rw | evanw/ev* | kr | mik* | ch* | rw | dnfield
* ev = evolutional
* js = jonsimantov
......
......@@ -30,6 +30,7 @@ Please select your desired language for our quest:
<input type="radio" name="language" value="typescript">TypeScript</input>
<input type="radio" name="language" value="php">PHP</input>
<input type="radio" name="language" value="c">C</input>
<input type="radio" name="language" value="dart">Dart</input>
</form>
\endhtmlonly
......@@ -132,6 +133,9 @@ For your chosen language, please cross-reference with:
<div class="language-c">
[monster.c](https://github.com/dvidelabs/flatcc/blob/master/samples/monster/monster.c)
</div>
<div class="language-dart">
[example.dart](https://github.com/google/flatbuffers/blob/master/dart/example/example.dart)
</div>
## Writing the Monsters' FlatBuffer Schema
......@@ -312,6 +316,12 @@ Please be aware of the difference between `flatc` and `flatcc` tools.
flatcc/samples/monster/build.sh
~~~
</div>
<div class="language-dart">
~~~{.sh}
cd flatbuffers/sample
./../flatc --dart samples/monster.fbs
~~~
</div>
For a more complete guide to using the `flatc` compiler, please read the
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
......@@ -421,6 +431,14 @@ The first step is to import/include the library, generated files, etc.
#define c_vec_len(V) (sizeof(V)/sizeof((V)[0]))
~~~
</div>
<div class="language-dart">
~~~{.dart}
import 'package:flat_buffers/flat_buffers.dart' as fb;
// Generated by `flatc`.
import 'monster_my_game.sample_generated.dart' as myGame;
~~~
</div>
Now we are ready to start building some buffers. In order to start, we need
to create an instance of the `FlatBufferBuilder`, which will contain the buffer
......@@ -491,6 +509,15 @@ which will grow automatically if needed:
flatcc_builder_init(B);
~~~
</div>
<div class="language-dart">
~~~{.dart}
// Create the fb.Builder object that will be used by our generated builders
// Note that if you are only planning to immediately get the byte array this builder would create,
// you can use the convenience method `toBytes()` on the generated builders.
// For example, you could do something like `new myGame.MonsterBuilder(...).toBytes()`
var builder = new fb.Builder(initialSize: 1024);
~~~
</div>
After creating the `builder`, we can start serializing our data. Before we make
our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
......@@ -633,6 +660,51 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
ns(Weapon_ref_t) axe = ns(Weapon_create(B, weapon_two_name, weapon_two_damage));
~~~
</div>
<div class="language-dart">
~~~{.dart}
// The generated Builder classes work much like in other languages,
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();
// The genearted ObjectBuilder classes offer an easier to use alternative
// at the cost of requiring some additional reference allocations. If memory
// usage is critical, or if you'll be working with especially large messages
// or tables, you should prefer using the generated Builder classes.
// The following code would produce an identical buffer as above.
final String weaponOneName = "Sword";
final int weaponOneDamage = 3;
final String weaponTwoName = "Axe";
final int weaponTwoDamage = 5;
final myGame.WeaponBuilder sword = new myGame.WeaponObjectBuilder(
name: weaponOneName,
damage: weaponOneDamage,
);
final myGame.WeaponBuilder axe = new myGame.WeaponObjectBuilder(
name: weaponTwoName,
damage: weaponTwoDamage,
);
~~~
</div>
Now let's create our monster, the `orc`. For this `orc`, lets make him
`red` with rage, positioned at `(1.0, 2.0, 3.0)`, and give him
......@@ -760,6 +832,26 @@ traversal. This is generally easy to do on any tree structures.
inventory = flatbuffers_uint8_vec_create(B, treasure, c_vec_len(treasure));
~~~
</div>
<div class="language-dart">
~~~{.dart}
// 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);
// The following code should be used instead if you intend to use the
// ObjectBuilder classes:
// Serialize a name for our monster, called "Orc".
final String name = '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];
~~~
</div>
We serialized two built-in data types (`string` and `vector`) and captured
their return values. These values are offsets into the serialized data,
......@@ -863,6 +955,15 @@ offsets.
ns(Weapon_vec_ref_t) weapons = ns(Weapon_vec_end(B));
~~~
</div>
<div class="language-dart">
~~~{.dart}
// If using the Builder classes, serialize the `[sword,axe]`
final weapons = builder.writeList([sword, axe]);
// If using the ObjectBuilders, just create an array from the two `Weapon`s
final List<myGame.WeaponBuilder> weaps = [sword, axe];
~~~
</div>
<div class="language-cpp">
<br>
......@@ -943,6 +1044,25 @@ for the `path` field above:
// TBD
~~~
</div>
<div class="language-dart">
~~~{.dart}
// Using the Builder classes, you can write a list of structs like so:
// Note that the intended order should be reversed if order is important.
final vec3Builder = new myGame.Vec3Builder(builder);
vec3Builder.finish(4.0, 5.0, 6.0);
vec3Builder.finish(1.0, 2.0, 3.0);
final int path = builder.endStructVector(2); // the lenght of the vector
// Otherwise, using the ObjectBuilder classes:
// The dart implementation provides a simple interface for writing vectors
// of structs, in `writeListOfStructs`. This method takes
// `List<ObjectBuilder>` and is used by the generated builder classes.
final List<myGame.Vec3ObjectBuilder> path = [
new myGame.Vec3ObjectBuilder(x: 1.0, y: 2.0, z: 3.0),
new myGame.Vec3ObjectBuilder(x: 4.0, y: 5.0, z: 6.0)
];
~~~
</div>
We have now serialized the non-scalar components of the orc, so we
can serialize the monster itself:
......@@ -1095,6 +1215,58 @@ can serialize the monster itself:
weapons, equipped, path));
~~~
</div>
<div class="language-dart">
~~~{.dart}
// Using the Builder API:
// 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))
..addPathOffset(path)
..addColor(myGame.Color.Red);
final int orc = monster.finish();
// -Or- using the ObjectBuilder API:
// Set his hit points to 300 and his mana to 150.
final int hp = 300;
final int mana = 150;
// Note that these parameters are optional - it is not necessary to set
// all of them.
// Also note that it is not necessary to `finish` the builder helpers above
// - the generated code will automatically reuse offsets if the same object
// is used in more than one place (e.g. the axe appearing in `weapons` and
// `equipped`).
final myGame.MonsterBuilder orcBuilder = new myGame.MonsterBuilder(
name: name,
inventory: treasure,
weapons: weaps,
equippedType: myGame.EquipmentTypeId.Weapon,
equipped: axe,
path: path,
hp: hp,
mana: mana,
pos: new myGame.Vec3Builder(x: 1.0, y: 2.0, z: 3.0),
color: myGame.Color.Red,
path: [
new myGame.Vec3ObjectBuilder(x: 1.0, y: 2.0, z: 3.0),
new myGame.Vec3ObjectBuilder(x: 4.0, y: 5.0, z: 6.0)
]);
final int orc = orcBuilder.finish(builder);
~~~
</div>
Note how we create `Vec3` struct in-line in the table. Unlike tables, structs
are simple combinations of scalars that are always stored inline, just like
......@@ -1226,6 +1398,17 @@ Here is a repetition these lines, to help highlight them more clearly:
ns(Monster_equipped_Weapon_add(B, axe));
~~~
</div>
<div class="language-dart">
~~~{.dart}
// using the builder API:
..addEquippedType(myGame.EquipmentTypeId.Weapon)
..addEquippedOffset(axe)
// in the ObjectBuilder API:
equippedTypeId: myGame.EquipmentTypeId.Weapon, // Union type
equipped: axe, // Union data
~~~
</div>
After you have created your buffer, you will have the offset to the root of the
data in the `orc` variable, so you can finish the buffer by calling the
......@@ -1291,6 +1474,12 @@ appropriate `finish` method.
// Because we used `Monster_create_as_root`, we do not need a `finish` call in C`.
~~~
</div>
<div class="language-dart">
~~~{.dart}
// Call `finish()` to instruct the builder that this monster is complete.
// See the next code section, as in Dart `finish` will also return the byte array.
~~~
</div>
The buffer is now ready to be stored somewhere, sent over the network, be
compressed, or whatever you'd like to do with it. You can access the buffer
......@@ -1383,6 +1572,11 @@ like so:
flatcc_builder_clear(B);
~~~
</div>
<div class="language-dart">
~~~{.dart}
final Uint8List buf = builder.finish(orc);
~~~
</div>
Now you can write the bytes to a file, send them over the network..
**Make sure your file mode (or tranfer protocol) is set to BINARY, not text.**
......@@ -1490,6 +1684,12 @@ before:
#define ns(x) FLATBUFFERS_WRAP_NAMESPACE(MyGame_Sample, x) // Specified in the schema.
~~~
</div>
<div class="language-dart">
~~~{.dart}
import 'package:flat_buffers/flat_buffers.dart' as fb;
import './monster_my_game.sample_generated.dart' as myGame;
~~~
</div>
Then, assuming you have a buffer of bytes received from disk,
network, etc., you can create start accessing the buffer like so:
......@@ -1591,6 +1791,13 @@ won't work**
// Note: root object pointers are NOT the same as the `buffer` pointer.
~~~
</div>
<div class="language-dart">
~~~{.dart}
List<int> data = ... // the data, e.g. from file or network
// A generated factory constructor that will read the data.
myGame.Monster monster = new myGame.Monster(data);
~~~
</div>
If you look in the generated files from the schema compiler, you will see it generated
accessors for all non-`deprecated` fields. For example:
......@@ -1611,7 +1818,7 @@ accessors for all non-`deprecated` fields. For example:
</div>
<div class="language-csharp">
~~~{.cs}
// For C#, unlike other languages support by FlatBuffers, most values (except for
// For C#, unlike most other languages support by FlatBuffers, most values (except for
// vectors and unions) are available as propreties instead of asccessor methods.
var hp = monster.Hp
var mana = monster.Mana
......@@ -1660,6 +1867,15 @@ accessors for all non-`deprecated` fields. For example:
flatbuffers_string_t name = ns(Monster_name(monster));
~~~
</div>
<div class="language-dart">
~~~{.dart}
// For Dart, unlike other languages support by FlatBuffers, most values
// are available as propreties instead of asccessor methods.
var hp = monster.hp;
var mana = monster.mana;
var name = monster.name;
~~~
</div>
These should hold `300`, `150`, and `"Orc"` respectively.
......@@ -1745,6 +1961,14 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
float z = ns(Vec3_z(pos));
~~~
</div>
<div class="language-dart">
~~~{.dart}
myGame.Vec3 pos = monster.pos;
double x = pos.x;
double y = pos.y;
double z = pos.z;
~~~
</div>
`x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0`, respectively.
......@@ -1811,6 +2035,12 @@ FlatBuffers `vector`.
size_t inv_len = flatbuffers_uint8_vec_len(inv);
~~~
</div>
<div class="language-dart">
~~~{.dart}
int invLength = monster.inventory.length;
var thirdItem = monster.inventory[2];
~~~
</div>
For `vector`s of `table`s, you can access the elements like any other vector,
except your need to handle the result as a FlatBuffer `table`:
......@@ -1885,6 +2115,13 @@ except your need to handle the result as a FlatBuffer `table`:
uint16_t second_weapon_damage = ns(Weapon_damage(ns(Weapon_vec_at(weapons, 1))));
~~~
</div>
<div class="language-dart">
~~~{.dart}
int weaponsLength = monster.weapons.length;
var secondWeaponName = monster.weapons[1].name;
var secondWeaponDamage = monster.Weapons[1].damage;
~~~
</div>
Last, we can access our `Equipped` FlatBuffer `union`. Just like when we created
the `union`, we need to get both parts of the `union`: the type and the data.
......@@ -2008,6 +2245,18 @@ We can access the type to dynamically cast the data as needed (since the
}
~~~
</div>
<div class="language-dart">
~~~{.dart}
var unionType = monster.equippedType.value;
if (unionType == myGame.EquipmentTypeId.Weapon.value) {
myGame.Weapon weapon = mon.equipped as myGame.Weapon;
var weaponName = weapon.name; // "Axe"
var weaponDamage = weapon.damage; // 5
}
~~~
</div>
## Mutating FlatBuffers
......@@ -2083,6 +2332,11 @@ mutators like so:
(except in-place vector sorting is possible).>
~~~
</div>
<div class="language-dart">
~~~{.dart}
<API for mutating FlatBuffers not yet available in Dart.>
~~~
</div>
We use the somewhat verbose term `mutate` instead of `set` to indicate that this
is a special use case, not to be confused with the default way of constructing
......@@ -2192,5 +2446,8 @@ For your chosen language, see:
<div class="language-c">
[Use in C](@ref flatbuffers_guide_use_c)
</div>
<div class="language-dart">
[Use in Dart](@ref flatbuffers_guide_use_dart)
</div>
<br>
......@@ -751,6 +751,7 @@ INPUT = "FlatBuffers.md" \
"Schemas.md" \
"CppUsage.md" \
"CUsage.md" \
"DartUsage.md" \
"GoUsage.md" \
"JavaCsharpUsage.md" \
"JavaScriptUsage.md" \
......
......@@ -39,6 +39,8 @@
title="Use in PHP"/>
<tab type="user" url="@ref flatbuffers_guide_use_python"
title="Use in Python"/>
<tab type="user" url="@ref flatbuffers_guide_use_dart"
title="Use in Dart"/>
<tab type="user" url="@ref flexbuffers"
title="Schema-less version"/>
<tab type="usergroup" url="" title="gRPC">
......
......@@ -405,6 +405,7 @@ struct IDLOptions {
kBinary = 1 << 8,
kTs = 1 << 9,
kJsonSchema = 1 << 10,
kDart = 1 << 11,
kMAX
};
......@@ -767,6 +768,10 @@ extern bool GenerateCPP(const Parser &parser,
const std::string &path,
const std::string &file_name);
extern bool GenerateDart(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
// See idl_gen_js.
extern bool GenerateJS(const Parser &parser,
......@@ -823,6 +828,12 @@ extern std::string CPPMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate a make rule for the generated Dart code
// see idl_gen_dart.cpp
extern std::string DartMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate a make rule for the generated Java/C#/... files.
// See idl_gen_general.cpp.
extern std::string GeneralMakeRule(const Parser &parser,
......
#!/bin/bash
#
# 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.
#
# Note: This script runs on Mac and Linux. It requires `Node.js` to be installed
# and `flatc` to be built (using `cmake` in the root directory).
sampledir=$(cd $(dirname $BASH_SOURCE) && pwd)
rootdir=$(cd $sampledir/.. && pwd)
currentdir=$(pwd)
if [[ "$sampledir" != "$currentdir" ]]; then
echo Error: This script must be run from inside the $sampledir directory.
echo You executed it from the $currentdir directory.
exit 1
fi
cd ../dart/example
# Run `flatc`. Note: This requires you to compile using `cmake` from the
# root `/flatbuffers` directory.
if [ -e ../../flatc ]; then
../../flatc --dart ../../samples/monster.fbs
elif [ -e ../../Debug/flatc ]; then
../../Debug/flatc --dart ../../samples/monster.fbs
else
echo 'flatc' could not be found. Make sure to build FlatBuffers from the \
$rootdir directory.
exit 1
fi
echo Running the Dart sample.
# Execute the sample.
dart example.dart
# Cleanup temporary files.
git checkout monster_my_game.sample_generated.dart
cd ../../samples
......@@ -58,6 +58,9 @@ int main(int argc, const char *argv[]) {
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript", true, nullptr,
flatbuffers::IDLOptions::kJs,
"Generate JavaScript code for tables/structs", flatbuffers::JSMakeRule },
{ flatbuffers::GenerateDart, "-d", "--dart", "Dart", true, nullptr,
flatbuffers::IDLOptions::kDart,
"Generate Dart classes for tables/structs", flatbuffers::DartMakeRule },
{ flatbuffers::GenerateJS, "-T", "--ts", "TypeScript", true, nullptr,
flatbuffers::IDLOptions::kTs,
"Generate TypeScript code for tables/structs", flatbuffers::JSMakeRule },
......
/*
* Copyright 2018 Dan Field
*
* 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.
*/
// independent from idl_parser, since this code is not needed for most clients
#include <cassert>
#include <unordered_map>
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
static std::string GeneratedFileName(const std::string &path,
const std::string &file_name) {
return path + file_name + "_generated.dart";
}
namespace dart {
const std::string _kFb = "fb";
// see https://www.dartlang.org/guides/language/language-tour#keywords
// yeild*, async*, and sync* shouldn't be problems anyway but keeping them in
static const char *keywords[] = {
"abstract", "deferred", "if", "super", "as", "do",
"implements", "switch", "assert", "dynamic", "import", "sync*",
"async", "else", "in", "this", "async*", "enum",
"is", "throw", "await", "export", "library", "true",
"break", "external", "new", "try", "case", "extends",
"null", "typedef", "catch", "factory", "operator", "var",
"class", "false", "part", "void", "const", "final",
"rethrow", "while", "continue", "finally", "return", "with",
"covariant", "for", "set", "yield", "default", "get",
"static", "yield*"
};
// Iterate through all definitions we haven't generate code for (enums, structs,
// and tables) and output them to a single file.
class DartGenerator : public BaseGenerator {
public:
typedef std::unordered_map<std::string, std::string> namespace_code_map;
DartGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "."){};
// Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file.
bool generate() {
std::string code;
namespace_code_map namespace_code;
GenerateEnums(&namespace_code);
GenerateStructs(&namespace_code);
for (auto kv = namespace_code.begin(); kv != namespace_code.end(); ++kv) {
code.clear();
code = code + "// " + FlatBuffersGeneratedWarning() + "\n";
code = code +
"// ignore_for_file: unused_import, unused_field, "
"unused_local_variable\n\n";
code += "library " + kv->first + ";\n\n";
code += "import 'dart:typed_data' show Uint8List;\n";
code += "import 'package:flat_buffers/flat_buffers.dart' as " + _kFb +
";\n\n";
for (auto kv2 = namespace_code.begin(); kv2 != namespace_code.end();
++kv2) {
if (kv2->first != kv->first) {
code += "import '" +
GeneratedFileName("./", file_name_ + "_" + kv2->first) +
"' as " + ImportAliasName(kv2->first) + ";\n";
}
}
code += "\n";
code += kv->second;
if (!SaveFile(
GeneratedFileName(path_, file_name_ + "_" + kv->first).c_str(),
code, false)) {
return false;
}
}
return true;
}
private:
static std::string ImportAliasName(const std::string &ns) {
std::string ret;
ret.assign(ns);
size_t pos = ret.find(".");
while (pos != std::string::npos) {
ret.replace(pos, 1, "_");
pos = ret.find(".", pos + 1);
}
return ret;
}
static std::string BuildNamespaceName(const Namespace &ns) {
std::stringstream sstream;
std::copy(ns.components.begin(), ns.components.end() - 1,
std::ostream_iterator<std::string>(sstream, "."));
auto ret = sstream.str() + ns.components.back();
for (int i = 0; ret[i]; i++) {
auto lower = tolower(ret[i]);
if (lower != ret[i]) {
ret[i] = static_cast<char>(lower);
if (i != 0 && ret[i - 1] != '.') {
ret.insert(i, "_");
i++;
}
}
}
// std::transform(ret.begin(), ret.end(), ret.begin(), ::tolower);
return ret;
}
static std::string EscapeKeyword(const std::string &name) {
for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
if (name == keywords[i]) { return MakeCamel(name + "_", false); }
}
return MakeCamel(name, false);
}
void GenerateEnums(namespace_code_map *namespace_code) {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
auto &enum_def = **it;
GenEnum(enum_def, namespace_code); // enum_code_ptr);
}
}
void GenerateStructs(namespace_code_map *namespace_code) {
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it;
GenStruct(struct_def, namespace_code);
}
}
// Generate a documentation comment, if available.
static void GenDocComment(const std::vector<std::string> &dc,
std::string *code_ptr,
const std::string &extra_lines,
const char *indent = nullptr) {
if (dc.empty() && extra_lines.empty()) {
// Don't output empty comment blocks with 0 lines of comment content.
return;
}
auto &code = *code_ptr;
if (indent) code += indent;
for (auto it = dc.begin(); it != dc.end(); ++it) {
if (indent) code += indent;
code += "/// " + *it + "\n";
}
if (!extra_lines.empty()) {
if (!dc.empty()) {
if (indent) code += indent;
code += "///\n";
}
if (indent) code += indent;
std::string::size_type start = 0;
for (;;) {
auto end = extra_lines.find('\n', start);
if (end != std::string::npos) {
code += "/// " + extra_lines.substr(start, end - start) + "\n";
start = end + 1;
} else {
code += "/// " + extra_lines.substr(start) + "\n";
break;
}
}
}
}
static void GenDocComment(std::string *code_ptr,
const std::string &extra_lines) {
GenDocComment(std::vector<std::string>(), code_ptr, extra_lines);
}
// Generate an enum declaration and an enum string lookup table.
void GenEnum(EnumDef &enum_def, namespace_code_map *namespace_code) {
if (enum_def.generated) return;
auto ns = BuildNamespaceName(*enum_def.defined_namespace);
std::string code;
GenDocComment(enum_def.doc_comment, &code, "");
auto name = enum_def.is_union ? enum_def.name + "TypeId" : enum_def.name;
auto is_bit_flags = enum_def.attributes.Lookup("bit_flags");
code += "class " + name + " {\n";
code += " final int value;\n";
code += " const " + name + "._(this.value);\n\n";
code += " factory " + name + ".fromValue(int value) {\n";
code += " if (value == null) return null;\n";
code += " if (!values.containsKey(value)) {\n";
code +=
" throw new StateError('Invalid value $value for bit flag enum ";
code += name + "');\n";
code += " }\n";
code += " return values[value];\n";
code += " }\n\n";
// this is meaningless for bit_flags
// however, note that unlike "regular" dart enums this enum can still have
// holes.
if (!is_bit_flags) {
code += " static const int minValue = " +
NumToString(enum_def.vals.vec.front()->value) + ";\n";
code += " static const int maxValue = " +
NumToString(enum_def.vals.vec.back()->value) + ";\n";
}
code +=
" static bool containsValue(int value) =>"
" values.containsKey(value);\n\n";
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) {
auto &ev = **it;
if (!ev.doc_comment.empty()) {
if (it != enum_def.vals.vec.begin()) { code += '\n'; }
GenDocComment(ev.doc_comment, &code, "", " ");
}
code += " static const " + name + " " + ev.name + " = ";
code += "const " + name + "._(" + NumToString(ev.value) + ");\n";
}
code += " static get values => {";
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) {
auto &ev = **it;
code += NumToString(ev.value) + ": " + ev.name + ",";
}
code += "};\n\n";
code += " static const " + _kFb + ".Reader<" + name +
"> reader = const _" + name + "Reader();\n\n";
code += " @override\n";
code += " String toString() {\n";
code += " return '" + name + "{value: $value}';\n";
code += " }\n";
code += "}\n\n";
GenEnumReader(enum_def, name, &code);
(*namespace_code)[ns] += code;
}
void GenEnumReader(EnumDef &enum_def, const std::string &name,
std::string *code_ptr) {
auto &code = *code_ptr;
code += "class _" + name + "Reader extends " + _kFb + ".Reader<" + name +
"> {\n";
code += " const _" + name + "Reader();\n\n";
code += " @override\n";
code += " int get size => 1;\n\n";
code += " @override\n";
code +=
" " + name + " read(" + _kFb + ".BufferContext bc, int offset) =>\n";
code += " new " + name + ".fromValue(const " + _kFb + "." +
GenType(enum_def.underlying_type) + "Reader().read(bc, offset));\n";
code += "}\n\n";
}
static std::string GenType(const Type &type) {
switch (type.base_type) {
case BASE_TYPE_BOOL: return "Bool";
case BASE_TYPE_CHAR: return "Int8";
case BASE_TYPE_UTYPE:
case BASE_TYPE_UCHAR: return "Uint8";
case BASE_TYPE_SHORT: return "Int16";
case BASE_TYPE_USHORT: return "Uint16";
case BASE_TYPE_INT: return "Int32";
case BASE_TYPE_UINT: return "Uint32";
case BASE_TYPE_LONG: return "Int64";
case BASE_TYPE_ULONG: return "Uint64";
case BASE_TYPE_FLOAT: return "Float32";
case BASE_TYPE_DOUBLE: return "Float64";
case BASE_TYPE_STRING: return "String";
case BASE_TYPE_VECTOR: return GenType(type.VectorType());
case BASE_TYPE_STRUCT: return type.struct_def->name;
case BASE_TYPE_UNION: return type.enum_def->name + "TypeId";
default: return "Table";
}
}
std::string GenReaderTypeName(const Type &type, Namespace *current_namespace,
const FieldDef &def,
bool parent_is_vector = false) {
if (type.base_type == BASE_TYPE_BOOL) {
return "const " + _kFb + ".BoolReader()";
} else if (type.base_type == BASE_TYPE_VECTOR) {
return "const " + _kFb + ".ListReader<" +
GenDartTypeName(type.VectorType(), current_namespace, def) + ">(" +
GenReaderTypeName(type.VectorType(), current_namespace, def,
true) +
")";
} else if (type.base_type == BASE_TYPE_STRING) {
return "const " + _kFb + ".StringReader()";
}
if (IsScalar(type.base_type)) {
if (type.enum_def && parent_is_vector) {
return GenDartTypeName(type, current_namespace, def) + ".reader";
}
return "const " + _kFb + "." + GenType(type) + "Reader()";
} else {
return GenDartTypeName(type, current_namespace, def) + ".reader";
}
}
std::string GenDartTypeName(const Type &type, Namespace *current_namespace,
const FieldDef &def, bool addBuilder = false) {
if (type.enum_def) {
if (type.enum_def->is_union && type.base_type != BASE_TYPE_UNION) {
return type.enum_def->name + "TypeId";
} else if (type.enum_def->is_union) {
return "dynamic";
} else if (type.base_type != BASE_TYPE_VECTOR) {
return type.enum_def->name;
}
}
switch (type.base_type) {
case BASE_TYPE_BOOL: return "bool";
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG:
case BASE_TYPE_INT:
case BASE_TYPE_UINT:
case BASE_TYPE_SHORT:
case BASE_TYPE_USHORT:
case BASE_TYPE_CHAR:
case BASE_TYPE_UCHAR: return "int";
case BASE_TYPE_FLOAT:
case BASE_TYPE_DOUBLE: return "double";
case BASE_TYPE_STRING: return "String";
case BASE_TYPE_STRUCT:
return MaybeWrapNamespace(
type.struct_def->name + (addBuilder ? "ObjectBuilder" : ""),
current_namespace, def);
case BASE_TYPE_VECTOR:
return "List<" +
GenDartTypeName(type.VectorType(), current_namespace, def,
addBuilder) +
">";
default: assert(0); return "dynamic";
}
}
static const std::string MaybeWrapNamespace(const std::string &type_name,
Namespace *current_ns,
const FieldDef &field) {
auto curr_ns_str = BuildNamespaceName(*current_ns);
std::string field_ns_str = "";
if (field.value.type.struct_def) {
field_ns_str +=
BuildNamespaceName(*field.value.type.struct_def->defined_namespace);
} else if (field.value.type.enum_def) {
field_ns_str +=
BuildNamespaceName(*field.value.type.enum_def->defined_namespace);
}
if (field_ns_str != "" && field_ns_str != curr_ns_str) {
return ImportAliasName(field_ns_str) + "." + type_name;
} else {
return type_name;
}
}
// Generate an accessor struct with constructor for a flatbuffers struct.
void GenStruct(const StructDef &struct_def,
namespace_code_map *namespace_code) {
if (struct_def.generated) return;
auto object_namespace = BuildNamespaceName(*struct_def.defined_namespace);
std::string code;
auto object_name = struct_def.name;
// Emit constructor
GenDocComment(struct_def.doc_comment, &code, "");
auto reader_name = "_" + struct_def.name + "Reader";
auto builder_name = struct_def.name + "Builder";
auto object_builder_name = struct_def.name + "ObjectBuilder";
std::string reader_code, builder_code;
code += "class " + struct_def.name + " {\n";
code += " " + struct_def.name + "._(this._bc, this._bcOffset);\n";
if (!struct_def.fixed) {
code += " factory " + struct_def.name + "(List<int> bytes) {\n";
code += " " + _kFb + ".BufferContext rootRef = new " + _kFb +
".BufferContext.fromBytes(bytes);\n";
code += " return reader.read(rootRef, 0);\n";
code += " }\n";
}
code += "\n";
code += " static const " + _kFb + ".Reader<" + struct_def.name +
"> reader = const " + reader_name + "();\n\n";
code += " final " + _kFb + ".BufferContext _bc;\n";
code += " final int _bcOffset;\n\n";
GenImplementationGetters(struct_def, &code);
code += "}\n\n";
GenReader(struct_def, &reader_name, &reader_code);
GenBuilder(struct_def, &builder_name, &builder_code);
GenObjectBuilder(struct_def, &object_builder_name, &builder_code);
code += reader_code;
code += builder_code;
(*namespace_code)[object_namespace] += code;
}
std::string NamespaceAliasFromUnionType(const std::string &in) {
if (in.find("_") == std::string::npos) { return in; }
std::stringstream ss(in);
std::string item;
std::vector<std::string> parts;
std::string ns;
while (std::getline(ss, item, '_')) { parts.push_back(item); }
for (auto it = parts.begin(); it != parts.end() - 1; ++it) {
auto &part = *it;
for (size_t i = 0; i < part.length(); i++) {
if (i && !isdigit(part[i]) &&
part[i] == static_cast<char>(toupper(part[i]))) {
ns += "_";
ns += static_cast<char>(tolower(part[i]));
} else {
ns += static_cast<char>(tolower(part[i]));
}
}
if (it != parts.end() - 2) { ns += "_"; }
}
return ns + "." + parts.back();
}
void GenImplementationGetters(const StructDef &struct_def,
std::string *code_ptr) {
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
std::string field_name = MakeCamel(field.name, false);
std::string type_name = GenDartTypeName(
field.value.type, struct_def.defined_namespace, field, false);
GenDocComment(field.doc_comment, &code, "");
code += " " + type_name + " get " + field_name;
if (field.value.type.base_type == BASE_TYPE_UNION) {
code += " {\n";
code += " switch (" + field_name + "Type?.value) {\n";
for (auto en_it = field.value.type.enum_def->vals.vec.begin() + 1;
en_it != field.value.type.enum_def->vals.vec.end(); ++en_it) {
auto &ev = **en_it;
auto enum_name = NamespaceAliasFromUnionType(ev.name);
code += " case " + NumToString(ev.value) + ": return " +
enum_name + ".reader.vTableGet(_bc, _bcOffset, " +
NumToString(field.value.offset) + ", null);\n";
}
code += " default: return null;\n";
code += " }\n";
code += " }\n";
} else {
code += " => ";
if (field.value.type.enum_def &&
field.value.type.base_type != BASE_TYPE_VECTOR) {
code += "new " +
GenDartTypeName(field.value.type,
struct_def.defined_namespace, field) +
".fromValue(";
}
code += GenReaderTypeName(field.value.type,
struct_def.defined_namespace, field);
if (struct_def.fixed) {
code +=
".read(_bc, _bcOffset + " + NumToString(field.value.offset) + ")";
} else {
code += ".vTableGet(_bc, _bcOffset, " +
NumToString(field.value.offset) + ", ";
if (!field.value.constant.empty() && field.value.constant != "0") {
code += field.value.constant;
} else {
code += "null";
}
code += ")";
}
if (field.value.type.enum_def &&
field.value.type.base_type != BASE_TYPE_VECTOR) {
code += ")";
}
code += ";\n";
}
}
code += "\n";
code += " @override\n";
code += " String toString() {\n";
code += " return '" + struct_def.name + "{";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
code +=
MakeCamel(field.name, false) + ": $" + MakeCamel(field.name, false);
if (it != struct_def.fields.vec.end() - 1) { code += ", "; }
}
code += "}';\n";
code += " }\n";
}
void GenReader(const StructDef &struct_def, std::string *reader_name_ptr,
std::string *code_ptr) {
auto &code = *code_ptr;
auto &reader_name = *reader_name_ptr;
auto &impl_name = struct_def.name;
code += "class " + reader_name + " extends " + _kFb;
if (struct_def.fixed) {
code += ".StructReader<";
} else {
code += ".TableReader<";
}
code += impl_name + "> {\n";
code += " const " + reader_name + "();\n\n";
if (struct_def.fixed) {
code += " @override\n";
code += " int get size => " + NumToString(struct_def.bytesize) + ";\n\n";
}
code += " @override\n";
code += " " + impl_name +
" createObject(fb.BufferContext bc, int offset) => \n new " +
impl_name + "._(bc, offset);\n";
code += "}\n\n";
}
void GenBuilder(const StructDef &struct_def, std::string *builder_name_ptr,
std::string *code_ptr) {
if (struct_def.fields.vec.size() == 0) { return; }
auto &code = *code_ptr;
auto &builder_name = *builder_name_ptr;
code += "class " + builder_name + " {\n";
code += " " + builder_name + "(this.fbBuilder) {\n";
code += " assert(fbBuilder != null);\n";
code += " }\n\n";
code += " final " + _kFb + ".Builder fbBuilder;\n\n";
if (struct_def.fixed) {
StructBuilderBody(struct_def, code_ptr);
} else {
TableBuilderBody(struct_def, code_ptr);
}
code += "}\n\n";
}
void StructBuilderBody(const StructDef &struct_def, std::string *code_ptr) {
auto &code = *code_ptr;
code += " int finish(";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
if (IsStruct(field.value.type)) {
code += "fb.StructBuilder";
} else {
code += GenDartTypeName(field.value.type, struct_def.defined_namespace,
field);
}
code += " " + field.name;
if (it != struct_def.fields.vec.end() - 1) { code += ", "; }
}
code += ") {\n";
for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
if (field.padding) {
code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n";
}
if (IsStruct(field.value.type)) {
code += " " + field.name + "();\n";
} else {
code += " fbBuilder.put" + GenType(field.value.type) + "(";
code += field.name;
if (field.value.type.enum_def) { code += "?.value"; }
code += ");\n";
}
}
code += " return fbBuilder.offset;\n";
code += " }\n\n";
}
void TableBuilderBody(const StructDef &struct_def, std::string *code_ptr) {
auto &code = *code_ptr;
code += " void begin() {\n";
code += " fbBuilder.startTable();\n";
code += " }\n\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto offset = it - struct_def.fields.vec.begin();
if (IsScalar(field.value.type.base_type)) {
code += " int add" + MakeCamel(field.name) + "(";
code += GenDartTypeName(field.value.type, struct_def.defined_namespace,
field);
code += " " + MakeCamel(field.name, false) + ") {\n";
code += " fbBuilder.add" + GenType(field.value.type) + "(" +
NumToString(offset) + ", ";
code += MakeCamel(field.name, false);
if (field.value.type.enum_def) { code += "?.value"; }
code += ");\n";
} else if (IsStruct(field.value.type)) {
code += " int add" + MakeCamel(field.name) + "(int offset) {\n";
code +=
" fbBuilder.addStruct(" + NumToString(offset) + ", offset);\n";
} else {
code += " int add" + MakeCamel(field.name) + "Offset(int offset) {\n";
code +=
" fbBuilder.addOffset(" + NumToString(offset) + ", offset);\n";
}
code += " return fbBuilder.offset;\n";
code += " }\n";
}
code += "\n";
code += " int finish() {\n";
code += " return fbBuilder.endTable();\n";
code += " }\n";
}
void GenObjectBuilder(const StructDef &struct_def,
std::string *builder_name_ptr, std::string *code_ptr) {
auto &code = *code_ptr;
auto &builder_name = *builder_name_ptr;
code += "class " + builder_name + " extends " + _kFb + ".ObjectBuilder {\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
code += " final " +
GenDartTypeName(field.value.type, struct_def.defined_namespace,
field, true) +
" _" + MakeCamel(field.name, false) + ";\n";
}
code += "\n";
code += " " + builder_name + "(";
if (struct_def.fields.vec.size() != 0) {
code +=
"{\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
code += " " +
GenDartTypeName(field.value.type, struct_def.defined_namespace,
field, true) +
" " + MakeCamel(field.name, false) + ",\n";
}
code += " })\n";
code += " : ";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
code += "_" + MakeCamel(field.name, false) + " = " +
MakeCamel(field.name, false);
if (it == struct_def.fields.vec.end() - 1) {
code += ";\n\n";
} else {
code += ",\n ";
}
}
} else {
code += ");\n\n";
}
code += " /// Finish building, and store into the [fbBuilder].\n";
code += " @override\n";
code += " int finish(\n";
code += " " + _kFb + ".Builder fbBuilder) {\n";
code += " assert(fbBuilder != null);\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type))
continue;
code += " final int " + MakeCamel(field.name, false) + "Offset";
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
code +=
" = _" + MakeCamel(field.name, false) + "?.isNotEmpty == true\n";
code += " ? fbBuilder.writeList";
switch (field.value.type.VectorType().base_type) {
case BASE_TYPE_STRING:
code += "(_" + MakeCamel(field.name, false) +
".map((b) => fbBuilder.writeString(b)).toList())";
break;
case BASE_TYPE_STRUCT:
if (field.value.type.struct_def->fixed) {
code += "OfStructs(_" + MakeCamel(field.name, false) + ")";
} else {
code += "(_" + MakeCamel(field.name, false) +
".map((b) => b.getOrCreateOffset(fbBuilder)).toList())";
}
break;
default:
code += GenType(field.value.type.VectorType()) + "(_" +
MakeCamel(field.name, false);
if (field.value.type.enum_def) { code += ".map((f) => f.value)"; }
code += ")";
}
code += "\n : null;\n";
} else if (field.value.type.base_type == BASE_TYPE_STRING) {
code += " = fbBuilder.writeString(_" + field.name + ");\n";
} else {
code += " = _" + MakeCamel(field.name, false) +
"?.getOrCreateOffset(fbBuilder);\n";
}
}
code += "\n";
if (struct_def.fixed) {
StructObjectBuilderBody(struct_def, code_ptr);
} else {
TableObjectBuilderBody(struct_def, code_ptr);
}
code += " }\n\n";
code += " /// Convenience method to serialize to byte list.\n";
code += " @override\n";
code += " Uint8List toBytes([String fileIdentifier]) {\n";
code += " " + _kFb + ".Builder fbBuilder = new ";
code += _kFb + ".Builder();\n";
code += " int offset = finish(fbBuilder);\n";
code += " return fbBuilder.finish(offset, fileIdentifier);\n";
code += " }\n";
code += "}\n";
}
void StructObjectBuilderBody(const StructDef &struct_def,
std::string *code_ptr,
bool prependUnderscore = true) {
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
if (field.padding) {
code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n";
}
if (IsStruct(field.value.type)) {
code += " ";
if (prependUnderscore) { code += "_"; }
code += field.name + ".finish(fbBuilder);\n";
} else {
code += " fbBuilder.put" + GenType(field.value.type) + "(";
if (prependUnderscore) { code += "_"; }
code += field.name;
if (field.value.type.enum_def) { code += "?.value"; }
code += ");\n";
}
}
code += " return fbBuilder.offset;\n";
}
void TableObjectBuilderBody(const StructDef &struct_def,
std::string *code_ptr,
bool prependUnderscore = true) {
std::string &code = *code_ptr;
code += " fbBuilder.startTable();\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto offset = it - struct_def.fields.vec.begin();
if (IsScalar(field.value.type.base_type)) {
code += " fbBuilder.add" + GenType(field.value.type) + "(" +
NumToString(offset) + ", ";
if (prependUnderscore) { code += "_"; }
code += MakeCamel(field.name, false);
if (field.value.type.enum_def) { code += "?.value"; }
code += ");\n";
} else if (IsStruct(field.value.type)) {
code += " if (";
if (prependUnderscore) { code += "_"; }
code += MakeCamel(field.name, false) + " != null) {\n";
code += " fbBuilder.addStruct(" + NumToString(offset) + ", ";
code += "_" + MakeCamel(field.name, false) + ".finish(fbBuilder));\n";
code += " }\n";
} else {
code +=
" if (" + MakeCamel(field.name, false) + "Offset != null) {\n";
code += " fbBuilder.addOffset(" + NumToString(offset) + ", " +
MakeCamel(field.name, false) + "Offset);\n";
code += " }\n";
}
}
code += " return fbBuilder.endTable();\n";
}
};
} // namespace dart
bool GenerateDart(const Parser &parser, const std::string &path,
const std::string &file_name) {
dart::DartGenerator generator(parser, path, file_name);
return generator.generate();
}
std::string DartMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
assert(parser.opts.lang <= IDLOptions::kMAX);
auto filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
auto make_rule = GeneratedFileName(path, filebase) + ": ";
auto included_files = parser.GetIncludedFilesRecursive(file_name);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
make_rule += " " + *it;
}
return make_rule;
}
} // namespace flatbuffers
#!/bin/sh
#
# Copyright 2016 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.
pushd "$(dirname $0)" >/dev/null
command -v pub >/dev/null 2>&1 || { echo >&2 "Dart tests require `pub` but it's not installed. Aborting."; exit 1; }
command -v dart >/dev/null 2>&1 || { echo >&2 "Dart tests require dart to be in path but it's not installed. Aborting."; exit 1; }
# output required files to the dart folder so that pub will be able to
# distrubte them and more people can more easily run the dart tests
../flatc --dart -I include_test -o ../dart/test monster_test.fbs
cp monsterdata_test.mon ../dart/test
cd ../dart
# update packages
pub get
# Execute the sample.
dart test/flat_buffers_test.dart
# cleanup
rm ../dart/test/monsterdata_test.mon
\ No newline at end of file
......@@ -36,6 +36,10 @@ echo "************************ PHP:"
php phpTest.php
sh phpUnionVectorTest.sh
echo "************************ Dart:"
sh DartTest.sh
echo "************************ C:"
echo "(in a different repo)"
......
......@@ -14,8 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
../flatc --cpp --java --csharp --go --binary --python --js --ts --php --grpc --gen-mutable --reflect-names --gen-object-api --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json
../flatc --cpp --java --csharp --go --binary --python --js --ts --php --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
../flatc --cpp --java --csharp --dart --go --binary --python --js --ts --php --grpc --gen-mutable --reflect-names --gen-object-api --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json
../flatc --cpp --java --csharp --dart --go --binary --python --js --ts --php --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
../flatc --cpp --js --ts --php --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs
../flatc -b --schema --bfbs-comments -I include_test monster_test.fbs
../flatc --jsonschema --schema -I include_test monster_test.fbs
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment